scip-query 0.8.0 → 0.8.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/dist/cli.js +1 -1
- package/dist/postinstall.js +1 -1
- package/dist/runtime.js +1 -1
- package/package.json +1 -1
- package/skills/scip-doc-reconcile/SKILL.md +100 -0
package/dist/cli.js
CHANGED
|
@@ -716,7 +716,7 @@ ${n}`:""}`)}return JSON.parse(t.stdout)}function lu(e,t){let n=[];for(let r=0;r<
|
|
|
716
716
|
Affected consumer files:`),_.list(e.affectedConsumers,t=>` ${t.file} (${t.consumedSymbols} symbol(s))`))}var yu=hs,R=(e=>parseInt(e,10)),ui=(e=>{let t=parseInt(e,10);if(!Number.isFinite(t)||t<1)throw new Error(`Expected a positive integer, got ${e}`);return t}),sr=parseFloat,bs=parseInt;function g(e,t,n,...r){return r.length>0?{flags:e,description:t,parser:n,defaultValue:r[0]}:{flags:e,description:t,parser:n}}function x(e,t=[]){return{category:e,examples:t}}import{existsSync as Rs,mkdirSync as mR,symlinkSync as dR,readlinkSync as pR,unlinkSync as fR}from"fs";import{join as ar,dirname as Cu,resolve as Is}from"path";import{homedir as vs,platform as gR}from"os";import{fileURLToPath as hR}from"url";import{execFileSync as bu}from"child_process";import{platform as Ss,arch as lR}from"os";import{execFileSync as sR}from"child_process";import{platform as aR}from"os";var cR=aR()==="win32";function De(e){let t=cR?"where":"which";try{return sR(t,[e],{stdio:"pipe"}),!0}catch{return!1}}var Su="v0.7.0";function xs(){return De("scip")}function uR(){let e=Ss(),t=lR(),n,r,i;switch(e){case"darwin":n="darwin",i="tar.gz";break;case"linux":n="linux",i="tar.gz";break;case"win32":n="windows",i="zip";break;default:return null}switch(t){case"arm64":r="arm64";break;case"x64":r="amd64";break;default:return null}let o=`scip-${n}-${r}.${i}`;return{url:`https://github.com/sourcegraph/scip/releases/download/${Su}/${o}`,filename:o}}function Cs(){let e=uR();console.log("\nThe `scip` CLI is required but not found on PATH.\n"),Ss()==="darwin"?(console.log("Install via Homebrew:"),console.log(` brew install sourcegraph/scip/scip
|
|
717
717
|
`),console.log("Or download manually:")):console.log("Download from:"),console.log(e?` ${e.url}
|
|
718
718
|
`:` https://github.com/sourcegraph/scip/releases/tag/${Su}
|
|
719
|
-
`),console.log("After installing, ensure `scip` is on your PATH and run `scip-query reindex`.")}function xu(e){if(Ss()==="darwin"&&De("brew")){e("Installing scip CLI via Homebrew...");try{if(bu("brew",["install","sourcegraph/scip/scip"],{stdio:"inherit",timeout:3e5,env:process.env}),De("scip"))return e("Successfully installed scip CLI via Homebrew"),!0}catch(t){let n=t instanceof Error?t.message:String(t);e(`Homebrew install failed: ${n}`)}}if(De("go")){e("Installing scip CLI via go install...");try{if(bu("go",["install","github.com/sourcegraph/scip/cmd/scip@latest"],{stdio:"inherit",timeout:3e5,env:process.env}),De("scip"))return e("Successfully installed scip CLI via go install"),!0}catch(t){let n=t instanceof Error?t.message:String(t);e(`go install failed: ${n}`)}}return e("Could not auto-install scip CLI."),e("Install manually from: https://github.com/sourcegraph/scip/releases"),!1}var yR=gR()==="win32",Ds=["concrete-plan","scip-ai-cleanup","scip-explore","scip-debloat","scip-maintainability","scip-verify","scip-language-playbook"];function Ru(e={}){let t=e.quiet?()=>{}:console.log,n=hR(import.meta.url),r=Is(Cu(n),"..","skills"),i=[ar(vs(),".claude","skills"),ar(vs(),".codex","skills"),ar(vs(),".agents","skills")],o={installed:[],skipped:[],alreadyLinked:[]};for(let s of i){let a=Cu(s);if(!Rs(a))continue;mR(s,{recursive:!0});let c=bR(s);for(let l of Ds){let u=ar(r,l),m=ar(s,l);if(!Rs(u)){o.skipped.push(`${c}/${l}`);continue}if(Rs(m)){try{let d=pR(m);if(Is(d)===Is(u)){o.alreadyLinked.push(`${c}/${l}`),t(` ok: ${l} \u2192 ${c} (already linked)`);continue}}catch{o.skipped.push(`${c}/${l}`),t(` skip: ${l} \u2192 ${c} (exists, not a symlink)`);continue}fR(m)}dR(u,m,yR?"junction":"dir"),o.installed.push(`${c}/${l}`),t(` done: ${l} \u2192 ${c}`)}}return o}function bR(e){return e.includes(".codex")?"Codex":e.includes(".agents")?"Agents":"Claude"}import{existsSync as Dm}from"fs";import{execFileSync as kv}from"child_process";import{closeSync as Pv,existsSync as qs,mkdirSync as pm,mkdtempSync as Fv,openSync as Tv,readFileSync as Av,renameSync as Vs,rmSync as Ws,writeFileSync as fm}from"fs";import{basename as bi,dirname as Vt,extname as Mv,join as Xe}from"path";import SR from"better-sqlite3";import{execFileSync as xR}from"child_process";import{existsSync as CR,readdirSync as RR,readFileSync as IR}from"fs";import{extname as mi,join as Iu}from"path";function pt(e){let t=new Set((e.extensions??ec).map(o=>o.toLowerCase()));if(t.size===0)return{scanned:0,inserted:0,existing:0};if(!CR(e.dbPath))throw new Error(`SCIP SQLite database not found at ${e.dbPath}`);let n=yn(e.projectRoot),r=vR(e.projectRoot,t).filter(o=>!n.isIgnored(o)),i=new SR(e.dbPath);try{let o=NR(i,r),s=i.prepare(`INSERT OR IGNORE INTO documents (language, relative_path, position_encoding, text)
|
|
719
|
+
`),console.log("After installing, ensure `scip` is on your PATH and run `scip-query reindex`.")}function xu(e){if(Ss()==="darwin"&&De("brew")){e("Installing scip CLI via Homebrew...");try{if(bu("brew",["install","sourcegraph/scip/scip"],{stdio:"inherit",timeout:3e5,env:process.env}),De("scip"))return e("Successfully installed scip CLI via Homebrew"),!0}catch(t){let n=t instanceof Error?t.message:String(t);e(`Homebrew install failed: ${n}`)}}if(De("go")){e("Installing scip CLI via go install...");try{if(bu("go",["install","github.com/sourcegraph/scip/cmd/scip@latest"],{stdio:"inherit",timeout:3e5,env:process.env}),De("scip"))return e("Successfully installed scip CLI via go install"),!0}catch(t){let n=t instanceof Error?t.message:String(t);e(`go install failed: ${n}`)}}return e("Could not auto-install scip CLI."),e("Install manually from: https://github.com/sourcegraph/scip/releases"),!1}var yR=gR()==="win32",Ds=["concrete-plan","scip-ai-cleanup","scip-explore","scip-debloat","scip-doc-reconcile","scip-maintainability","scip-verify","scip-language-playbook"];function Ru(e={}){let t=e.quiet?()=>{}:console.log,n=hR(import.meta.url),r=Is(Cu(n),"..","skills"),i=[ar(vs(),".claude","skills"),ar(vs(),".codex","skills"),ar(vs(),".agents","skills")],o={installed:[],skipped:[],alreadyLinked:[]};for(let s of i){let a=Cu(s);if(!Rs(a))continue;mR(s,{recursive:!0});let c=bR(s);for(let l of Ds){let u=ar(r,l),m=ar(s,l);if(!Rs(u)){o.skipped.push(`${c}/${l}`);continue}if(Rs(m)){try{let d=pR(m);if(Is(d)===Is(u)){o.alreadyLinked.push(`${c}/${l}`),t(` ok: ${l} \u2192 ${c} (already linked)`);continue}}catch{o.skipped.push(`${c}/${l}`),t(` skip: ${l} \u2192 ${c} (exists, not a symlink)`);continue}fR(m)}dR(u,m,yR?"junction":"dir"),o.installed.push(`${c}/${l}`),t(` done: ${l} \u2192 ${c}`)}}return o}function bR(e){return e.includes(".codex")?"Codex":e.includes(".agents")?"Agents":"Claude"}import{existsSync as Dm}from"fs";import{execFileSync as kv}from"child_process";import{closeSync as Pv,existsSync as qs,mkdirSync as pm,mkdtempSync as Fv,openSync as Tv,readFileSync as Av,renameSync as Vs,rmSync as Ws,writeFileSync as fm}from"fs";import{basename as bi,dirname as Vt,extname as Mv,join as Xe}from"path";import SR from"better-sqlite3";import{execFileSync as xR}from"child_process";import{existsSync as CR,readdirSync as RR,readFileSync as IR}from"fs";import{extname as mi,join as Iu}from"path";function pt(e){let t=new Set((e.extensions??ec).map(o=>o.toLowerCase()));if(t.size===0)return{scanned:0,inserted:0,existing:0};if(!CR(e.dbPath))throw new Error(`SCIP SQLite database not found at ${e.dbPath}`);let n=yn(e.projectRoot),r=vR(e.projectRoot,t).filter(o=>!n.isIgnored(o)),i=new SR(e.dbPath);try{let o=NR(i,r),s=i.prepare(`INSERT OR IGNORE INTO documents (language, relative_path, position_encoding, text)
|
|
720
720
|
VALUES (?, ?, NULL, ?)`),c=i.transaction(u=>{let m=0;for(let d of u){if(o.has(d))continue;let p=IR(Iu(e.projectRoot,d),"utf-8"),h=s.run(LR(d),d,p);m+=Number(h.changes)}return m})(r),l={scanned:r.length,inserted:c,existing:r.length-c};return e.onStatus?.(`Augmented SQLite documents with ${c} auxiliary source file${c===1?"":"s"} (${l.existing} already present).`),l}finally{i.close()}}function vR(e,t){let n=DR(e,t);if(n)return n;let r=[],i=o=>{let s=o?Iu(e,o):e,a;try{a=RR(s,{withFileTypes:!0})}catch{return}for(let c of a){if(zi.has(c.name))continue;let l=o?`${o}/${c.name}`:c.name;if(c.isDirectory()){i(l);continue}t.has(mi(c.name).toLowerCase())&&r.push(l)}};return i(""),r.sort()}function DR(e,t){try{return xR("git",["-C",e,"ls-files","-co","--exclude-standard","--","."],{encoding:"utf-8",maxBuffer:26214400,stdio:["ignore","pipe","ignore"]}).split(`
|
|
721
721
|
`).filter(r=>r&&t.has(mi(r).toLowerCase())).sort()}catch{return null}}function NR(e,t){let n=new Set,r=500;for(let i=0;i<t.length;i+=r){let o=t.slice(i,i+r),s=e.prepare(`SELECT relative_path FROM documents WHERE relative_path IN (${o.map(()=>"?").join(",")})`).all(...o);for(let a of s)n.add(a.relative_path)}return n}function LR(e){return mi(e).toLowerCase()===".vue"?"vue":mi(e).replace(/^\./,"").toLowerCase()||"source"}import{execFileSync as _R}from"child_process";import{existsSync as wR,readdirSync as Du}from"fs";import{extname as Nu,join as Lu}from"path";var ER=new Set([".git",".hg",".svn",".idea",".vscode","node_modules","vendor","dist","build","target","bin","obj",".dart_tool",".gradle",".next",".venv","venv","__pycache__"]),kR=[{language:"typescript",files:["tsconfig.json","tsconfig.base.json"],extensions:[".ts",".tsx",".mts",".cts"]},{language:"rust",files:["Cargo.toml"],extensions:[".rs"]},{language:"go",files:["go.mod"],extensions:[".go"]},{language:"java",files:["pom.xml","build.gradle","build.gradle.kts"],extensions:[".java"]},{language:"kotlin",files:["build.gradle.kts"],extensions:[".kt",".kts"]},{language:"scala",files:["build.sbt"],extensions:[".scala"]},{language:"python",files:["pyproject.toml","setup.py","setup.cfg","Pipfile"],extensions:[".py",".pyi"]},{language:"ruby",files:["Gemfile"],extensions:[".rb"]},{language:"cpp",files:["compile_commands.json","CMakeLists.txt","Makefile"],extensions:[".cc",".cpp",".cxx",".hpp",".hh",".hxx"]},{language:"c",files:["compile_commands.json","CMakeLists.txt","Makefile"],extensions:[".c",".h"]},{language:"csharp",globs:["*.csproj","*.sln"],extensions:[".cs"]},{language:"vb",globs:["*.vbproj"],extensions:[".vb"]},{language:"dart",files:["pubspec.yaml"],extensions:[".dart"]},{language:"php",files:["composer.json"],extensions:[".php"]},{language:"javascript",files:["package.json"],extensions:[".js",".jsx",".mjs",".cjs"]}];function Ht(e){let t=[],n=PR(e),r=MR(e);for(let i of kR){if(FR(e,i.files)){t.push(i.language);continue}if(TR(n,i.globs)){t.push(i.language);continue}$R(r,i.extensions)&&t.push(i.language)}return t.includes("typescript")&&vu(t,"javascript"),t.includes("cpp")&&!r.has(".c")&&vu(t,"c"),t}function PR(e){try{return Du(e)}catch{return[]}}function FR(e,t){return t?.length?t.some(n=>wR(Lu(e,n))):!1}function TR(e,t){return t?.length?e.some(n=>t.some(r=>AR(n,r))):!1}function AR(e,t){if(t==="*")return!0;if(!t.includes("*"))return e===t;let[n,r]=t.split("*");return e.startsWith(n??"")&&e.endsWith(r??"")}function MR(e){let t=OR(e);if(t)return t;let n=new Set,r=[e];for(;r.length>0;){let i=r.pop();if(!i)continue;let o;try{o=Du(i,{withFileTypes:!0})}catch{continue}for(let s of o){if(s.name.startsWith(".")&&!s.name.endsWith("proj")&&!s.name.endsWith("sln")&&s.isDirectory())continue;let a=Lu(i,s.name);if(s.isDirectory()){ER.has(s.name)||r.push(a);continue}let c=Nu(s.name).toLowerCase();c&&n.add(c)}}return n}function OR(e){try{let t=_R("git",["-C",e,"ls-files","-co","--exclude-standard","--","."],{encoding:"utf-8",maxBuffer:26214400,stdio:["ignore","pipe","ignore"]}),n=new Set;for(let r of t.split(`
|
|
722
722
|
`)){if(!r)continue;let i=Nu(r).toLowerCase();i&&n.add(i)}return n}catch{return null}}function $R(e,t){return t?.length?t.some(n=>e.has(n)):!1}function vu(e,t){let n=e.indexOf(t);n!==-1&&e.splice(n,1)}import{existsSync as _u,readdirSync as jR}from"fs";import{join as Ns}from"path";var BR={typescript:{language:"typescript",indexerBinary:"scip-typescript",checkCommand:"npx scip-typescript --version",indexArgs:({outputPath:e,pnpmWorkspaces:t,indexerBinary:n})=>{let r=["index","--infer-tsconfig","--output",e,"--no-progress-bar"];return t&&r.splice(1,0,"--pnpm-workspaces"),{binary:n,args:r}},markerFiles:["tsconfig.json"],installMethods:[{label:"npm",prerequisite:"npm",binary:"npm",args:["install","-g","@sourcegraph/scip-typescript"]}],installUrl:"https://github.com/sourcegraph/scip-typescript",bundledNpmPackage:"@sourcegraph/scip-typescript"},javascript:{language:"javascript",indexerBinary:"scip-typescript",checkCommand:"npx scip-typescript --version",indexArgs:({outputPath:e,indexerBinary:t})=>({binary:t,args:["index","--infer-tsconfig","--output",e,"--no-progress-bar"]}),markerFiles:["package.json"],installMethods:[{label:"npm",prerequisite:"npm",binary:"npm",args:["install","-g","@sourcegraph/scip-typescript"]}],installUrl:"https://github.com/sourcegraph/scip-typescript",bundledNpmPackage:"@sourcegraph/scip-typescript"},java:{language:"java",indexerBinary:"scip-java",checkCommand:"scip-java --version",indexArgs:({outputPath:e})=>({binary:"scip-java",args:["index","--output",e]}),markerFiles:["pom.xml","build.gradle"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-java/releases"},scala:{language:"scala",indexerBinary:"scip-java",checkCommand:"scip-java --version",indexArgs:({outputPath:e})=>({binary:"scip-java",args:["index","--output",e]}),markerFiles:["build.sbt"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-java/releases"},kotlin:{language:"kotlin",indexerBinary:"scip-java",checkCommand:"scip-java --version",indexArgs:({outputPath:e})=>({binary:"scip-java",args:["index","--output",e]}),markerFiles:["build.gradle.kts"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-java/releases"},rust:{language:"rust",indexerBinary:"rust-analyzer",checkCommand:"rust-analyzer --version",indexArgs:({outputPath:e})=>({binary:"rust-analyzer",args:["scip",".","--output",e]}),markerFiles:["Cargo.toml"],installMethods:[{label:"rustup",prerequisite:"rustup",binary:"rustup",args:["component","add","rust-analyzer"]}],installUrl:"https://github.com/rust-lang/rust-analyzer"},python:{language:"python",indexerBinary:"scip-python-plus",binaryAliases:["scip-python"],checkCommand:"scip-python-plus --version",indexArgs:({outputPath:e,indexerBinary:t})=>({binary:t,args:["index","--output",e,"--project-name","project"]}),markerFiles:["pyproject.toml","setup.py"],installMethods:[{label:"npm",prerequisite:"npm",binary:"npm",args:["install","-g","scip-python-plus"]}],installUrl:"https://github.com/PlunderStruck/scip-python",bundledNpmPackage:"scip-python-plus"},ruby:{language:"ruby",indexerBinary:"scip-ruby",checkCommand:"scip-ruby --version",indexArgs:({indexerBinary:e})=>({binary:e,args:["--dir","."]}),defaultOutputPath:"index.scip",markerFiles:["Gemfile"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-ruby/releases"},go:{language:"go",indexerBinary:"scip-go",checkCommand:"scip-go --version",indexArgs:({outputPath:e})=>({binary:"scip-go",args:["--output",e]}),markerFiles:["go.mod"],installMethods:[{label:"go install",prerequisite:"go",binary:"go",args:["install","github.com/sourcegraph/scip-go@latest"]}],installUrl:"https://github.com/sourcegraph/scip-go"},cpp:{language:"cpp",indexerBinary:"scip-clang",checkCommand:"scip-clang --version",indexArgs:({outputPath:e})=>({binary:"scip-clang",args:["--compdb-path","compile_commands.json","--index-output-path",e]}),markerFiles:["CMakeLists.txt","Makefile"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-clang/releases"},c:{language:"c",indexerBinary:"scip-clang",checkCommand:"scip-clang --version",indexArgs:({outputPath:e})=>({binary:"scip-clang",args:["--compdb-path","compile_commands.json","--index-output-path",e]}),markerFiles:["CMakeLists.txt","Makefile"],installMethods:[],installUrl:"https://github.com/sourcegraph/scip-clang/releases"},csharp:{language:"csharp",indexerBinary:"scip-dotnet",checkCommand:"scip-dotnet --version",indexArgs:({projectRoot:e,outputPath:t})=>({binary:"scip-dotnet",args:["index",wu(e,[".sln",".csproj"])??e,"--output",t,"--working-directory",e]}),markerFiles:["*.csproj","*.sln"],installMethods:[{label:"dotnet",prerequisite:"dotnet",binary:"dotnet",args:["tool","install","--global","scip-dotnet"]}],installUrl:"https://github.com/sourcegraph/scip-dotnet/releases"},vb:{language:"vb",indexerBinary:"scip-dotnet",checkCommand:"scip-dotnet --version",indexArgs:({projectRoot:e,outputPath:t})=>({binary:"scip-dotnet",args:["index",wu(e,[".sln",".vbproj"])??e,"--output",t,"--working-directory",e]}),markerFiles:["*.vbproj","*.sln"],installMethods:[{label:"dotnet",prerequisite:"dotnet",binary:"dotnet",args:["tool","install","--global","scip-dotnet"]}],installUrl:"https://github.com/sourcegraph/scip-dotnet/releases"},dart:{language:"dart",indexerBinary:"scip-dart",checkCommand:"scip-dart --version",indexArgs:({indexerBinary:e,outputPath:t})=>({binary:e,args:["--output",t]}),markerFiles:["pubspec.yaml"],installMethods:[{label:"dart pub",prerequisite:"dart",binary:"dart",args:["pub","global","activate","scip_dart"]}],installUrl:"https://github.com/Workiva/scip-dart/releases"},php:{language:"php",indexerBinary:"scip-php",projectLocalBinaries:["vendor/davidrjenni/scip-php/bin/scip-php","vendor/bin/scip-php"],checkCommand:"scip-php --version",indexArgs:({projectRoot:e,indexerBinary:t})=>{let n=Ns(e,"vendor","bin","scip-php"),r=Ns(e,"vendor","davidrjenni","scip-php","bin","scip-php");return{binary:"php",args:["-d","error_reporting=E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED",_u(r)?r:_u(n)?n:t]}},defaultOutputPath:"index.scip",markerFiles:["composer.json"],installMethods:[],installUrl:"https://github.com/davidrjenni/scip-php/releases"}};function di(e){return BR[e]}function wu(e,t){let n;try{n=jR(e)}catch{return null}for(let r of n)if(t.some(i=>r.endsWith(i)))return Ns(e,r);return null}import{readFileSync as HR,writeFileSync as qR}from"fs";import{create as Ls}from"@bufbuild/protobuf";import{deserializeSCIP as VR,serializeSCIP as WR,DocumentSchema as UR,IndexSchema as GR,SymbolInformationSchema as JR}from"@c4312/scip";function zR(e){if(e.length===0)throw new Error("Cannot merge zero SCIP indexes");if(e.length===1)return e[0];let t=QR(e),n=KR(e.flatMap(i=>i.documents??[])),r=ku(e.flatMap(i=>i.externalSymbols??[]));return Ls(GR,{metadata:t,documents:n,externalSymbols:r})}function Eu(e,t){if(e.length===0)throw new Error("Cannot merge zero SCIP files");let n=e.map(i=>VR(HR(i))),r=zR(n);return qR(t,Buffer.from(WR(r))),{documentCount:r.documents.length,externalSymbolCount:r.externalSymbols.length,inputCount:e.length}}function QR(e){let t=e[0]?.metadata;if(!t)return;let n=t.projectRoot;for(let r of e.slice(1)){let i=r.metadata?.projectRoot;if(n&&i&&i!==n)throw new Error(`Cannot merge SCIP indexes with different project roots: ${n} vs ${i}`)}return t}function KR(e){let t=new Map;for(let n of e){let r=t.get(n.relativePath);if(!r){t.set(n.relativePath,n);continue}t.set(n.relativePath,Ls(UR,{language:r.language||n.language,relativePath:r.relativePath||n.relativePath,occurrences:[...r.occurrences,...n.occurrences],symbols:ku([...r.symbols,...n.symbols]),text:XR(r.text,n.text),positionEncoding:r.positionEncoding||n.positionEncoding}))}return[...t.values()]}function ku(e){let t=new Map;for(let n of e){let r=t.get(n.symbol);if(!r){t.set(n.symbol,n);continue}t.set(n.symbol,Ls(JR,{symbol:r.symbol,documentation:ZR([...r.documentation,...n.documentation]),relationships:YR([...r.relationships,...n.relationships]),kind:r.kind||n.kind,displayName:r.displayName||n.displayName,enclosingSymbol:r.enclosingSymbol||n.enclosingSymbol,signatureDocumentation:r.signatureDocumentation??n.signatureDocumentation}))}return[...t.values()]}function YR(e){let t=new Set,n=[];for(let r of e){let i=[r.symbol,r.isReference?"1":"0",r.isImplementation?"1":"0",r.isTypeDefinition?"1":"0",r.isDefinition?"1":"0"].join("|");t.has(i)||(t.add(i),n.push(r))}return n}function XR(e,t){return e?t?e.length>=t.length?e:t:e:t}function ZR(e){return[...new Set(e)]}import{execFileSync as eI}from"child_process";import{createHash as tI}from"crypto";import{readdirSync as nI,readFileSync as rI}from"fs";import{join as Pu}from"path";function iI(e){return(oI(e)??sI(e)).filter(t=>t&&!Fu(t)).sort()}function pi(e){return iI(e).map(t=>{let n=Pu(e,t);try{let r=rI(n);return{path:t,size:r.byteLength,hash:tI("sha256").update(r).digest("hex")}}catch{return{path:t,size:-1,hash:"unreadable"}}})}function oI(e){try{return eI("git",["-C",e,"ls-files","-co","--exclude-standard","--","."],{encoding:"utf-8",maxBuffer:50*1024*1024,stdio:["ignore","pipe","ignore"]}).split(`
|
package/dist/postinstall.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{b as k,c as g,d as f,e as m}from"./chunk-LWYIGRHR.js";import{existsSync as p,mkdirSync as L,symlinkSync as v,readlinkSync as b,unlinkSync as C}from"fs";import{join as s,dirname as S,resolve as d}from"path";import{homedir as u,platform as q}from"os";import{fileURLToPath as N}from"url";var R=q()==="win32",T=["concrete-plan","scip-ai-cleanup","scip-explore","scip-debloat","scip-maintainability","scip-verify","scip-language-playbook"];function A(n={}){let e=n.quiet?()=>{}:console.log,o=N(import.meta.url),I=d(S(o),"..","skills"),$=[s(u(),".claude","skills"),s(u(),".codex","skills"),s(u(),".agents","skills")],
|
|
2
|
+
import{b as k,c as g,d as f,e as m}from"./chunk-LWYIGRHR.js";import{existsSync as p,mkdirSync as L,symlinkSync as v,readlinkSync as b,unlinkSync as C}from"fs";import{join as s,dirname as S,resolve as d}from"path";import{homedir as u,platform as q}from"os";import{fileURLToPath as N}from"url";var R=q()==="win32",T=["concrete-plan","scip-ai-cleanup","scip-explore","scip-debloat","scip-doc-reconcile","scip-maintainability","scip-verify","scip-language-playbook"];function A(n={}){let e=n.quiet?()=>{}:console.log,o=N(import.meta.url),I=d(S(o),"..","skills"),$=[s(u(),".claude","skills"),s(u(),".codex","skills"),s(u(),".agents","skills")],t={installed:[],skipped:[],alreadyLinked:[]};for(let r of $){let h=S(r);if(!p(h))continue;L(r,{recursive:!0});let l=j(r);for(let i of T){let a=s(I,i),c=s(r,i);if(!p(a)){t.skipped.push(`${l}/${i}`);continue}if(p(c)){try{let x=b(c);if(d(x)===d(a)){t.alreadyLinked.push(`${l}/${i}`),e(` ok: ${i} \u2192 ${l} (already linked)`);continue}}catch{t.skipped.push(`${l}/${i}`),e(` skip: ${i} \u2192 ${l} (exists, not a symlink)`);continue}C(c)}v(a,c,R?"junction":"dir"),t.installed.push(`${l}/${i}`),e(` done: ${i} \u2192 ${l}`)}}return t}function j(n){return n.includes(".codex")?"Codex":n.includes(".agents")?"Agents":"Claude"}function y(){console.log("scip-query: installing skills...");let n=A({quiet:!1});if(n.installed.length+n.alreadyLinked.length>0&&console.log(`
|
|
3
3
|
${n.installed.length} skill(s) installed, ${n.alreadyLinked.length} already linked.`),!k())console.log(`
|
|
4
4
|
scip CLI not found on PATH. Attempting auto-install...`),m(console.log)||f();else{let o=g();console.log(`
|
|
5
5
|
scip CLI: ${o??"installed"}`)}console.log("")}y();
|
package/dist/runtime.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import{b,c as j,d as W}from"./chunk-LWYIGRHR.js";import{a as w}from"./chunk-TKDJQ2WD.js";import{readFileSync as _,writeFileSync as D,existsSync as v,mkdirSync as F}from"fs";import{join as l,resolve as C}from"path";import{createHash as L}from"crypto";import{homedir as $}from"os";var P=".scipquery.json",A={enabled:!1,debounceMs:3e4,cooldownMs:6e4,ignore:[]};function N(i){let t=l(i,P);if(!v(t))return{};try{let e=_(t,"utf-8");return JSON.parse(e)}catch{return{}}}function R(i){return{...A,...i.watch}}function O(i,t){let e=process.env.SCIP_QUERY_CACHE_DIR;if(e)return g(e);if(t?.dbPath)return g(C(i,t.dbPath));let n=process.env.XDG_CACHE_HOME||l($(),".cache"),o=L("sha256").update(C(i)).digest("hex").slice(0,12),r=l(n,"scip-query","projects",o);return g(r)}function f(i,t){let e=O(i,t);return{cacheDir:e,dbPath:l(e,"index.db"),indexPath:l(e,"index.scip"),metaPath:l(e,"meta.json")}}function M(i,t){let e=l(i,P);return v(e)||D(e,JSON.stringify({languages:t,watch:{enabled:!1,debounceMs:3e4,cooldownMs:6e4}},null,2)+`
|
|
2
|
-
`),e}function g(i){return F(i,{recursive:!0}),i}import{watch as q}from"fs";import{existsSync as I,renameSync as T}from"fs";import{join as U,relative as H}from"path";import{fork as G}from"child_process";import X from"ignore";var m=class{projectRoot;watchConfig;indexPaths;languages;pnpmWorkspaces;onStatus;onReindexComplete;onError;status={state:"idle"};debounceTimer=null;cooldownTimer=null;dirty=!1;changedFiles=0;reindexInFlight=!1;lastReindexEnd=0;fsWatchers=[];gitignoreFilter;extraIgnore;stopped=!1;constructor(t){this.projectRoot=t.projectRoot,this.watchConfig=R(t.config),this.indexPaths=f(t.projectRoot,t.config),this.languages=t.languages,this.pnpmWorkspaces=t.config.indexer?.typescript?.pnpmWorkspaces??!1,this.onStatus=t.onStatus??(()=>{}),this.onReindexComplete=t.onReindexComplete??(()=>{}),this.onError=t.onError??(e=>console.error(e.message)),this.gitignoreFilter=w(t.projectRoot),this.extraIgnore=X(),this.watchConfig.ignore.length>0&&this.extraIgnore.add(this.watchConfig.ignore)}start(){this.stopped=!1,this.setStatus({state:"idle"});try{let t=q(this.projectRoot,{recursive:!0},(e,s)=>{s&&!this.stopped&&this.handleFileChange(s)});this.fsWatchers.push(t)}catch{this.onError(new Error("Failed to start file watcher. On Linux, you may need to increase inotify limits: sysctl -w fs.inotify.max_user_watches=524288"))}}stop(){this.stopped=!0;for(let t of this.fsWatchers)t.close();this.fsWatchers=[],this.clearDebounceTimer(),this.clearCooldownTimer(),this.setStatus({state:"idle"})}handleFileChange(t){let e=H(this.projectRoot,U(this.projectRoot,t));if(this.gitignoreFilter.isIgnored(e)||this.extraIgnore.ignores(e)||t.endsWith("index.db")||t.endsWith("index.scip")||t.endsWith("index.db.tmp")||t.endsWith(".scipquery.json"))return;if(this.changedFiles++,this.reindexInFlight){this.dirty=!0,this.setStatus({state:"indexing",startedAt:this.status.startedAt});return}if(this.status.state==="cooldown"){this.dirty=!0,this.setStatus({state:"cooldown",until:this.status.until,dirty:!0});return}this.clearDebounceTimer();let s=Date.now()+this.watchConfig.debounceMs;this.setStatus({state:"waiting",changedFiles:this.changedFiles,reindexAt:s}),this.debounceTimer=setTimeout(()=>{this.debounceTimer=null,this.triggerReindex()},this.watchConfig.debounceMs)}triggerReindex(){if(this.reindexInFlight||this.stopped)return;let t=Date.now()-this.lastReindexEnd;if(this.lastReindexEnd>0&&t<this.watchConfig.cooldownMs){let s=this.watchConfig.cooldownMs-t;this.dirty=!0;let n=Date.now()+s;this.setStatus({state:"cooldown",until:n,dirty:!0}),this.cooldownTimer=setTimeout(()=>{this.cooldownTimer=null,this.dirty&&!this.stopped&&(this.dirty=!1,this.triggerReindex())},s);return}this.reindexInFlight=!0,this.dirty=!1,this.changedFiles=0;let e=Date.now();this.setStatus({state:"indexing",startedAt:e}),this.runReindex().then(s=>{if(this.reindexInFlight=!1,this.lastReindexEnd=Date.now(),this.onReindexComplete(s),this.dirty&&!this.stopped){let n=Date.now()+this.watchConfig.cooldownMs;this.setStatus({state:"cooldown",until:n,dirty:!0}),this.cooldownTimer=setTimeout(()=>{this.cooldownTimer=null,this.dirty&&!this.stopped?(this.dirty=!1,this.triggerReindex()):this.setStatus({state:"idle"})},this.watchConfig.cooldownMs)}else this.setStatus({state:"idle"})}).catch(s=>{this.reindexInFlight=!1,this.lastReindexEnd=Date.now(),this.onError(s instanceof Error?s:new Error(String(s))),this.setStatus({state:"idle"})})}runReindex(){return new Promise((t,e)=>{let s=Date.now(),n=this.indexPaths.dbPath+".tmp",o=B(this.indexPaths.indexPath),r=G(new URL("./reindex-worker.js",import.meta.url).pathname,[],{env:{...process.env,SCIP_REINDEX_PROJECT_ROOT:this.projectRoot,SCIP_REINDEX_OUTPUT_SCIP:o,SCIP_REINDEX_OUTPUT_DB:n,SCIP_REINDEX_LANGUAGES:this.languages?.join(",")??"",SCIP_REINDEX_PNPM_WORKSPACES:this.pnpmWorkspaces?"1":""},stdio:"pipe"});r.on("exit",h=>{if(h===0)try{I(n)&&T(n,this.indexPaths.dbPath),I(o)&&T(o,this.indexPaths.indexPath),t(Date.now()-s)}catch(a){e(new Error(`Atomic swap failed: ${a}`))}else e(new Error(`Reindex worker exited with code ${h}`))}),r.on("error",e)})}setStatus(t){this.status=t,this.onStatus(t)}clearDebounceTimer(){this.debounceTimer&&(clearTimeout(this.debounceTimer),this.debounceTimer=null)}clearCooldownTimer(){this.cooldownTimer&&(clearTimeout(this.cooldownTimer),this.cooldownTimer=null)}};function B(i){return i.endsWith(".scip")?i.slice(0,-5)+".tmp.scip":i+".tmp.scip"}import{existsSync as x,mkdirSync as J,symlinkSync as V,readlinkSync as K,unlinkSync as Q}from"fs";import{join as d,dirname as k,resolve as S}from"path";import{homedir as y,platform as Y}from"os";import{fileURLToPath as z}from"url";var Z=Y()==="win32",tt=["concrete-plan","scip-ai-cleanup","scip-explore","scip-debloat","scip-maintainability","scip-verify","scip-language-playbook"];function et(i={}){let t=i.quiet?()=>{}:console.log,e=z(import.meta.url),s=S(k(e),"..","skills"),n=[d(y(),".claude","skills"),d(y(),".codex","skills"),d(y(),".agents","skills")],o={installed:[],skipped:[],alreadyLinked:[]};for(let r of n){let h=k(r);if(!x(h))continue;J(r,{recursive:!0});let a=it(r);for(let c of tt){let u=d(s,c),p=d(r,c);if(!x(u)){o.skipped.push(`${a}/${c}`);continue}if(x(p)){try{let E=K(p);if(S(E)===S(u)){o.alreadyLinked.push(`${a}/${c}`),t(` ok: ${c} \u2192 ${a} (already linked)`);continue}}catch{o.skipped.push(`${a}/${c}`),t(` skip: ${c} \u2192 ${a} (exists, not a symlink)`);continue}Q(p)}V(u,p,Z?"junction":"dir"),o.installed.push(`${a}/${c}`),t(` done: ${c} \u2192 ${a}`)}}return o}function it(i){return i.includes(".codex")?"Codex":i.includes(".agents")?"Agents":"Claude"}export{m as Watcher,j as getScipVersion,M as initProjectConfig,et as installSkills,b as isScipInstalled,N as loadProjectConfig,W as printScipInstallInstructions,f as resolveIndexPaths};
|
|
2
|
+
`),e}function g(i){return F(i,{recursive:!0}),i}import{watch as q}from"fs";import{existsSync as I,renameSync as T}from"fs";import{join as U,relative as H}from"path";import{fork as G}from"child_process";import X from"ignore";var m=class{projectRoot;watchConfig;indexPaths;languages;pnpmWorkspaces;onStatus;onReindexComplete;onError;status={state:"idle"};debounceTimer=null;cooldownTimer=null;dirty=!1;changedFiles=0;reindexInFlight=!1;lastReindexEnd=0;fsWatchers=[];gitignoreFilter;extraIgnore;stopped=!1;constructor(t){this.projectRoot=t.projectRoot,this.watchConfig=R(t.config),this.indexPaths=f(t.projectRoot,t.config),this.languages=t.languages,this.pnpmWorkspaces=t.config.indexer?.typescript?.pnpmWorkspaces??!1,this.onStatus=t.onStatus??(()=>{}),this.onReindexComplete=t.onReindexComplete??(()=>{}),this.onError=t.onError??(e=>console.error(e.message)),this.gitignoreFilter=w(t.projectRoot),this.extraIgnore=X(),this.watchConfig.ignore.length>0&&this.extraIgnore.add(this.watchConfig.ignore)}start(){this.stopped=!1,this.setStatus({state:"idle"});try{let t=q(this.projectRoot,{recursive:!0},(e,s)=>{s&&!this.stopped&&this.handleFileChange(s)});this.fsWatchers.push(t)}catch{this.onError(new Error("Failed to start file watcher. On Linux, you may need to increase inotify limits: sysctl -w fs.inotify.max_user_watches=524288"))}}stop(){this.stopped=!0;for(let t of this.fsWatchers)t.close();this.fsWatchers=[],this.clearDebounceTimer(),this.clearCooldownTimer(),this.setStatus({state:"idle"})}handleFileChange(t){let e=H(this.projectRoot,U(this.projectRoot,t));if(this.gitignoreFilter.isIgnored(e)||this.extraIgnore.ignores(e)||t.endsWith("index.db")||t.endsWith("index.scip")||t.endsWith("index.db.tmp")||t.endsWith(".scipquery.json"))return;if(this.changedFiles++,this.reindexInFlight){this.dirty=!0,this.setStatus({state:"indexing",startedAt:this.status.startedAt});return}if(this.status.state==="cooldown"){this.dirty=!0,this.setStatus({state:"cooldown",until:this.status.until,dirty:!0});return}this.clearDebounceTimer();let s=Date.now()+this.watchConfig.debounceMs;this.setStatus({state:"waiting",changedFiles:this.changedFiles,reindexAt:s}),this.debounceTimer=setTimeout(()=>{this.debounceTimer=null,this.triggerReindex()},this.watchConfig.debounceMs)}triggerReindex(){if(this.reindexInFlight||this.stopped)return;let t=Date.now()-this.lastReindexEnd;if(this.lastReindexEnd>0&&t<this.watchConfig.cooldownMs){let s=this.watchConfig.cooldownMs-t;this.dirty=!0;let n=Date.now()+s;this.setStatus({state:"cooldown",until:n,dirty:!0}),this.cooldownTimer=setTimeout(()=>{this.cooldownTimer=null,this.dirty&&!this.stopped&&(this.dirty=!1,this.triggerReindex())},s);return}this.reindexInFlight=!0,this.dirty=!1,this.changedFiles=0;let e=Date.now();this.setStatus({state:"indexing",startedAt:e}),this.runReindex().then(s=>{if(this.reindexInFlight=!1,this.lastReindexEnd=Date.now(),this.onReindexComplete(s),this.dirty&&!this.stopped){let n=Date.now()+this.watchConfig.cooldownMs;this.setStatus({state:"cooldown",until:n,dirty:!0}),this.cooldownTimer=setTimeout(()=>{this.cooldownTimer=null,this.dirty&&!this.stopped?(this.dirty=!1,this.triggerReindex()):this.setStatus({state:"idle"})},this.watchConfig.cooldownMs)}else this.setStatus({state:"idle"})}).catch(s=>{this.reindexInFlight=!1,this.lastReindexEnd=Date.now(),this.onError(s instanceof Error?s:new Error(String(s))),this.setStatus({state:"idle"})})}runReindex(){return new Promise((t,e)=>{let s=Date.now(),n=this.indexPaths.dbPath+".tmp",o=B(this.indexPaths.indexPath),r=G(new URL("./reindex-worker.js",import.meta.url).pathname,[],{env:{...process.env,SCIP_REINDEX_PROJECT_ROOT:this.projectRoot,SCIP_REINDEX_OUTPUT_SCIP:o,SCIP_REINDEX_OUTPUT_DB:n,SCIP_REINDEX_LANGUAGES:this.languages?.join(",")??"",SCIP_REINDEX_PNPM_WORKSPACES:this.pnpmWorkspaces?"1":""},stdio:"pipe"});r.on("exit",h=>{if(h===0)try{I(n)&&T(n,this.indexPaths.dbPath),I(o)&&T(o,this.indexPaths.indexPath),t(Date.now()-s)}catch(a){e(new Error(`Atomic swap failed: ${a}`))}else e(new Error(`Reindex worker exited with code ${h}`))}),r.on("error",e)})}setStatus(t){this.status=t,this.onStatus(t)}clearDebounceTimer(){this.debounceTimer&&(clearTimeout(this.debounceTimer),this.debounceTimer=null)}clearCooldownTimer(){this.cooldownTimer&&(clearTimeout(this.cooldownTimer),this.cooldownTimer=null)}};function B(i){return i.endsWith(".scip")?i.slice(0,-5)+".tmp.scip":i+".tmp.scip"}import{existsSync as x,mkdirSync as J,symlinkSync as V,readlinkSync as K,unlinkSync as Q}from"fs";import{join as d,dirname as k,resolve as S}from"path";import{homedir as y,platform as Y}from"os";import{fileURLToPath as z}from"url";var Z=Y()==="win32",tt=["concrete-plan","scip-ai-cleanup","scip-explore","scip-debloat","scip-doc-reconcile","scip-maintainability","scip-verify","scip-language-playbook"];function et(i={}){let t=i.quiet?()=>{}:console.log,e=z(import.meta.url),s=S(k(e),"..","skills"),n=[d(y(),".claude","skills"),d(y(),".codex","skills"),d(y(),".agents","skills")],o={installed:[],skipped:[],alreadyLinked:[]};for(let r of n){let h=k(r);if(!x(h))continue;J(r,{recursive:!0});let a=it(r);for(let c of tt){let u=d(s,c),p=d(r,c);if(!x(u)){o.skipped.push(`${a}/${c}`);continue}if(x(p)){try{let E=K(p);if(S(E)===S(u)){o.alreadyLinked.push(`${a}/${c}`),t(` ok: ${c} \u2192 ${a} (already linked)`);continue}}catch{o.skipped.push(`${a}/${c}`),t(` skip: ${c} \u2192 ${a} (exists, not a symlink)`);continue}Q(p)}V(u,p,Z?"junction":"dir"),o.installed.push(`${a}/${c}`),t(` done: ${c} \u2192 ${a}`)}}return o}function it(i){return i.includes(".codex")?"Codex":i.includes(".agents")?"Agents":"Claude"}export{m as Watcher,j as getScipVersion,M as initProjectConfig,et as installSkills,b as isScipInstalled,N as loadProjectConfig,W as printScipInstallInstructions,f as resolveIndexPaths};
|
|
3
3
|
//# sourceMappingURL=runtime.js.map
|
package/package.json
CHANGED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scip-doc-reconcile
|
|
3
|
+
description: Reconcile standards docs and living documentation with the current code using scip-query doc-drift evidence. Updates descriptive claims, repairs broken file references, and escalates normative violations instead of silently blessing them. Ends with staleness driven to zero.
|
|
4
|
+
allowed-tools: [Bash, Read, Write, Edit, Glob, Agent, TaskCreate, TaskUpdate, TaskGet, TaskList]
|
|
5
|
+
keywords: [docs, standards, reconcile, doc-drift, stale-docs, agent-os, spec, documentation, drift, sync]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Doc Reconciliation with scip-query
|
|
9
|
+
|
|
10
|
+
Standards docs exist so agents implement consistently. When the code moves and
|
|
11
|
+
the doc doesn't, every agent that reads it implements against a dead spec.
|
|
12
|
+
This skill reconciles docs with reality — using evidence, not memory.
|
|
13
|
+
|
|
14
|
+
## The One Rule That Matters
|
|
15
|
+
|
|
16
|
+
A doc contains two kinds of statements, and they drift differently:
|
|
17
|
+
|
|
18
|
+
- **Descriptive** ("the horses workflow lives in `workflows/horses.ts` and
|
|
19
|
+
exposes `listHorses`") — when code moved on, **update the doc**.
|
|
20
|
+
- **Normative** ("all routes MUST validate stable scope before querying") —
|
|
21
|
+
when code violates it, **do NOT rewrite the standard to bless the
|
|
22
|
+
violation**. Either fix the code to comply, or record the contradiction in
|
|
23
|
+
the report for a human decision. Silently weakening a standard to match
|
|
24
|
+
drifted code is worse than the drift.
|
|
25
|
+
|
|
26
|
+
When unsure which kind a statement is: MUST/SHOULD/NEVER language is
|
|
27
|
+
normative; file paths, symbol names, and behavior descriptions are
|
|
28
|
+
descriptive.
|
|
29
|
+
|
|
30
|
+
## Workflow
|
|
31
|
+
|
|
32
|
+
### 1. Build the evidence-backed worklist
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
scip-query reindex
|
|
36
|
+
scip-query doc-drift # all living docs, ranked by staleness
|
|
37
|
+
scip-query doc-drift agent-os/standards # scoped to a standards tree
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Triage order:
|
|
41
|
+
1. Docs with `BROKEN REFERENCE` lines (the spec cites deleted code — actively wrong)
|
|
42
|
+
2. Highest staleness score
|
|
43
|
+
3. Docs agents read most (AGENTS.md, CLAUDE.md, standards indexes)
|
|
44
|
+
|
|
45
|
+
Track each doc as a task. Archival docs (dated plans, ADRs, reports) are
|
|
46
|
+
excluded automatically — do not "reconcile" records of past decisions.
|
|
47
|
+
|
|
48
|
+
### 2. Reconcile one doc at a time
|
|
49
|
+
|
|
50
|
+
For each doc, gather what actually changed:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
scip-query doc-drift <doc> # its subjects + changes since
|
|
54
|
+
git log --oneline -15 -- <subject-file> # WHY the subject changed
|
|
55
|
+
scip-query outline <subject-file> # what it looks like NOW
|
|
56
|
+
scip-query system <module> # current module shape
|
|
57
|
+
scip-query trace <symbol-the-doc-mentions> # does it still exist? who uses it?
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Then edit the doc:
|
|
61
|
+
|
|
62
|
+
- **Broken references**: find where the code went (`scip-query files <stem>`,
|
|
63
|
+
`git log --follow`) and update the citation — or delete the claim if the
|
|
64
|
+
capability is gone.
|
|
65
|
+
- **Stale descriptive claims**: re-read the subject files and rewrite the
|
|
66
|
+
claims to match current behavior. Every concrete claim you write must be
|
|
67
|
+
something you verified with a scip-query command this session — no claims
|
|
68
|
+
from memory.
|
|
69
|
+
- **Examples and snippets**: re-derive them from current code
|
|
70
|
+
(`scip-query code <symbol>`), don't patch them by eye.
|
|
71
|
+
- **Normative violations found while reading**: add them to the report under
|
|
72
|
+
"Standard vs code contradictions" with file:line evidence. Do not edit the
|
|
73
|
+
normative text.
|
|
74
|
+
|
|
75
|
+
### 3. Verify, per doc and overall
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
scip-query doc-drift <doc> # staleness must drop to 0, broken refs to none
|
|
79
|
+
scip-query diff-gate # your own doc edits gate clean before commit
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
A doc still showing staleness after your edit means a subject changed in
|
|
83
|
+
ways you haven't reflected — go back.
|
|
84
|
+
|
|
85
|
+
### 4. Report
|
|
86
|
+
|
|
87
|
+
- Per doc: staleness before → after, broken references fixed, claims updated.
|
|
88
|
+
- **Standard vs code contradictions** (normative): each with the standard's
|
|
89
|
+
requirement, the violating file:line, and a recommendation (fix code /
|
|
90
|
+
amend standard) — explicitly awaiting a human call.
|
|
91
|
+
- Docs recommended for deletion (describe removed capabilities entirely).
|
|
92
|
+
|
|
93
|
+
## Hard Rules
|
|
94
|
+
|
|
95
|
+
1. Every updated claim cites the scip-query command that verified it (in the
|
|
96
|
+
commit message or PR description).
|
|
97
|
+
2. Never weaken normative language to match drifted code.
|
|
98
|
+
3. Never reconcile archival docs (plans, ADRs, reports) — they are records.
|
|
99
|
+
4. One commit per doc (or tight group) so review is per-standard.
|
|
100
|
+
5. Re-run `scip-query doc-drift` at the end; the summary line is the result.
|