@longzai-intelligence-issues/ledger 0.0.1
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 +18 -0
- package/README.md +26 -0
- package/dist/index.d.ts +2123 -0
- package/dist/index.js +78 -0
- package/dist/rolldown-runtime-BqT_7tdF.js +1 -0
- package/lzi-builder.config.ts +15 -0
- package/lzi-bun.config.ts +8 -0
- package/oxlint.config.ts +3 -0
- package/package.json +39 -0
- package/src/__tests__/close/verify-close.commands.test.ts +560 -0
- package/src/__tests__/docs-refs/docs-refs.commands.test.ts +213 -0
- package/src/__tests__/fs/mini-glob.utils.test.ts +71 -0
- package/src/__tests__/fs/walk-surface.utils.test.ts +170 -0
- package/src/__tests__/health/health.commands.test.ts +131 -0
- package/src/__tests__/lint/lint.core.test.ts +332 -0
- package/src/__tests__/numbering/numbering.commands.test.ts +194 -0
- package/src/__tests__/numbering/numbering.core.test.ts +318 -0
- package/src/__tests__/parser/guide-fixture.utils.test.ts +45 -0
- package/src/__tests__/parser/registry.parser.test.ts +316 -0
- package/src/__tests__/prompts/prompts.commands.test.ts +47 -0
- package/src/__tests__/template/issue-template.renderer.test.ts +133 -0
- package/src/close/evidence-reader.utils.ts +201 -0
- package/src/close/green-flip.commands.ts +199 -0
- package/src/close/verify-close.commands.ts +676 -0
- package/src/docs-refs/docs-refs.commands.ts +693 -0
- package/src/freeze/freeze.commands.ts +261 -0
- package/src/fs/mini-glob.utils.ts +216 -0
- package/src/fs/walk-surface.utils.ts +298 -0
- package/src/health/health.commands.ts +327 -0
- package/src/index.ts +46 -0
- package/src/lint/lint-baseline.commands.ts +147 -0
- package/src/lint/lint.core.ts +584 -0
- package/src/normalize/normalize-header.commands.ts +361 -0
- package/src/numbering/numbering.commands.ts +375 -0
- package/src/numbering/numbering.core.ts +685 -0
- package/src/parser/format.utils.ts +279 -0
- package/src/parser/guide-fixture.utils.ts +117 -0
- package/src/parser/registry.parser.ts +679 -0
- package/src/prompts/prompts.commands.ts +211 -0
- package/src/template/issue-template.renderer.ts +351 -0
- package/src/triage/triage.classify.ts +93 -0
- package/src/vault/vault.commands.ts +434 -0
- package/tsconfig/.cache/build.tsbuildinfo +1 -0
- package/tsconfig/.cache/node.tsbuildinfo +1 -0
- package/tsconfig/.cache/test.tsbuildinfo +1 -0
- package/tsconfig/app.json +13 -0
- package/tsconfig/build.json +15 -0
- package/tsconfig/node.json +12 -0
- package/tsconfig/test.json +15 -0
- package/tsconfig.json +23 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import"./rolldown-runtime-BqT_7tdF.js";import{renderBaselineRegeneratedConfig as e}from"@longzai-intelligence-issues/config";import{existsSync as t,mkdirSync as n,readFileSync as r,readdirSync as i,renameSync as a,rmSync as o,statSync as s,writeFileSync as c}from"node:fs";import{dirname as l,join as u,posix as d,resolve as f}from"node:path";import{execFileSync as p}from"node:child_process";import{createHash as m}from"node:crypto";const h=/^[0-9]{3,4}-.+\.md$/,g=/^[a-z0-9]+(?:-[a-z0-9]+)*$/,_=`状态\\*{0,2}\\s*[::]`,v=RegExp(_),ee=30,y=/[((]([^))]{4,})[))]/,te=`处置结果`,b=/(?:处置中|待回填)(?=[))::,,。;;、]|——|$)/,ne=8,re=[`证据锚点(末次通过零执行收口`,`判据执行证据(`],ie=/^```criteria\s*$/,ae=/^```\s*$/,oe=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,x=`沿革`,S=`阻塞`,se=`\\*{0,2}%s\\*{0,2}\\s*[::]`,C={red:`🔴 待处理`,yellow:`🟡 处理中`,green:`🟢 已处置`,frozen:`⚪ 已冻结`,canceled:`⚫ 已取消`},ce=/\[([0-9]{3,4})(?:-([a-z0-9-]+))?\](?:\(([^)]*)\))?/g,le=/([0-9]{3,4})-([a-z0-9-]+)\.md/;function ue(e){let t=[],n=new RegExp(ce.source,`g`),r=n.exec(e);for(;r!==null;){let i=r[1]??``,a=r[2]??null,o=r[3]??null;a===null&&o!==null&&(a=le.exec(o)?.[2]??null),t.some(e=>e.number===i&&e.slug===a)||t.push({number:i,slug:a}),r=n.exec(e)}return t}function de(e){return RegExp(`^\\*{0,2}${e}\\*{0,2}\\s*[::]`)}function w(e){return e.includes(`已冻结`)?`frozen`:e.includes(`🔴`)?`red`:e.includes(`⚫`)?`canceled`:/🟡\s*处理中/.test(e)?`yellow`:e.includes(`🟡`)?`legacy-yellow`:/🟢\s*已处置/.test(e)?`green`:e.includes(`🟢`)||e.includes(`✅`)?`legacy-green`:`unknown`}const fe=/证书指纹\s+([0-9a-f]{64})/,pe=/退出码\s*0(?!\d)|EXIT\s*=\s*0(?!\d)/i,me=/(?<![未待])全(?:绿|过|部通过)/,he=/用户[^。\n]{0,30}自验/;function T(e){let t=e.split(/\r?\n/),n=t.findIndex(e=>e.startsWith(`## `)&&e.includes(`处置结果`));if(n===-1)return``;let r=t.length;for(let e=n+1;e<t.length;e+=1)if((t[e]??``).startsWith(`## `)){r=e;break}return t.slice(n,r).join(`
|
|
2
|
+
`)}function ge(e){let t=[],n=new Set,r=0;for(let i of e.split(/\r?\n/)){if(i.trim().startsWith("```")){r=+(r===0);continue}if(r>0)continue;let e=[{kind:`certificate`,pattern:fe},{kind:`exit-zero`,pattern:pe},{kind:`all-green`,pattern:me},{kind:`adjudicated`,pattern:he}];for(let r of e)!n.has(r.kind)&&r.pattern.test(i)&&(t.push({kind:r.kind,line:i}),n.add(r.kind))}return t}function _e(e){let t=T(e);return{anchors:ge(t),dispositionText:t}}function ve(e,t){return t.find(t=>e.includes(t))??null}function ye(e){let t=y.exec(e);return t===null?null:(t[1]??``).trim()}var E=class extends Error{constructor(e,t){super(`glob 模式「${e}」非法:${t}`),this.name=`MiniGlobError`}};const be=new Set([`.`,`^`,`$`,`+`,`(`,`)`,`|`,`\\`,`]`]),xe=new Map;function Se(e){return be.has(e)?`\\${e}`:e}function Ce(e,t){let n=``,r=0;for(;r<t.length;){let i=t[r]??``;if(i===`[`)throw new E(e,`不支持字符类 [(与既有生态对齐,显式抛错不静默误配)`);if(i===`*`){let e=0;for(;(t[r+e]??``)===`*`;)e+=1;if(e>=2&&(t[r+e]??``)===`/`){n+=`(?:.*/)?`,r+=e+1;continue}if(e>=2){n+=`[\\s\\S]*`,r+=e;continue}n+=`[^/]*`,r+=1;continue}if(i===`?`){n+=`[^/]`,r+=1;continue}n+=Se(i),r+=1}return n}function we(e,t){let n=t.indexOf(`{`);if(n===-1)return Ce(e,t);let r=t.indexOf(`}`,n+1);if(r===-1)throw new E(e,`大括号未闭合`);let i=t.slice(0,n),a=t.slice(n+1,r);if(a.includes(`{`))throw new E(e,`不支持嵌套大括号`);let o=a.split(`,`),s=t.slice(r+1);return`(?:${o.map(t=>we(e,`${i}${t}${s}`)).join(`|`)})`}function Te(e){let t=xe.get(e);if(t!==void 0)return t;let n=RegExp(`^${we(e,e)}$`);return xe.set(e,n),n}function D(e,t){return Te(e).test(t)}const Ee=new Set([`*`,`?`,`{`,`}`]);function De(e){return[...e].some(e=>Ee.has(e))}function Oe(e){let t=[];for(let n of e){let e=n.split(`/`).filter(e=>e!==``).slice(0,-1),r=[``];for(let t of e){let e=/^\{([^{}]+)\}$/.exec(t);if(e!==null){let t=[];for(let n of(e[1]??``).split(`,`))De(n)?t.push(...r):t.push(...r.map(e=>ke(e,n)));r=t;continue}if(De(t))break;r=r.map(e=>ke(e,t))}t.push(...r)}let n=[...new Set(t)];return n.filter(e=>e===``||!n.some(t=>t!==e&&(t===``||e.startsWith(`${t}/`))))}function ke(e,t){return e===``?t:`${e}/${t}`}function Ae(e,t){return e.some(e=>D(e,t)||D(e,`${t}/`)||D(e,`${t}/**`))}function je(e,t){return e.some(e=>D(e,t))}function Me(e,t){return e.some(e=>e===``||t===e||t.startsWith(`${e}/`)||e.startsWith(`${t}/`))}function Ne(e,t){return e.some(e=>e===``||t.startsWith(`${e}/`))}function O(e,n,r,a,o,s){if(!t(e)){if(o)throw Error(`扫描面目录缺失:${e}(严格模式防扫描面静默缩水)`);return}let c=i(e,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name));for(let t of c){let i=n===``?t.name:`${n}/${t.name}`;if(t.isDirectory()){if(t.name===`.git`||Ae(a,i)||!Me(r,i))continue;O(u(e,t.name),i,r,a,o,s);continue}if(t.isFile()){if(je(a,i)||!Ne(r,i))continue;s.push(d.normalize(i))}}}function k(e,t,n={}){let r=[];return O(e,``,t,n.excludeGlobs??[],!1,r),r.sort((e,t)=>e.localeCompare(t))}function A(e,t={}){let n=[];return O(e,``,[``],t.excludeGlobs??[],!0,n),n.sort((e,t)=>e.localeCompare(t))}function j(e){let t=/^([0-9]{3,4})-(.+)\.md$/.exec(e);return t===null?null:{id:t[1]??``,slug:t[2]??``}}function M(e){let t=[],n=-1;return e.forEach((e,r)=>{if(n===-1){ie.test(e)&&(n=r);return}ae.test(e)&&(t.push({start:n,end:r}),n=-1)}),n!==-1&&t.push({start:n,end:-1}),t}function N(e){let t=e.split(/\r?\n/),n=M(t);if(n.length===0)throw Error("未找到 criteria 围栏块(```criteria 开栏)");if(n.length>1){let e=(n[1]?.start??0)+1;throw Error(`criteria 围栏块必须唯一:第 ${e} 行出现第二块`)}let r=n[0];if(r===void 0)throw Error("未找到 criteria 围栏块(```criteria 开栏)");if(r.end===-1)throw Error(`criteria 围栏块未闭合(第 ${r.start+1} 行开栏后无闭栏)`);let i=null,a=0,o=[];for(let e=r.start+1;e<r.end;e+=1){let n=t[e]??``,r=e+1;if(n.trim()===``||n.trimStart().startsWith(`#`))continue;if(n.startsWith(`summary:`)){let e=n.slice(8).trim();if(e===``)throw Error(`第 ${r} 行 summary 值为空(须唯一且非空)`);if(a+=1,a>1)throw Error(`第 ${r} 行 summary 重复(summary 行必须唯一)`);i=e;continue}let s=n.split(`|`);if(s.length!==4)throw Error(`第 ${r} 行判据须为四段 label|channel|cwd|command(命令含竖线须以脚本承载)`);let c=(s[0]??``).trim(),l=(s[1]??``).trim(),u=(s[2]??``).trim(),d=(s[3]??``).trim();if(c===``||l===``||u===``||d===``)throw Error(`第 ${r} 行判据存在空段(四段逐段非空)`);if(!oe.test(l))throw Error(`第 ${r} 行 channel「${l}」不合法(限字母数字起首的 [A-Za-z0-9._-])`);o.push({label:c,channel:l,cwd:u,command:d})}if(o.length===0)throw Error(`criteria 围栏块内至少一条判据(第 ${r.start+1} 行块为空)`);return{summary:i,criteria:o}}function P(e,t){let n=de(t),r=Math.min(e.length,30);for(let t=0;t<r;t+=1){let r=e[t]??``;if(n.test(r))return ue(r)}return[]}function F(e,t,n){let r=j(e);if(r===null)return null;let i=t.split(/\r?\n/),a=``;for(let e of i)if(e.startsWith(`# `)){a=e.slice(2).trim();break}let o=``,s=0,c=`unknown`,l=Math.min(i.length,30);for(let e=0;e<l;e+=1){let t=i[e]??``;if(v.test(t)){o=t.trim(),s=e+1,c=w(t);break}}let u=o===``?null:y.exec(o),d=u===null?null:(u[1]??``).trim(),f=-1;i.forEach((e,t)=>{f===-1&&e.startsWith(`## `)&&e.includes(`处置结果`)&&(f=t)});let p=!1;if(f!==-1){let e=Math.min(i.length,f+8);for(let t=f;t<e;t+=1)if(b.test(i[t]??``)){p=!0;break}}let m=re.some(e=>t.includes(e)),h=null,g=null;if(M(i).length>0)try{h=N(t)}catch(e){g=e instanceof Error?e.message:String(e)}return{id:r.id,slug:r.slug,file:e,title:a,status:c,statusLine:o,statusLineNumber:s,pendingReason:d,hasDispositionSection:f!==-1,dispositionIsPlaceholder:p,hasEvidenceAnchorBlock:m,criteria:h,criteriaError:g,historyRefs:P(i,x),blockedByRefs:P(i,S),rawContent:t,modifiedAtMs:n}}function I(e){if(!t(e))return[];let n=i(e).filter(e=>h.test(e)).sort((e,t)=>e.localeCompare(t)),a=[];for(let t of n){let n=u(e,t);try{let e=r(n,`utf8`),i=s(n).mtimeMs,o=F(t,e,i);o!==null&&a.push(o)}catch{a.push({id:j(t)?.id??``,slug:j(t)?.slug??``,file:t,title:``,status:`unknown`,statusLine:``,statusLineNumber:0,pendingReason:null,hasDispositionSection:!1,dispositionIsPlaceholder:!1,hasEvidenceAnchorBlock:!1,criteria:null,criteriaError:null,historyRefs:[],blockedByRefs:[],rawContent:``,modifiedAtMs:0})}}return a}const L=/\[([0-9]{3,4})(?:-([a-z0-9-]+))?\]/g;function R(e,t){return t.scopes.flatMap(t=>I(u(e,t.registryDir)).map(e=>({scopeKey:t.key,number:e.id,slug:e.slug})))}function Pe(e,t,n){let r=n.filter(t=>t.number===e);if(r.length===0)return{kind:`unknown`,message:`引用编号 ${e} 在全部 scope 中无命中`};if((t===null?[]:r.filter(e=>e.slug===t)).length===1)return{kind:`ok`};let i=t===null?r:r.filter(e=>e.slug.startsWith(t));return i.length===1?{kind:`ok`}:i.length===0?{kind:`unknown`,message:`引用 ${e}-${t} 在 scope 候选集中无 slug 命中(编号命中:${r.map(e=>`${e.scopeKey}/${e.number}-${e.slug}`).join(`、`)})`}:{kind:`ambiguous`,message:`引用 ${e}${t===null?``:`-${t}`} 命中不唯一——候选:${i.map(e=>`${e.scopeKey}/${e.number}-${e.slug}`).join(`、`)}(请展开完整 slug 或注明 scope)`}}function z(e){if(e.config.docs===void 0)throw Error(`配置未登记 docs 节(docs.scanRoots)——docs 引用检查显式拒绝隐式扫描面`);let t=R(e.root,e.config),n=[],i=0;for(let a of e.config.docs.scanRoots){let o=A(u(e.root,a),{excludeGlobs:e.config.docs.exclusions.map(e=>e.glob)});i+=o.length;for(let i of o){if(!e.config.docs.includeExtensions.some(e=>i.endsWith(e)))continue;let o=r(u(e.root,a,i),`utf8`),s=Le(o),c=a===``?i:`${a}/${i}`,l=new RegExp(L.source,`g`),d=l.exec(o);for(;d!==null;){let e=Pe(d[1]??``,d[2]??null,t);if(e.kind!==`ok`){let t=Re(s,d.index??0);n.push({file:c,line:t.line,column:t.column,rule:e.kind===`unknown`?`doc-ref-unknown`:`doc-ref-ambiguous`,message:e.message})}d=l.exec(o)}}}let a=new Map((e.config.docs.baseline??[]).map(e=>[`${e.file}::${e.rule}`,e]));if(e.ignoreBaseline===!0)return{violations:n,suppressed:0,scannedFiles:i};let o=[],s=0,c=new Set;for(let e of n){let t=`${e.file}::${e.rule}`;if(a.has(t)){s+=1,c.add(t);continue}o.push(e)}let l=[...a.entries()].filter(([e])=>!c.has(e)).map(([e,t])=>({file:e.split(`::`)[0]??``,line:0,column:0,rule:`baseline-stale`,message:`docs 基线条目已无对应现行违规——棘轮只许缩短,须同步删除该条目(收编指针:${t.issue})`}));return{violations:[...o,...l].sort((e,t)=>e.file.localeCompare(t.file)||e.rule.localeCompare(t.rule)),suppressed:s,scannedFiles:i}}function Fe(e){if(e.config.docs===void 0)throw Error(`配置未登记 docs 节(docs.scanRoots)——docs 修复显式拒绝隐式扫描面`);let t=R(e.root,e.config),n=[],i=[];for(let a of e.config.docs.scanRoots){let o=A(u(e.root,a),{excludeGlobs:e.config.docs.exclusions.map(e=>e.glob)});for(let s of o){if(!e.config.docs.includeExtensions.some(e=>s.endsWith(e)))continue;let o=r(u(e.root,a,s),`utf8`),l=[],d=new RegExp(L.source,`g`),f=d.exec(o);for(;f!==null;){let e=f[1]??``,n=f[2]??null;if(n!==null){let r=t.filter(t=>t.number===e&&t.slug.startsWith(n));if(r.length>1){let t=Re(Le(o),f.index??0);i.push({file:s,line:t.line,column:t.column,rule:`refused`,message:`引用 ${e}-${n} 前缀命中不唯一,无法机械归位(候选:${r.map(e=>`${e.scopeKey}/${e.number}-${e.slug}`).join(`、`)})——需人工核定`})}else r.length===1&&r[0]?.slug!==n&&l.push({start:f.index??0,end:(f.index??0)+f[0].length,replacement:`[${e}-${r[0]?.slug}]`})}f=d.exec(o)}if(l.length===0)continue;let p=o;for(let e of[...l].sort((e,t)=>t.start-e.start))p=`${p.slice(0,e.start)}${e.replacement}${p.slice(e.end)}`;e.dryRun!==!0&&p!==o?(c(u(e.root,a,s),p),n.push(s)):e.dryRun===!0&&n.push(s)}}return{fixedFiles:n,refused:i}}function Ie(t){if(t.config.docs===void 0)throw Error(`配置未登记 docs 节——无法再生 docs 基线`);if(t.issuePointer.trim()===``)return{ok:!1,error:`再生须携带非空 --issue <指针>(收编盖章)`};let n=z({root:t.root,config:t.config,ignoreBaseline:!0}).violations,r=new Set((t.config.docs.baseline??[]).map(e=>`${e.file}::${e.rule}`)),i=n.filter(e=>!r.has(`${e.file}::${e.rule}`));if(i.length>0)return{ok:!1,error:`存在 ${i.length} 项基线外新增违规,拒绝再生(先处置新增违规后再收编存量):\n${i.slice(0,10).map(e=>`${e.file}:${e.line} [${e.rule}]`).join(`
|
|
3
|
+
`)}`};let a=n.map(e=>({file:e.file,rule:e.rule,issue:t.issuePointer}));return{ok:!0,content:e(t.config,`docs`,a),entryCount:a.length}}function Le(e){let t=[0];for(let n=0;n<e.length;n+=1)e[n]===`
|
|
4
|
+
`&&t.push(n+1);return t}function Re(e,t){let n=0;for(let r=0;r<e.length&&(e[r]??0)<=t;r+=1)n=r;return{line:n+1,column:t-(e[n]??0)+1}}const ze=[{id:`issue-create-and-process`,description:`登记新问题到注册表并完成治理:范围判定、查重、门禁取号、证据先行、裁决门槛、TDD、单载体回填、verify-close 收口`,content:`# issue-create-and-process:登记新问题并完成治理
|
|
5
|
+
|
|
6
|
+
## 命令定位
|
|
7
|
+
|
|
8
|
+
输入:问题原文(用户观察/描述的现象、报错、异常)。**问题原文必须逐字保留进 issue 文档,禁止转述改写**;调用未附带问题原文时立即停止并说明缺少原文。输入是既有 issue 引用时改走 issue-process,本命令不重复登记。
|
|
9
|
+
|
|
10
|
+
两个职责顺序执行:**登记**(范围判定→查重→门禁取号→落盘骨架)→**治理**(核实→修复→测试→记账→回填)。
|
|
11
|
+
|
|
12
|
+
## 一、登记
|
|
13
|
+
|
|
14
|
+
- **范围判定先于建档**:按 lzi-issues.config.ts 的 scopes(paths 覆盖面)判定问题归属——跨项目/全局问题落全局 scope 注册表,项目/包专属问题落对应 scope;判定不了时列出全部 scope 请用户裁定。
|
|
15
|
+
- **查重先于建档**:在目标注册表目录检索主题关键词、现象特征、涉及文件名;已存在同语义 issue 时走既有更新路径(回填现象与证据),禁止重复建档。
|
|
16
|
+
- **门禁取号**:\`lzi-issues create --title <标题> --scope <key>\`(编号写入时刻确定,目录即编号命名空间);落盘后跑 \`lzi-issues numbering check --dir <注册表目录>\` 自检。禁止手工定号。
|
|
17
|
+
- 骨架即标准模板(\`lzi-issues template\`),正文四段:问题动机(原文逐字+客观证据)→现状与证据→处置方向(【1】备选方案和分析【2】推荐方案和分析)→处置结果/验证口径。
|
|
18
|
+
|
|
19
|
+
## 二、治理
|
|
20
|
+
|
|
21
|
+
- **证据先行**:现象在当前代码上复现或查证后才写入;根因经检索/调试/最小复现确认后才落盘;无法确认的如实标注「根因待治理时核实」。已被并行治理修复的,证据确认后归属写入并收口,不做重复修复。
|
|
22
|
+
- **处理原则**:长期治理、最大工作量、最佳实践——按根因根治与体系化改进取舍,不选「恰好让报错消失」的最小改动。
|
|
23
|
+
- **裁决门槛**:能自决的技术方案直接决定并执行;规格语义裁决、产品行为取舍、推翻既有裁决等重大分歧**停下**,正文提供【1】问题动机/背景【2】备选方案和分析【3】推荐方案和分析,等用户裁决。
|
|
24
|
+
- **TDD**:先写复现/定义预期的失败测试(Red),再实现(Green)、重构(Refactor)。
|
|
25
|
+
- **测试最小范围**:只运行与本次改动相关的测试文件;三层覆盖缺失则补齐。
|
|
26
|
+
- **CHANGELOG**:变更落定即时 \`bun run changelog:add -- --added|--changed|--fixed "描述" --package <pkg>\`;纯文档/注释变更不入账。
|
|
27
|
+
- **边界治理**:同类问题排查(rg 受影响链路);命中不在本期边界的、治理中新暴露的遗留——按范围**单独建档**(同样走门禁取号),禁止混入本 issue;本 issue「处置结果/验证口径」逐条写明去向。
|
|
28
|
+
- **单载体回填**:发现、决策、处置过程全部回填 issue 文档自身(状态行实时更新),禁止外写专题 records/findings。
|
|
29
|
+
- **收口**:判据全绿后 \`lzi-issues verify-close --issue <文档>\`(缺省零执行证据收口;确须真跑加 --rerun,重度命令须 --confirm-heavy,仅人类明令)。
|
|
30
|
+
- **git 全程只读**:仅 status/diff/log/show 服务于本任务;非本任务产出的文件不动。
|
|
31
|
+
|
|
32
|
+
## 收尾
|
|
33
|
+
|
|
34
|
+
状态行终态化(🟢 已处置 或如实保持 🔴/🟡 并写明原因);处置结果/验证口径回填检查清单、测试结果、遗留去向;全部变更留工作区由用户审阅提交。`,source:`builtin`},{id:`issue-process`,description:`治理既有 issue:引用唯一定位消歧、终态拦截、现状核实、治理与回填、verify-close 收口`,content:`# issue-process:治理既有 issue
|
|
35
|
+
|
|
36
|
+
## 命令定位
|
|
37
|
+
|
|
38
|
+
输入:issue 引用(完整 NNNN-slug / 纯编号 / 不完整 slug 前缀)。**引用必须唯一定位**——编号命中不唯一(历史撞号)时停止并列出候选(含 scope 与完整 slug),要求重新指定;未指定 issue 时立即停止,禁止自行挑选。
|
|
39
|
+
|
|
40
|
+
三个阶段:**读题核实**→**治理落地**→**回填归档**。
|
|
41
|
+
|
|
42
|
+
## 一、读题核实
|
|
43
|
+
|
|
44
|
+
- **终态拦截**:状态行已 🟢 的默认不处理(复审须明确要求);⚪ 已冻结的先停下(解冻须「用户裁定」)。
|
|
45
|
+
- **开工标注**:确认处理对象后状态行更新为 🟡 处理中(括注挂起原因)。
|
|
46
|
+
- **现状优先于记载**:issue 是写入时刻快照——现象、根因、涉及文件逐项在当前代码上核实;漂移时先如实修订记载再治理;已被并行治理修复的,证据确认后归属写入并收口,不重复修复。
|
|
47
|
+
|
|
48
|
+
## 二、治理落地
|
|
49
|
+
|
|
50
|
+
- 处理原则、裁决门槛、TDD、测试最小范围、CHANGELOG、边界治理、单载体回填纪律与 issue-create-and-process 完全一致。
|
|
51
|
+
- 治理中发现原方案实现层缺陷:有实证时把证据与修正方案记入「处置结果/验证口径」后继续;需变更已裁决规格语义时停下等用户裁定。
|
|
52
|
+
|
|
53
|
+
## 三、回填归档
|
|
54
|
+
|
|
55
|
+
- 状态行终态化;「处置结果/验证口径」记裁决内容(含否决备选与理由)、落地清单、检查与测试结果、遗留去向。
|
|
56
|
+
- 落地形态与登记时不一致或根因被修正:证据与修正理由写进正文,保留排查链路,禁止静默偏离。
|
|
57
|
+
- 收口走 \`lzi-issues verify-close\`(判据块 + 证据锚点;阻塞引用未全 🟢 会被门禁拒收)。`,source:`builtin`}];function Be(e){return t(e)?i(e).filter(e=>e.endsWith(`.md`)).map(t=>{let n=r(u(e,t),`utf8`),i=/^name:\s*(.+)$/m.exec(n),a=/^description:\s*(.+)$/m.exec(n);return{id:i?.[1]?.trim()??t.replace(/\.md$/,``),description:a?.[1]?.trim()??``,content:n,source:`extra`}}):[]}function Ve(e){let t=[];return e.builtin!==!1&&t.push(...ze),e.extraDir!==void 0&&t.push(...Be(e.extraDir)),[...new Map(t.map(e=>[e.id,e])).values()]}function He(e,t){return Ve(t).find(t=>t.id===e)??null}const Ue=RegExp(`(${_}\\s*)(🔴|🟡|🟢)[^\\n]*`);function B(e){let t=`🟢 已处置(${e.summary}——判据证据锚点见处置段)`,n=e.raw.replace(Ue,`$1${t}`);if(n===e.raw){if(Ue.test(e.raw))return{content:e.raw,idempotent:!0};throw Error(`状态行零命中——缺状态行的文档不得走翻绿路径(先补状态行)`)}return{content:We(n,e.evidenceBlock),idempotent:!1}}function We(e,t){if(t.trim()===``)return e;let n=e.split(/\r?\n/),r=n.findIndex(e=>e.startsWith(`## `)&&e.includes(`处置结果`));if(r===-1)return`${e.replace(/\n+$/,``)}\n\n## 四、处置结果/验证口径\n\n${t}\n`;let i=n.length;for(let e=r+1;e<n.length;e+=1)if((n[e]??``).startsWith(`## `)){i=e;break}let a=n.slice(r+1,i).join(`
|
|
58
|
+
`).replace(/\n+$/,``),o=n.slice(0,r).join(`
|
|
59
|
+
`).replace(/\n+$/,``),s=n.slice(i).join(`
|
|
60
|
+
`);return`${o}\n\n${[n[r]??``,``,a,``,t].filter(e=>e!==``).join(`
|
|
61
|
+
`)}\n\n${s.replace(/^\n+/,``)}`.replace(/\n+$/,`
|
|
62
|
+
`)}function Ge(e,t){return[`证据锚点(末次通过零执行收口,${t}):`,...e.map(e=>`- ${e}`)].join(`
|
|
63
|
+
`)}function Ke(e,t,n){return[`${e}`,``,`判据执行证据(证书化收口,${n}):`,...t.map(e=>`- ${e}`)].join(`
|
|
64
|
+
`)}function qe(e){try{return p(`git`,[`ls-files`,`--cached`,`--others`,`--exclude-standard`,`-z`],{cwd:e,maxBuffer:67108864}).toString(`utf8`).split(`\0`).filter(e=>e!==``).sort().join(`
|
|
65
|
+
`)}catch{return A(e).join(`
|
|
66
|
+
`)}}function V(e,t){let n=qe(e);return m(`sha256`).update(`${n}\nidentity:${t.command}`).digest(`hex`)}function H(e,t,n){return u(e,`.lzi`,`issues`,`vault`,`certificates`,t,`${n}.json`)}function Je(e,n,i){let a=H(e,n,i);if(!t(a))return null;try{let e=JSON.parse(r(a,`utf8`));return Ye(e)?e:null}catch{return null}}function Ye(e){if(typeof e!=`object`||!e)return!1;let t=Reflect.get(e,`fingerprint`),n=Reflect.get(e,`exitCode`);return typeof t==`string`&&typeof n==`number`}function Xe(e){let t=e.split(/\r?\n/).filter(e=>e!==``);return t.length<=16?t:[...t.slice(0,8),`……(共 ${t.length} 行)`,...t.slice(-8)]}function Ze(e){let t=e.fingerprint??V(e.root,e.criterion),n=Je(e.root,e.criterion.channel,t);if(n!==null&&n.exitCode===0)return{green:!0,reused:!0,certificate:n};let r=new Date().toISOString();try{let n=p(`/bin/sh`,[`-c`,e.criterion.command],{cwd:u(e.root,e.criterion.cwd),maxBuffer:16777216}).toString(`utf8`),i={fingerprint:t,channel:e.criterion.channel,command:e.criterion.command,cwd:e.criterion.cwd,exitCode:0,outputSummary:Xe(n),executedAt:r};return Qe(e.root,i),{green:!0,reused:!1,certificate:i}}catch(n){let i=typeof n==`object`&&n?n:{},a=Reflect.get(i,`status`),o=Reflect.get(i,`stdout`),s=Reflect.get(i,`stderr`),c={fingerprint:t,channel:e.criterion.channel,command:e.criterion.command,cwd:e.criterion.cwd,exitCode:typeof a==`number`?a:127,outputSummary:Xe(`${typeof o==`string`?o:``}\n${typeof s==`string`?s:``}`.trim()),executedAt:r};return Qe(e.root,c),{green:!1,reused:!1,certificate:c}}}function Qe(e,t){let r=H(e,t.channel,t.fingerprint);n(l(r),{recursive:!0});let i=`${r}.tmp`;c(i,`${JSON.stringify(t,null,2)}\n`),a(i,r)}function $e(e){let i=u(e,`.lzi`,`issues`,`vault`,`run.lock`);if(n(l(i),{recursive:!0}),t(i))throw Error(`已有并行真跑持锁(${i})——完成后自动释放;如为残留死锁请人工确认后删除`);return c(i,`${process.pid}\n`),{unlock:()=>{try{r(i,`utf8`).trim()===String(process.pid)&&o(i,{force:!0})}catch{return}}}}function et(e,t,n){if(n.length===0)return[];let r=I(u(e,t));return n.filter(e=>{let t=r.find(t=>t.id===e);return t===void 0||t.status!==`green`&&t.status!==`legacy-green`})}function tt(e){let t=[];for(let n of e.files)t.push(nt(e.root,e.config,n,e.summaryOverride,e.dryRun===!0));return{cases:t,succeeded:t.filter(e=>e.ok).length,gateBlocked:!1,gateMessage:``}}function nt(e,t,n,i,a){let o=u(e,n),s=``;try{s=r(o,`utf8`)}catch{return{file:n,ok:!1,message:`读档失败(文件不存在或不可读)`,idempotent:!1}}let l=F(n.split(`/`).pop()??``,s,0);if(l===null)return{file:n,ok:!1,message:`文件名不符合注册表口径`,idempotent:!1};if(l.status===`frozen`)return{file:n,ok:!1,message:`冻结案拒收(不翻绿、不回填证据——须先经 unfreeze 裁定)`,idempotent:!1};let d=ve(l.statusLine,t.close.pendingWords);if(d!==null)return{file:n,ok:!1,message:`状态行含挂起词「${d}」——诚实黄灯维持,不得收口`,idempotent:!1};if(t.close.blockingMustBeGreen){let t=et(e,n.split(`/`).slice(0,-1).join(`/`),l.blockedByRefs.map(e=>e.number));if(t.length>0)return{file:n,ok:!1,message:`「阻塞」引用未全 🟢:${t.join(`、`)}——阻塞收口门禁拒收`,idempotent:!1}}let f=_e(s);if(f.anchors.length===0)return{file:n,ok:!1,message:`处置段围栏外零绿证据锚点——不核验即翻绿红线维持(补证据或走 --rerun 真跑)`,idempotent:!1};let p=i??l.criteria?.summary??`末次通过证据收口(${l.id}):${f.anchors.length} 条绿证据锚点`,m=Ge(f.anchors.map(e=>e.line),`末次通过即收口`),h;try{h=B({raw:s,summary:p,evidenceBlock:m})}catch(e){return{file:n,ok:!1,message:e instanceof Error?e.message:String(e),idempotent:!1}}return!a&&!h.idempotent&&c(o,h.content),{file:n,ok:!0,message:h.idempotent?`已 🟢 且概要一致——幂等零变更`:`翻绿完成(${f.anchors.length} 条锚点,零执行)`,idempotent:h.idempotent}}function rt(e,t,n,r){if(!n&&e.close.fullPattern!==void 0){let n=t.filter(t=>new RegExp(e.close.fullPattern??``).test(t.command));if(n.length>0)return{blocked:!0,kind:`full`,message:`禁用级门禁:判据须 scope 定向,禁止全量(命中 ${n.length} 条:${n.map(e=>e.label).join(`、`)})——确需全量须 --allow-full-criterion 且留痕`}}if(!r&&e.close.heavyPattern!==void 0){let n=t.filter(t=>new RegExp(e.close.heavyPattern??``).test(t.command));if(n.length>0)return{blocked:!0,kind:`heavy`,message:`确认级门禁:判据含重度命令(命中 ${n.length} 条:${n.map(e=>e.label).join(`、`)})——预览未执行,确认执行须 --confirm-heavy(仅人类明令环节)`}}return{blocked:!1,kind:`none`,message:``}}function it(e){let t=[];for(let n of e.files){let i=``;try{i=r(u(e.root,n),`utf8`)}catch{continue}let a=F(n.split(`/`).pop()??``,i,0);if(a===null||a.status===`frozen`)continue;let o=[];e.criteriaFromIssue===!0&&a.criteria!==null&&o.push(...a.criteria.criteria);for(let t of e.explicitCriteria??[]){let e=t.split(`|`);e.length===4&&o.push({label:e[0]?.trim()??``,channel:e[1]?.trim()??``,cwd:e[2]?.trim()??``,command:e[3]?.trim()??``})}o.length!==0&&t.push({file:n,raw:i,criteria:o})}let n=t.flatMap(e=>e.criteria),i=rt(e.config,n,e.allowFullCriterion===!0,e.confirmHeavy===!0);if(i.blocked)return{cases:t.map(e=>({file:e.file,ok:!1,message:`门禁拦截(${i.kind}),零执行`,idempotent:!1})),succeeded:0,gateBlocked:!0,gateMessage:i.message};if(e.dryRun===!0)return{cases:t.map(e=>({file:e.file,ok:!0,message:`干跑预览(${e.criteria.length} 条判据,未执行)`,idempotent:!1})),succeeded:t.length,gateBlocked:!1,gateMessage:``};let a=$e(e.root),o=[];try{for(let n of t){let t=n.criteria.map(t=>{let n=V(e.root,t);return{criterion:t,fingerprint:n,run:Ze({root:e.root,criterion:t,fingerprint:n})}}),r=t.filter(e=>!e.run.green);if(r.length>0){o.push({file:n.file,ok:!1,message:`判据未全绿(${r.map(e=>`${e.criterion.label} 退出码 ${e.run.certificate.exitCode}`).join(`、`)})——跳过翻绿`,idempotent:!1});continue}let i=F(n.file.split(`/`).pop()??``,n.raw,0),a=e.summaryOverride??i?.criteria?.summary??`批量证书化收口(${i?.id??``}):${t.length} 条判据全绿`,s=t.map(e=>`${e.criterion.label}:证书指纹 ${e.run.certificate.fingerprint}(${e.run.reused?`复用`:`真实执行`},退出码 ${e.run.certificate.exitCode})`),l=B({raw:n.raw,summary:a,evidenceBlock:Ke(a,s,`issues:verify-close`)});l.idempotent||c(u(e.root,n.file),l.content),o.push({file:n.file,ok:!0,message:`证书化收口完成(${t.length} 条判据全绿${l.idempotent?`,幂等零变更`:``})`,idempotent:l.idempotent})}}finally{a.unlock()}return{cases:o,succeeded:o.filter(e=>e.ok).length,gateBlocked:!1,gateMessage:``}}const U=`用户裁定`;function at(e){let t=e.split(/\r?\n/),n=Math.min(t.length,30);for(let e=0;e<n;e+=1)if(v.test(t[e]??``))return{line:t[e]??``,index:e};return null}function ot(e){return e.reason.includes(`用户裁定`)?ct(e.root,e.file,e.reason,`freeze`):{ok:!1,message:`冻结属人类裁定事项:--reason 必须含「${U}」——工具拒绝形式冻结`,idempotent:!1}}function st(e){return e.note.includes(`用户裁定`)?ct(e.root,e.file,e.note,`unfreeze`):{ok:!1,message:`解冻属人类裁定事项:--note 必须含「${U}」——工具拒绝形式解冻`,idempotent:!1}}function ct(e,t,n,i){let a=``;try{a=r(u(e,t),`utf8`)}catch{return{ok:!1,message:`读档失败(文件不存在或不可读)`,idempotent:!1}}let o=at(a);if(o===null)return{ok:!1,message:`未定位到状态行——冻结/解冻拒绝写入`,idempotent:!1};if(o.line.includes(`|`))return{ok:!1,message:`状态行为复合元信息行(含 |)——拒绝整行破坏性替换,请先经 normalize-header 迁移`,idempotent:!1};let s=o.line.includes(`已冻结`);if(i===`unfreeze`&&!s)return{ok:!1,message:`非冻结案拒绝解冻(当前状态行:${o.line})`,idempotent:!1};let l=i===`freeze`?`**状态**: ⚪ 已冻结(${n}——不推进、不处置、无验证判据;如需推进须先取得「解冻」的显式裁定)`:`**状态**: 🔴 待处理(${n}——冻结解除,处置方向待重新评估)`;if(o.line===l)return{ok:!0,message:`状态行已为目标形态——幂等零变更`,idempotent:!0};let d=`${RegExp(`^(状态\\*{0,2}\\s*[::])\\s*`).exec(o.line)?.[1]??`**状态**:`} ${l.replace(/^\*\*状态\*\*:\s*/,``)}`,f=a.split(/\r?\n/);return f[o.index]=d,c(u(e,t),f.join(`
|
|
67
|
+
`)),{ok:!0,message:i===`freeze`?`已冻结(⚪)`:`已解冻恢复 🔴`,idempotent:!1}}const lt=[`真机`,`雪场`,`合作方`,`回执`,`技术支持`,`REAL_DEVICE`,`人工确认`,`环境不具备`],ut=[`在途`,`并行线`,`待并行`,`让锁`,`待落地`,`待补跑`,`待复跑`];function W(e){let t=lt.find(t=>e.rawContent.includes(t));if(t!==void 0)return{category:`B`,reason:`判据依赖环境(命中「${t}」)——诚实保持黄灯,环境具备后再收口`};let n=ut.find(t=>e.rawContent.includes(t));if(n!==void 0)return{category:`C`,reason:`被并行在途线阻断(命中「${n}」)——待在途线落地后复跑收口`};let r=e.criteria?.criteria.length??0;return{category:`A`,reason:r>0?`判据全部机器可跑(${r} 条)——verify-close 补跑收口`:`判据清单为空,需人工核对后补录 criteria 块再收口`}}function dt(e,t,n){return(n===void 0?t.scopes:t.scopes.filter(e=>n.includes(e.registryDir))).flatMap(t=>I(u(e,t.registryDir)).map(e=>({record:e,file:`${t.registryDir}/${e.file}`,registryDir:t.registryDir})))}function ft(e){let t=dt(e.root,e.config,e.dirRels),n={};for(let{record:e}of t)n[e.status]=(n[e.status]??0)+1;let r=t.filter(({record:e})=>e.status===`yellow`||e.status===`legacy-yellow`),i=r.reduce((e,{record:t})=>Math.max(e,t.modifiedAtMs),0),a={};for(let{record:e}of r){let{category:t}=W(e);a[t]=(a[t]??0)+1}return{statusCounts:n,yellowTotal:r.length,oldestYellowAgeDays:i===0?0:Math.max(0,Math.floor((Date.now()-i)/864e5)),categoryCounts:a}}function pt(e){let r=dt(e.root,e.config).filter(({record:e})=>e.status===`yellow`||e.status===`legacy-yellow`).map(({record:e,file:t})=>{let n=W(e);return{id:e.id,file:t,status:e.status,category:n.category,reason:n.reason,criteriaCommands:e.criteria?.criteria.map(e=>e.command)??[]}}),i={generatedAtMs:Date.now(),registryDirs:e.config.scopes.map(e=>e.registryDir),items:r},o=e.outDir??u(e.root,`.lzi`,`issues`,`runs`,`ledger`);n(o,{recursive:!0});let s=u(o,`triage-${i.generatedAtMs}.json`);for(;t(s)||t(`${s}.tmp`);)i.generatedAtMs+=1,s=u(o,`triage-${i.generatedAtMs}.json`);let l=`${s}.tmp`;return c(l,`${JSON.stringify(i,null,2)}\n`),a(l,s),{ledgerPath:s,ledger:i}}const mt=new Map;function ht(e,t){mt.set(e,t)}function gt(e){if(typeof e!=`object`||!e)return null;let t=Reflect.get(e,`items`);if(t===void 0)return[];if(!Array.isArray(t))return null;let n=[];for(let e of t){if(typeof e!=`object`||!e)continue;let t=Reflect.get(e,`issueId`);typeof t==`string`&&t!==``&&n.push(t)}return n}const _t=[{name:`status-line-missing`,evaluate:e=>e.status===`unknown`?`头部 30 行内未定位到状态行(状态行是处理情况的第一入口)`:null},{name:`status-line-legacy-format`,evaluate:(e,t)=>t.config.lint.strictLegacy&&(e.status===`legacy-yellow`||e.status===`legacy-green`)?`状态行为旧格式变体(${e.status})——须迁移为规范五态写法`:null},{name:`yellow-no-pending-reason`,evaluate:e=>(e.status===`yellow`||e.status===`legacy-yellow`)&&e.pendingReason===null?`黄灯(处理中)状态行须括注 ≥4 字挂起原因`:null},{name:`green-no-disposition-section`,evaluate:e=>(e.status===`green`||e.status===`legacy-green`)&&!e.hasDispositionSection?`绿灯缺少「处置结果/验证口径」段`:null},{name:`green-disposition-placeholder`,evaluate:e=>(e.status===`green`||e.status===`legacy-green`)&&e.hasDispositionSection&&e.dispositionIsPlaceholder?`处置段仍为占位形态(处置中/待回填)——禁止虚标终态`:null},{name:`green-canonical-no-evidence-block`,evaluate:e=>e.status===`green`&&e.statusLine.includes(`判据证据锚点见处置段`)&&!e.hasEvidenceAnchorBlock?`状态行声称「判据证据锚点见处置段」而证据锚点块缺席(手工翻绿识别——收口须经 verify-close)`:null},{name:`frozen-format`,evaluate:e=>e.status===`frozen`&&!/⚪\s*已冻结/.test(e.statusLine)?`冻结状态行须为「⚪ 已冻结(…)」规范形态`:null},{name:`frozen-no-adjudication-note`,evaluate:e=>e.status===`frozen`&&!e.statusLine.includes(`用户裁定`)?`冻结状态行须含「用户裁定」语(工具拒绝形式冻结)`:null},{name:`issue-slug-non-ascii`,evaluate:e=>g.test(e.slug)?null:`slug 段须为纯 ASCII kebab(小写字母/数字/连字符,禁中文与非 ASCII 字符):${e.file}`},{name:`issue-slug-contains-digit`,evaluate:(e,t)=>{if(!/\d/.test(e.slug))return null;let n=`${t.registryDir}/${e.file}`;return t.config.slugDigitAllowlist.some(e=>D(e.glob,n))?null:`slug 段含数字(白名单登记请到配置 slugDigitAllowlist):${e.file}`}},{name:`canceled-no-reason`,evaluate:e=>e.status===`canceled`&&e.pendingReason===null?`已取消(⚫)状态行须括注 ≥4 字取消原因`:null},{name:`blocking-ref-unknown`,evaluate:(e,t)=>{let n=e.blockedByRefs.filter(e=>!t.registryBasenames.has(`${e.number}.md`));return n.length>0?`「阻塞」引用的 issue 不存在:${n.map(e=>e.number).join(`、`)}`:null}},{name:`orphan-sidecar`,evaluate:(e,n)=>{let i=u(n.root,`.lzi`,`issues`,`comments`,n.scopeKey,`${e.id}.json`);if(!t(i))return null;try{let e=gt(JSON.parse(r(i,`utf8`)));if(e===null)return`评论边车结构非法(items 非数组)——孤儿判定降级为违规提示`;let t=e.filter(e=>!n.registryBasenames.has(`${e}.md`));return t.length>0?`评论边车存在孤儿引用(issue 不存在):${t.join(`、`)}`:null}catch{return`评论边车 JSON 解析失败(孤儿判定降级为违规提示)`}}}];function vt(e){let t=[..._t];for(let n of e.config.lint.rulePacks){let e=mt.get(n);e!==void 0&&t.push(...e)}let n=e.dirRels===void 0?e.config.scopes:e.config.scopes.filter(t=>e.dirRels?.includes(t.registryDir)),r=[];for(let i of n){let n=I(u(e.root,i.registryDir)),a=new Set(n.map(e=>e.file)),o={root:e.root,scopeKey:i.key,registryDir:i.registryDir,registryBasenames:a,config:e.config};for(let e of n)for(let n of t){let t=n.evaluate(e,o);t!==null&&r.push({file:`${i.registryDir}/${e.file}`,line:e.statusLineNumber,rule:n.name,message:t})}}let i=new Map(e.config.lint.baseline.map(e=>[`${e.file}::${e.rule}`,e]));if(e.ignoreBaseline===!0)return{violations:r.sort(yt),suppressed:0,baselineCount:i.size};let a=[],o=0,s=new Set;for(let e of r){let t=`${e.file}::${e.rule}`;if(i.has(t)){o+=1,s.add(t);continue}a.push(e)}let c=[...i.entries()].filter(([e])=>!s.has(e)).map(([e,t])=>({file:e.split(`::`)[0]??``,line:0,rule:`baseline-stale`,message:`基线条目已无对应现行违规——棘轮只许缩短,须同步删除该条目(收编指针:${t.issue})`}));return{violations:[...a,...c].sort(yt),suppressed:o,baselineCount:i.size}}function yt(e,t){return e.file===t.file?e.rule.localeCompare(t.rule):e.file.localeCompare(t.file)}function bt(e,n){let r=[];for(let i of n.scopes){let n=u(e,`.lzi`,`issues`,`comments`,i.key);if(!t(n))continue;let a=new Set(I(u(e,i.registryDir)).map(e=>e.id));for(let e of k(n,[``])){let t=e.split(`/`).pop()?.replace(/\.json$/,``)??``;t!==``&&!a.has(t)&&r.push({file:`.lzi/issues/comments/${i.key}/${t}.json`,line:0,rule:`orphan-sidecar`,message:`评论边车为孤儿(注册表无 ${i.registryDir}/${t}-*.md)——请联动清理`})}}return r}function xt(t){if(t.issuePointer.trim()===``)return{ok:!1,error:`再生须携带非空 --issue <指针>(收编盖章)`};let n=vt({root:t.root,config:t.config,ignoreBaseline:!0}).violations.filter(e=>e.rule!==`baseline-stale`),r=new Set(t.config.lint.baseline.map(e=>`${e.file}::${e.rule}`)),i=n.filter(e=>!r.has(`${e.file}::${e.rule}`));if(i.length>0){let e=i.slice(0,10).map(e=>`${e.file} [${e.rule}]`).join(`
|
|
68
|
+
`);return{ok:!1,error:`存在 ${i.length} 项基线外新增违规,拒绝再生(先处置新增违规后再收编存量):\n${e}`}}let a=n.map(e=>({file:e.file,rule:e.rule,issue:t.issuePointer}));return{ok:!0,content:e(t.config,`lint`,a),entryCount:a.length}}function St(e,t){return e.map(e=>({file:e.file,rule:e.rule,issue:t}))}const Ct={立案日期:10,优先级:20,严重程度:30,状态:40,处置日期:50,所属域:60};function wt(e){let t=[],n=[],r=e.length;for(let i=0;i<e.length;i+=1){let a=e[i]??``;if(a.startsWith(`## `)||a===``&&t.length>0&&i>4){r=i;break}if(a===``||a.startsWith(`# `))continue;let o=/^##\s+([^::]{1,8})\s*[::]\s*(.+)$/.exec(a);if(o!==null){t.push({key:o[1]?.trim()??``,value:o[2]?.trim()??``});continue}let s=/^(?:\*\*|- )([^*::]{1,8})(?:\*\*)?\s*[::]\s*(.+)$/.exec(a);if(s!==null){t.push({key:s[1]?.trim()??``,value:s[2]?.trim()??``});continue}if(a.startsWith(`>`)){let e=a.slice(1).split(/[||]/).map(e=>e.trim());for(let r of e){let e=/^([^::]{1,8})\s*[::]\s*(.+)$/.exec(r);e===null?n.push(r):t.push({key:e[1]?.trim()??``,value:e[2]?.trim()??``})}continue}n.push(a)}return{fields:t,residuals:n,bodyStartIndex:r}}function Tt(e,t){return Ct[e]??1e3+t}function Et(e){let t=e.split(/\r?\n/),n=wt(t);if(!n.fields.some(e=>e.key===`状态`))return{content:e,outcome:`skipped`};let r=new Map;n.fields.forEach((e,t)=>{r.has(e.key)||r.set(e.key,t)});let i=[...[...n.fields].sort((e,t)=>{let n=Tt(e.key,r.get(e.key)??0),i=Tt(t.key,r.get(t.key)??0);return n===i?0:n-i}).map(e=>`**${e.key}**: ${e.value}`),...n.residuals],a=t.findIndex((e,t)=>t>0&&e.startsWith(`# `)),o=[...t.slice(0,a===-1?1:a),``,...i,``,...t.slice(n.bodyStartIndex)].join(`
|
|
69
|
+
`);return o===e?{content:e,outcome:`unchanged`}:{content:o,outcome:`rewritten`}}function Dt(e,t){return e.fields.filter(e=>!t.includes(`**${e.key}**: ${e.value}`)).map(e=>e.key)}function Ot(e){let t=``;try{t=r(u(e.root,e.file),`utf8`)}catch{return{file:e.file,outcome:`failed`,message:`读档失败(文件不存在或不可读)`}}let n=Et(t);if(n.outcome===`skipped`)return{file:e.file,outcome:`skipped`,message:`无可识别状态行且未给 --status——灯位属语义判断,不猜灯`};if(n.outcome===`unchanged`)return{file:e.file,outcome:`unchanged`,message:`头部已是规范形态`};let i=Dt(wt(t.split(/\r?\n/)),n.content);return i.length>0?{file:e.file,outcome:`failed`,message:`零丢失守卫失败:字段 ${i.join(`、`)} 未在产物在场——不落盘`}:(c(u(e.root,e.file),n.content),{file:e.file,outcome:`rewritten`,message:`头部已迁移为规范形态`})}function G(e,t){if(t.kind===`numericPrefix`)return/^(\d+)(?=[-._ ]|$)/.exec(e)?.[1]??null;if(t.kind===`compositePrefix`)return RegExp(`^(\\d+(?:[-._ ]\\d+){${t.groups-1}})(?=[-._ ]|$)`).exec(e)?.[1]??null;if(t.kind===`numericSuffix`){let t=e.replace(/\.[^.]+$/,``);return/(\d+)$/.exec(t)?.[1]??null}return new RegExp(t.pattern).exec(e)?.groups?.key??null}function K(e){let t=/^\d+/.exec(e);return t===null?null:Number.parseInt(t[0]??``,10)}function q(e){let t=new Set;for(let n of e.basenames){let r=G(n,e.rule);r!==null&&t.add(r)}if(t.size===0)return{ok:!1,error:`该范围当前无编号文件,无法推断位数——请人工定号后落盘`};let n=``;for(let e of t)(K(e)??0)>(K(n)||0)&&(n=e);if(n===``)return{ok:!1,error:`该范围无数字前缀键,无法取号`};let r=n.length,i=new Set(e.reserved),a=0,o=0,s=(K(n)??0)+1;for(;;){let e=String(s).padStart(r,`0`);if(t.has(e)){a+=1,s+=1;continue}if(i.has(e)){o+=1,s+=1;continue}return{ok:!0,number:e,skippedOccupied:a,skippedReserved:o}}}function kt(e){let t=/^\d+[-._ ](.+)\.[^.]+$/.exec(e);return t===null?null:t[1]??``}function At(e,t){if(e.length!==t.length)return!1;let n=[...e].sort(),r=[...t].sort();return n.every((e,t)=>e===r[t])}function jt(e){let t=[],n=new Map;for(let t of e.basenames){let r=G(t,e.rule);r!==null&&n.set(r,[...n.get(r)??[],t])}let r=new Map(e.reserved.map(e=>[e.number,e.reason])),i=new Set;for(let[a,o]of n){if(o.length>=2){let n=e.allowlist.findIndex((t,n)=>!i.has(n)&&t.number===a&&At(t.files,o.map(t=>e.toRepoRelative(t))));n===-1?t.push({kind:`duplicate`,scopeKey:e.scopeKey,message:`scope「${e.scopeKey}」编号 ${a} 撞号:${o.join(`、`)}——先入库者保号,后到线顺延清偿`}):i.add(n);continue}let n=r.get(a);n!==void 0&&t.push({kind:`reservedOccupied`,scopeKey:e.scopeKey,message:`scope「${e.scopeKey}」保留号 ${a} 被占用(${o.join(`、`)};保留理由:${n}——保留号不回收复用,请让号重编`})}if([...n.keys()].some(e=>e.length>1&&e.startsWith(`0`))){let r=new Set([...n.keys()].map(e=>e.length));r.size>1&&t.push({kind:`widthInconsistent`,scopeKey:e.scopeKey,message:`scope「${e.scopeKey}」零填充位数混用(族内键长 ${[...r].sort((e,t)=>e-t).join(`/`)}):${[...n.keys()].slice(0,6).join(`、`)}`})}if(e.allowlist.forEach((r,a)=>{if(i.has(a))return;let o=r.files.filter(e=>{let t=e.split(`/`).pop()??``;return(n.get(r.number)??[]).includes(t)});t.push({kind:`allowlistStale`,scopeKey:e.scopeKey,message:`scope「${e.scopeKey}」豁免条目(${r.number},${r.status})已无对应现行撞号组——棘轮只许缩短,须同步删除该条目(登记集:${r.files.join(`、`)};磁盘现状:${o.length>0?o.join(`、`):`无`})`})}),e.slugDigitPolicy===`forbid`){let n=new Set;for(let r of e.basenames){let i=kt(r);if(i===null||i===``||!/\d/.test(i))continue;let a=e.toRepoRelative(r);e.slugDigitAllowlist.some(e=>D(e,a)?(n.add(e),!0):!1)||t.push({kind:`slugContainsDigit`,scopeKey:e.scopeKey,message:`scope「${e.scopeKey}」slug 段含数字:${r}(白名单登记请到配置 slugDigitAllowlist,逐条带理由)`})}if(e.fullMode)for(let r of e.slugDigitAllowlist)n.has(r)||t.push({kind:`slugDigitAllowlistStale`,scopeKey:`global`,message:`slug 白名单条目「${r}」在启用域内已匹配不到任何文件——棘轮只许缩短,须同步删除该条目`})}return t}function Mt(e){let t=[],n=new RegExp(e.numberishPattern),r=new Map,i=new Set;for(let t of e.files){let a=t.split(`/`).pop()??``;if(!n.test(a)||e.registryDirs.some(e=>t===e||t.startsWith(`${e}/`))||e.pending.find(e=>D(e.glob,t)?(i.add(e.glob),!0):!1)!==void 0)continue;let o=t.split(`/`).slice(0,-1).join(`/`);r.set(o,[...r.get(o)??[],a])}for(let e of[...r.keys()].sort((e,t)=>e.localeCompare(t)))t.push({kind:`coverageGap`,message:`未登记编号区:目录 ${e===``?`(仓库根)`:e} 有 ${r.get(e)?.length??0} 个编号文件未被任何 scope/pending 覆盖——${(r.get(e)??[]).join(`、`)}(请在 lzi-issues.config.ts 登记 scope 或 pending 并注明理由)`});for(let n of e.pending)i.has(n.glob)||t.push({kind:`pendingStale`,message:`pending 条目「${n.glob}」已匹配不到任何编号文件——棘轮只许缩短,须同步删除该条目(登记理由:${n.reason})`});return t}const J={kind:`numericPrefix`};function Y(e,t){return k(e,[t]).map(e=>e.split(`/`).pop()??``)}function Nt(e){let t=e.scopeKey!==void 0&&e.dirRel!==void 0,n=e.scopeKey===void 0&&e.dirRel===void 0;if(t||n)return{ok:!1,error:`取号须且仅须指定 --scope <key> 或 --dir <目录> 之一`};if(e.scopeKey!==void 0){let t=e.config.scopes.find(t=>t.key===e.scopeKey);if(t===void 0)return{ok:!1,error:`scope「${e.scopeKey}」未登记(请在 lzi-issues.config.ts 注册)`};let n=q({basenames:Y(e.root,t.registryDir),rule:J,reserved:t.numbering.reserved.map(e=>e.number)});return n.ok?{ok:!0,number:n.number,target:t.key,skippedOccupied:n.skippedOccupied,skippedReserved:n.skippedReserved}:n}let r=e.config.scopes.filter(t=>t.registryDir===e.dirRel);if(r.length===0)return{ok:!1,error:`目录「${e.dirRel}」未登记为任何 scope 的注册表(请在 lzi-issues.config.ts 注册后再取号)`};let i=[...new Set(r.flatMap(e=>e.numbering.reserved.map(e=>e.number)))],a=q({basenames:Y(e.root,e.dirRel??``),rule:J,reserved:i});return a.ok?{ok:!0,number:a.number,target:e.dirRel??``,skippedOccupied:a.skippedOccupied,skippedReserved:a.skippedReserved}:a}function Pt(e){let t=e.dirRel===void 0?e.config.scopes:e.config.scopes.filter(t=>t.registryDir===e.dirRel),n=[],r=0;for(let i of t){let t=Y(e.root,i.registryDir);r+=t.length;let a=e.dirRel===void 0?e.config.numbering.allowlist.filter(e=>e.scopeKey===i.key).map(e=>({...e,files:[...e.files]})):e.config.numbering.allowlist.filter(t=>t.scopeKey===i.key&&t.files.some(t=>t.startsWith(`${e.dirRel}/`))).map(e=>({...e,files:[...e.files]}));n.push(...jt({scopeKey:i.key,basenames:t,rule:J,reserved:i.numbering.reserved,allowlist:a,slugDigitPolicy:i.slugDigitPolicy,slugDigitAllowlist:e.config.slugDigitAllowlist.map(e=>e.glob),toRepoRelative:e=>`${i.registryDir}/${e}`,fullMode:e.dirRel===void 0}))}return{findings:n,scopeCount:t.length,scannedFiles:r}}function Ft(e){let t=[];for(let n of e.config.numbering.audit.roots)t.push(...A(u(e.root,n),{excludeGlobs:e.config.numbering.globalExclusions.map(e=>e.glob)}).map(e=>n===``?e:`${n}/${e}`));return{findings:Mt({files:t,numberishPattern:e.config.numbering.audit.numberishPattern,registryDirs:e.config.scopes.map(e=>e.registryDir),pending:e.config.numbering.audit.pending}),scannedFiles:t.length}}const X=`<!-- issue-file-format-fixture:start -->`,Z=`<!-- issue-file-format-fixture:end -->`,Q=`docs/guides/issue-file-format.md`;function It(){let e=l(f(import.meta.url.replace(`file://`,``)));for(let n=0;n<10;n+=1){let n=u(e,Q);if(t(n))return n;let r=l(e);if(r===e)break;e=r}throw Error(`未定位到格式指南:${Q}(自模块位置向上 10 层内)`)}function Lt(){return r(It(),`utf8`)}function Rt(e){let t=e.indexOf(X),n=e.indexOf(Z);if(t===-1)throw Error(`指南活样板起点标记缺席:${X}`);if(n===-1)throw Error(`指南活样板终点标记缺席:${Z}`);if(n<t)throw Error(`指南活样板标记次序颠倒(终点在起点之前)`);return e.slice(t+40,n).replace(/^\n+/,``).replace(/\n+$/,``)}const zt=[`## 一、问题动机`,``,`> <问题原文逐字记录,禁止转述改写>`,``,`客观证据(报错/复现步骤/涉及文件/日志路径):`,`- <证据>`,``].join(`
|
|
70
|
+
`),Bt=[`## 二、现状与证据`,``,`<排查链路与实证;无法确认根因时如实标注「根因待治理时核实」>`,``].join(`
|
|
71
|
+
`),Vt=[`## 三、处置方向`,``,`【1】备选方案和分析`,`- <备选>:<分析>`,``,`【2】推荐方案和分析`,`- <推荐>:<分析;能自决的直接执行,裁决类停下等用户裁定>`,``].join(`
|
|
72
|
+
`),Ht=[`## 四、处置结果/验证口径`,``,`<随治理进展回填;判据以 criteria 围栏块声明;收口由 verify-close 回填证据锚点>`,``].join(`
|
|
73
|
+
`);function $(e){return e.map(e=>e.slug?`[${e.number}](./${e.number}-${e.slug}.md)`:`[${e.number}]`).join(`;`)}function Ut(){return[`# <NNNN> - <一句话标题:问题是什么,禁笼统词>`,``,`**优先级**: <P1|P2|P3>`,`**状态**: ${C.red}`,`**立案日期**: <YYYY-MM-DD>`,`**所属域**: <scope title>`,`**来源**: <问题原文出处(用户裁定/会话记录/自动巡检 + 日期)>`,`**沿革**: <可选:前序 issue 引用,如 [0035](./0035-<slug>.md)>`,`**阻塞**: <可选:被阻塞于哪些 issue;全部 🟢 后方可收口>`,``,zt,Bt,Vt,Ht].join(`
|
|
74
|
+
`)}function Wt(e){let t=[`# ${e.number} - ${e.title}`,``,`**优先级**: ${e.priority}`,`**状态**: ${C.red}`,`**立案日期**: ${e.date}`,`**所属域**: ${e.scopeTitle}`,`**来源**: ${e.source}`];return e.historyRefs!==void 0&&e.historyRefs.length>0&&t.push(`**${x}**: ${$(e.historyRefs)}`),e.blockedByRefs!==void 0&&e.blockedByRefs.length>0&&t.push(`**${S}**: ${$(e.blockedByRefs)}`),t.push(``),[t.join(`
|
|
75
|
+
`),zt,Bt,Vt,Ht].join(`
|
|
76
|
+
`)}function Gt(){return["```criteria",`# 一行一判据:label|channel|cwd|command(四段竖线分隔,段内禁竖线)`,`# channel 限字母数字起首的 [A-Za-z0-9._-];cwd 相对仓库根;command 为退出码即判据的自动化命令`,`# summary 行唯一且非空——真跑收口 --criteria-from-issue 的机器可读载体`,`summary: 示例:单包测试全绿`,`单包测试|test|packages/demo|bun run test`,"```",``].join(`
|
|
77
|
+
`)}function Kt(e,t){return[`# ${e} issue 注册表`,``,"本目录是 lzi-issues 注册表(`NNNN-<slug>.md`,目录即编号命名空间,编号独立序列)。",``,`## 建档`,``,"- `lzi-issues create --title <标题> --scope <key>`(编号走门禁取号,禁止手工定号)","- 标准模板:`lzi-issues template`;完整格式规范:[issue-file-format]("+t+`)`,``,`## 状态行(处理情况第一入口)`,``,`- ${C.red}:待处理`,`- ${C.yellow}(须括注 ≥4 字挂起原因)`,`- ${C.green}(须处置段 + 证据锚点;收口走 \`lzi-issues verify-close\`)`,`- ${C.frozen}(仅经 \`lzi-issues freeze\`,理由须含「用户裁定」)`,`- ${C.canceled}(须括注取消原因)`,``,`## 正文四段`,``,`一、问题动机 → 二、现状与证据 → 三、处置方向(【1】备选方案和分析 / 【2】推荐方案和分析)→ 四、处置结果/验证口径`,``].join(`
|
|
78
|
+
`)}const qt=[{name:`number`,required:!0,description:`scope 内编号,4 位零填充,由编号门禁取号分配(写入时刻确定)`},{name:`slug`,required:!0,description:`ASCII kebab slug(小写字母/数字/连字符,禁中文),slug 段默认禁数字(slugDigitPolicy)`},{name:`title`,required:!0,description:`一句话标题:问题是什么,禁笼统词`},{name:`priority`,required:!0,description:`优先级,P1 | P2 | P3`},{name:`status`,required:!0,description:`状态行五态;建档固定 🔴 待处理,流转走工具(verify-close / freeze 等)`},{name:`立案日期`,required:!0,description:`YYYY-MM-DD`},{name:`所属域`,required:!0,description:`config 登记的 scope title`},{name:`来源`,required:!0,description:`问题原文出处(用户裁定 / 会话记录 / 自动巡检 + 日期)`},{name:`沿革`,required:!1,description:`前序 issue 引用,markdown 相对链接或纯编号形态`},{name:`阻塞`,required:!1,description:`被阻塞于哪些 issue;全部 🟢 后方可收口(blockingMustBeGreen 门禁)`}];export{U as ADJUDICATION_KEYWORD,g as ASCII_KEBAB_SLUG_PATTERN,S as BLOCKING_LINE_KEY,C as CANONICAL_STATUS_LABELS,_t as CORE_LINT_RULES,oe as CRITERIA_CHANNEL_PATTERN,ae as CRITERIA_FENCE_CLOSE_PATTERN,ie as CRITERIA_FENCE_OPEN_PATTERN,b as DISPOSITION_PLACEHOLDER_PATTERN,ne as DISPOSITION_PLACEHOLDER_WINDOW_LINES,te as DISPOSITION_TITLE_KEYWORD,re as EVIDENCE_ANCHOR_MARKERS,Z as GUIDE_FIXTURE_END_MARK,X as GUIDE_FIXTURE_START_MARK,x as HISTORY_LINE_KEY,J as ISSUES_KEY_RULE,Q as ISSUE_FILE_FORMAT_GUIDE_RELATIVE,ce as ISSUE_REF_TOKEN_PATTERN,se as META_LINE_PREFIX_SOURCE_TEMPLATE,E as MiniGlobError,y as PENDING_REASON_PATTERN,h as REGISTRY_FILE_PATTERN,v as STATUS_LINE_LOCATE_PATTERN,_ as STATUS_LINE_PREFIX_SOURCE,ee as STATUS_LINE_SCAN_LINES,qt as TEMPLATE_FIELDS,$e as acquireRunLock,B as applyGreenFlip,Mt as auditCoverage,de as buildMetaLineLocatePattern,H as certificatePath,W as classifyIssue,w as classifyStatusLine,Te as compileMiniGlob,V as computeCriterionFingerprint,q as computeNextNumber,St as deriveEntriesFromViolations,Oe as deriveWalkPrefixes,tt as evidenceCloseFlow,G as extractFileKey,ue as extractIssueRefTokens,kt as extractSlugSegment,Je as findCertificate,ve as findPendingWord,ot as freezeIssue,K as keyLeadingNumber,Ve as listPrompts,Lt as loadIssueFileFormatGuide,T as locateDispositionText,It as locateIssueFileFormatGuide,D as matchMiniGlob,Et as normalizeHeader,Ot as normalizeHeaderFile,N as parseCriteriaBlock,F as parseIssueDoc,j as parseRegistryFileName,_e as readEvidence,ge as readEvidenceAnchors,ye as readPendingReason,ht as registerLintRulePack,Gt as renderCriteriaBlockExample,Ge as renderEvidenceCloseBlock,Wt as renderIssueTemplate,Ut as renderIssueTemplateSkeleton,Kt as renderRegistryReadmeStub,Ke as renderRerunEvidenceBlock,it as rerunCloseFlow,rt as resolveCloseGates,Ze as runCriterionViaVault,z as runDocsCheck,Fe as runDocsFix,ft as runHealth,vt as runLint,Ft as runNumberingAudit,Pt as runNumberingCheck,Nt as runNumberingNext,pt as runTriage,Ie as runWriteDocsBaseline,xt as runWriteLintBaseline,bt as scanOrphanSidecars,I as scanRegistryDir,jt as scanScopeForFindings,He as showPrompt,Rt as sliceGuideFixtureSample,st as unfreezeIssue,k as walkFilesUnderPrefixes,A as walkFilesUnderRoots};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"node:module";export{};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineConfig } from '@longzai-intelligence-builder/esm';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 引擎包构建配置
|
|
5
|
+
*
|
|
6
|
+
* 单入口库包:index 汇出解析器、模板渲染、编号、lint、收口、引用检查、提示词全部引擎面。
|
|
7
|
+
* 引擎依赖 node:fs / node:path(纯 Node 运行时),按 baseEsmConfig 约定显式声明
|
|
8
|
+
* platform: 'node'(neutral 仅供跨运行时包使用)。
|
|
9
|
+
*/
|
|
10
|
+
export default defineConfig({
|
|
11
|
+
entry: {
|
|
12
|
+
index: 'src/index.ts',
|
|
13
|
+
},
|
|
14
|
+
platform: 'node',
|
|
15
|
+
});
|
package/oxlint.config.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@longzai-intelligence-issues/ledger",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"license": "UNLICENSED",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "lzi-builder",
|
|
16
|
+
"build:prod": "NODE_ENV=production bun run build",
|
|
17
|
+
"prepublishOnly": "bun run build:prod",
|
|
18
|
+
"typecheck": "bun run typecheck:app && bun run typecheck:node && bun run typecheck:test",
|
|
19
|
+
"typecheck:app": "lzi-tsgo typecheck tsconfig/app.json",
|
|
20
|
+
"typecheck:node": "lzi-tsgo typecheck tsconfig/node.json",
|
|
21
|
+
"typecheck:test": "lzi-tsgo typecheck tsconfig/test.json",
|
|
22
|
+
"lint": "oxlint && oxfmt --check",
|
|
23
|
+
"lint:fix": "oxlint --fix && oxfmt",
|
|
24
|
+
"test": "lzi-bun-cli test",
|
|
25
|
+
"test:watch": "lzi-bun-cli test --watch",
|
|
26
|
+
"test:coverage": "lzi-bun-cli test --coverage",
|
|
27
|
+
"clean": "lzi-dev-cli clean"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@longzai-intelligence-issues/config": "0.0.1"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@longzai-intelligence-builder/cli": "^0.2.16",
|
|
34
|
+
"@longzai-intelligence-tsgo/cli": "^0.0.1",
|
|
35
|
+
"@types/bun": "^1.4.2",
|
|
36
|
+
"@typescript/native-preview": "beta",
|
|
37
|
+
"oxlint": "^1.77.0"
|
|
38
|
+
}
|
|
39
|
+
}
|