scip-query 0.8.0 → 0.8.2
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/README.md +1 -1
- package/dist/cli.js +122 -122
- package/dist/postinstall.js +1 -1
- package/dist/runtime.js +1 -1
- package/package.json +1 -1
- package/skills/scip-ai-cleanup/SKILL.md +1 -1
- package/skills/scip-doc-reconcile/SKILL.md +100 -0
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
|
@@ -98,7 +98,7 @@ scip-query cleanup-plan --verify
|
|
|
98
98
|
- Batches are ordered: batch 0 is graph-fact dead now; batch n is dead once
|
|
99
99
|
batch n-1 lands (the cascade). Apply ONE batch at a time.
|
|
100
100
|
- `COMPILER-VERIFIED` means the deletion was applied in a throwaway worktree
|
|
101
|
-
and your own checker (tsc / cargo check) passed differentially.
|
|
101
|
+
and your own checker (tsc / cargo check / go build / ruff) passed differentially.
|
|
102
102
|
- `FAILED` errors name real references — usually barrel export lines or
|
|
103
103
|
imports that must be removed together with the symbol, occasionally a
|
|
104
104
|
detector false positive. Investigate before deleting anything.
|
|
@@ -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.
|