scip-query 0.19.10 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,24 @@ All notable changes to `scip-query` are documented here. This file starts at 0.1
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.20.0]
|
|
8
|
+
|
|
9
|
+
### Maintained native SQLite distribution
|
|
10
|
+
|
|
11
|
+
- `better-sqlite3` is upgraded to 13.0.2, whose N-API binaries ship inside
|
|
12
|
+
the dependency tarball. New installs no longer resolve the abandoned
|
|
13
|
+
`prebuild-install` helper. The repository explicitly denies npm's inferred
|
|
14
|
+
`node-gyp rebuild` fallback because the bundled binary needs no lifecycle
|
|
15
|
+
setup.
|
|
16
|
+
- The public runtime floor is now Node.js 22, matching the required native
|
|
17
|
+
dependency instead of advertising the obsolete Node 18 contract; every
|
|
18
|
+
published bundle now targets the same runtime floor. Install output and the
|
|
19
|
+
README recommend Node.js 24 LTS while distinguishing it from the supported
|
|
20
|
+
minimum.
|
|
21
|
+
- Runtime-contract tests and a Node 22/24/26 CI matrix exercise a real SQLite
|
|
22
|
+
database, while install guidance distinguishes bundled SQLite binaries from
|
|
23
|
+
the remaining Tree-sitter lifecycle scripts.
|
|
24
|
+
|
|
7
25
|
## [0.19.10]
|
|
8
26
|
|
|
9
27
|
### Safer setup and removal
|
package/README.md
CHANGED
|
@@ -100,12 +100,20 @@ makes every package-subpath signature change explicit before release.
|
|
|
100
100
|
|
|
101
101
|
On npm setups with script approval enabled (`allow-scripts`), the install prints warnings like
|
|
102
102
|
`15 packages have install scripts not yet covered by allowScripts` — and **skips those scripts**,
|
|
103
|
-
which leaves the native modules unbuilt. Every script on that list is expected:
|
|
103
|
+
which leaves the affected native modules unbuilt. Every remaining script on that list is expected:
|
|
104
104
|
|
|
105
105
|
- `scip-query` — its own postinstall (non-fatal by construction: `... || true`)
|
|
106
|
-
- `better-sqlite3` — builds/downloads the native SQLite binding that backs the index
|
|
107
106
|
- `tree-sitter` + the per-language grammars — native parsers behind multi-language source facts
|
|
108
107
|
|
|
108
|
+
`better-sqlite3` 13 does not need lifecycle-script approval: it ships stable
|
|
109
|
+
N-API SQLite binaries for the supported platforms inside its npm package.
|
|
110
|
+
Although npm infers a default `node-gyp rebuild` from the addon's source
|
|
111
|
+
metadata, scip-query explicitly denies that unnecessary fallback in its own
|
|
112
|
+
development install policy. A real database test verifies that the bundled
|
|
113
|
+
binary works with scripts disabled.
|
|
114
|
+
Seeing `prebuild-install` during a scip-query install therefore means an older
|
|
115
|
+
scip-query dependency tree was selected.
|
|
116
|
+
|
|
109
117
|
Approve them and re-run the builds (`--allow-scripts-pending` only _lists_ — the approving forms
|
|
110
118
|
are `npm approve-scripts <pkg> ...` or `--all`):
|
|
111
119
|
|
|
@@ -240,18 +248,20 @@ intended.
|
|
|
240
248
|
**8. Gate every diff.** `diff-gate` runs a defined set of checks scoped to what a change _introduces_ and exits nonzero with remediation text for each finding. Baseline regressions are included when you pass `--baseline`.
|
|
241
249
|
|
|
242
250
|
<!-- BEGIN GENERATED DIFF-GATE CHECKS -->
|
|
243
|
-
|
|
244
|
-
|
|
|
245
|
-
|
|
|
246
|
-
| `
|
|
247
|
-
| `
|
|
248
|
-
| `
|
|
249
|
-
| `
|
|
250
|
-
| `
|
|
251
|
-
| `
|
|
252
|
-
| `
|
|
253
|
-
| `
|
|
254
|
-
| `
|
|
251
|
+
|
|
252
|
+
| Check | What it catches | When it runs |
|
|
253
|
+
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
254
|
+
| `echo` | Changed symbols that newly echo established code elsewhere. | Default diff gate. |
|
|
255
|
+
| `incomplete-migration` | New helpers or abstractions wired into some sites while older inline sites remain. | Default diff gate. |
|
|
256
|
+
| `co-change-partner` | Historically coupled files that usually change together but are missing from this diff. | Default diff gate. |
|
|
257
|
+
| `twin-partner` | A changed symbol has a same-(near-)name twin (identical or already-divergent) elsewhere that this diff left untouched. | Default diff gate. Advisory: findings print but never cause a nonzero exit by themselves. |
|
|
258
|
+
| `coverage-contract` | A configured `coverageContracts` entry (.scipquery.json) drifted: its declared key set no longer matches its ground-truth source. | Default diff gate, only when either side of a configured contract changed. |
|
|
259
|
+
| `architecture` | A declared architecture boundary rule has a violation absent from the committed health baseline. | Default diff gate when closed dependency rows, requireCompletePolicy, requireAcyclic, requireResolvedBoundaries, requireMinimalPolicy, maxBoundaryFanOut/maxBoundaryFiles, or testPaths are configured and a baseline exists. |
|
|
260
|
+
| `doc-reference` | Docs that cite changed files and may need a matching update. Dated snapshot docs (docs.snapshotPaths) are excluded by policy. | Default diff gate. Advisory (21.2) for bare file-mention citations; blocking when the citation has a line anchor or the cited file was deleted/renamed. |
|
|
261
|
+
| `unused-params` | Fresh trailing parameters or options that no changed body uses. | Default diff gate. |
|
|
262
|
+
| `new-dead` | Changed production symbols with zero indexed consumers. | Default diff gate. |
|
|
263
|
+
| `baseline` | New health finding identities compared with the committed health baseline. | Only with `diff-gate --baseline`. |
|
|
264
|
+
|
|
255
265
|
<!-- END GENERATED DIFF-GATE CHECKS -->
|
|
256
266
|
|
|
257
267
|
Illustrative output:
|
|
@@ -537,7 +547,8 @@ scip-query health --write-baseline # start the ratchet
|
|
|
537
547
|
|
|
538
548
|
## Prerequisites
|
|
539
549
|
|
|
540
|
-
- Node.js
|
|
550
|
+
- Node.js 24 LTS is recommended. Node.js 22 is the minimum supported runtime;
|
|
551
|
+
Node.js 22, 24, and 26 are tested.
|
|
541
552
|
- `scip` CLI, from [Sourcegraph SCIP releases](https://github.com/sourcegraph/scip/releases)
|
|
542
553
|
- A language-specific SCIP indexer for your project
|
|
543
554
|
|
|
@@ -759,7 +770,7 @@ Add `--result-only` when a program needs just the command payload:
|
|
|
759
770
|
{
|
|
760
771
|
"kind": "scip-query-result",
|
|
761
772
|
"schemaVersion": 1,
|
|
762
|
-
"producer": { "name": "scip-query", "version": "0.
|
|
773
|
+
"producer": { "name": "scip-query", "version": "0.20.0" },
|
|
763
774
|
"command": "fan-in",
|
|
764
775
|
"resultSchemaVersion": 1,
|
|
765
776
|
"args": ["login"],
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{b as M,c as z,d as L,e as $,j as q,k as G,m as h}from"./chunk-LU47HG23.js";import{A as D,De as g,Ee as T,Ge as V,H as N,I as b,J as S,K as P,L as x,Re as X,Ye as I,Ze as _,cb as k,o as E,pe as A,qe as f,se as j,ue as O,ve as U,wd as a,we as R}from"./chunk-JFGGXWQF.js";import{program as c}from"commander";import{realpathSync as K}from"fs";import{fileURLToPath as ye}from"url";var Y=new Set(["code","outline","refs"]);function Z(e){return e!==void 0&&Y.has(e)}async function W(e){if(Z(e)){let{directNavigationQueryCommandDescriptors:n}=await import("./direct-navigation-6YHV6IB5.js"),o=n.find(r=>r.id===e);if(!o)throw new Error(`Direct navigation command descriptor is unavailable: ${e}`);return[o]}let{commandDescriptors:t}=await import("./command-descriptors-
|
|
2
|
+
import{b as M,c as z,d as L,e as $,j as q,k as G,m as h}from"./chunk-LU47HG23.js";import{A as D,De as g,Ee as T,Ge as V,H as N,I as b,J as S,K as P,L as x,Re as X,Ye as I,Ze as _,cb as k,o as E,pe as A,qe as f,se as j,ue as O,ve as U,wd as a,we as R}from"./chunk-JFGGXWQF.js";import{program as c}from"commander";import{realpathSync as K}from"fs";import{fileURLToPath as ye}from"url";var Y=new Set(["code","outline","refs"]);function Z(e){return e!==void 0&&Y.has(e)}async function W(e){if(Z(e)){let{directNavigationQueryCommandDescriptors:n}=await import("./direct-navigation-6YHV6IB5.js"),o=n.find(r=>r.id===e);if(!o)throw new Error(`Direct navigation command descriptor is unavailable: ${e}`);return[o]}let{commandDescriptors:t}=await import("./command-descriptors-DSS46KXI.js");return t}function F(e){return e.evidence?e.evidence:ee.has(e.id)?"mixed":e.heuristic?"heuristic":"graph-fact"}var ee=new Set(["diff-gate","health","plan-context","co-change"]);function J(e,t){return I(new Map(t.map(n=>[n.id,F(n)]))),_(new Map(t.flatMap(n=>n.agent?[[n.id,{...n.agent,resultUnits:ne(n)}]]:[]))),t.map(n=>{let o=n.hidden?e.command(n.command,{hidden:!0}):e.command(n.command);o.description(n.description);for(let r of n.arguments??[])o.argument(r.name);for(let r of n.options??[])r.parser&&Object.hasOwn(r,"defaultValue")?o.option(r.flags,r.description,r.parser,r.defaultValue):r.parser?o.option(r.flags,r.description,r.parser):Object.hasOwn(r,"defaultValue")?o.option(r.flags,r.description,r.defaultValue):o.option(r.flags,r.description);return o.action(async(...r)=>{try{let i=o.optsWithGlobals();te(i),await q({command:n.id,producerVersion:a,invocationPrefix:process.argv[1]?[process.execPath,process.argv[1]]:["scip-query"],argv:process.argv.slice(2),cwd:process.cwd(),json:i.json===!0,...typeof i.outputPageSize=="number"?{pageSize:i.outputPageSize}:{},...typeof i.outputCursor=="string"?{cursor:i.outputCursor}:{}},()=>n.handler(...r))}catch(i){re(i)}}),{descriptor:n,command:o}})}function te(e){if(e.resultOnly===!0&&e.json!==!0)throw new Error("--result-only requires --json.");if(e.compact===!0&&e.json!==!0)throw new Error("--compact requires --json.")}function ne(e){let t=e.agent?.resultUnits;if(t?.kind==="field"&&t.field.trim()==="")throw new Error(`Command ${e.id} declares an empty result-unit field.`);return t||(e.renderShape==="list"||e.renderShape==="table"||e.renderShape==="grouped-by-file"?{kind:"rows"}:{kind:"report"})}function re(e){let t=e instanceof Error?e.message:String(e);console.error(`error: ${T(t)}`),process.exitCode=1}import{existsSync as oe,mkdirSync as ie,writeFileSync as ae}from"fs";import{homedir as se}from"os";import{join as u}from"path";var ce=1440*60*1e3,B="update-check.json",me="https://registry.npmjs.org/scip-query/latest";async function C(e={}){let t=e.env??process.env;if(t.SCIP_QUERY_UPDATE_CHECK==="0"||t.NO_UPDATE_NOTIFIER||e.commandName&&de(e.commandName))return;let n=e.cacheDir??le(t),o=e.now??Date.now(),r=e.currentVersion??a,i=fe(n),s=i&&o-i.checkedAt<ce?i.latestVersion:await ge(n,e.fetchLatestVersion??Ce,o);if(!s||!pe(s,r))return;(e.writeNotice??(m=>console.error(m)))(ue(r,s))}function de(e){return e==="hook-context"||e==="hook-stop"}function ue(e,t){return[`scip-query update available: ${e} -> ${t}.`,"Agent: tell your human to update with: npm install -g scip-query@latest",""].join(`
|
|
3
3
|
`)}function pe(e,t){let n=H(e),o=H(t);if(!n||!o)return e!==t;for(let r=0;r<n.length;r++){let i=n[r]-o[r];if(i>0)return!0;if(i<0)return!1}return!1}function le(e){let t=e.XDG_CACHE_HOME||u(se(),".cache");return u(t,"scip-query")}function fe(e){let t=u(e,B);if(!oe(t))return null;try{let n=JSON.parse(D(t,"update notice cache"));return typeof n.checkedAt=="number"&&(typeof n.latestVersion=="string"||n.latestVersion===null)?{checkedAt:n.checkedAt,latestVersion:n.latestVersion}:null}catch{return null}}async function ge(e,t,n){let o;try{o=await t()}catch{o=null}return he(e,{checkedAt:n,latestVersion:o}),o}function he(e,t){try{ie(e,{recursive:!0}),ae(u(e,B),`${JSON.stringify(t,null,2)}
|
|
4
4
|
`)}catch{}}async function Ce(){let e=await fetch(me,{signal:AbortSignal.timeout(1e3)});if(!e.ok)return null;let t=await e.json();return typeof t.version=="string"?t.version:null}function H(e){let t=/^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(e);return t?[Number(t[1]),Number(t[2]),Number(t[3])]:null}var y=we();y&&(V(),c.configureOutput({writeOut:e=>process.stdout.write(g(e)),writeErr:e=>process.stderr.write(g(e))}));c.name("scip-query").description("Language-agnostic code intelligence CLI powered by SCIP indexes").version(a).option("--output-page-size <characters>","Return bounded output pages with an exact continuation command",G).option("--output-cursor <cursor>","Continue a bounded output page");var ve=await W(y?process.argv[2]:void 0);J(c,ve);c.hook("preAction",async(e,t)=>{let n=t.name(),o=U(n),r=z(n);if(!o&&!r){Q(),await C({commandName:n});return}let i=A(),s=k(i),p=j(i,s);f(p),Q(),await C({commandName:n});let{config:m,paths:l}=p,v;if(r&&m.watch?.enabled===!0)try{v=M($({projectRoot:i,cacheDir:l.cacheDir,cliVersion:a,gitContext:s}))}catch{}if(o){let w=O(i,m,l,{gitContext:s,watcherGeneration:v});w.kind==="failed"&&process.env.SCIP_QUERY_DEBUG&&console.error(`shared-cache: ${w.reason}`)}if(!r){h(i,a);return}let d=L({commandName:n,projectRoot:i,cacheDir:l.cacheDir,cliVersion:a,config:m,gitContext:s});d.kind==="failed"&&console.error(`warning: scip-query watch service did not start: ${d.message}`),(d.kind==="failed"||d.kind==="skipped")&&h(i,a)});c.hook("postAction",()=>f(void 0));function Q(){if(S(),!N()||P())return;let e=null;try{e=R(t=>E(t))}catch{}x({command:b()??`scip-query ${process.argv.slice(2).join(" ")}`,toolVersion:a,projectFingerprint:e})}y&&await c.parseAsync();function we(){if(!process.argv[1])return!1;let e=ye(import.meta.url);try{return K(e)===K(process.argv[1])}catch{return e===process.argv[1]}}export{c as program,X as renderHeuristicNotice};
|
|
5
5
|
//# sourceMappingURL=cli.js.map
|
|
@@ -639,4 +639,4 @@ Conformance: ${e.conformance.mappedVariables} variable(s), ${e.conformance.mappe
|
|
|
639
639
|
Finding groups (${e.findingGroups.length}) \u2014 pass --full for every finding ungrouped:`);for(let n of e.findingGroups){console.log(`
|
|
640
640
|
[${n.severity}] ${n.category}${n.modelElement?` (${n.modelElement})`:""} \u2014 ${n.count} finding(s)`);for(let i of n.findingIds.slice(0,Vy)){let o=t.get(i);o&&Uy(o)}let r=n.count-Vy;r>0&&console.log(` ... and ${r} more in this group (use --full to show all)`)}}function TA(e){let t=`${e.checker.checker} ${e.checker.status==="passed"?"PASS":e.checker.status.toUpperCase()}`,n=e.conformance.waivers.filter(s=>s.kind==="write").length,r=e.conformance.waivers.filter(s=>s.kind==="read").length,i=e.conformance.waivers.filter(s=>s.kind==="referent").length,o=e.conformance.findings.filter(s=>s.category==="missing-call").length;return[`checker: ${t}`,`model parsed by: ${e.conformance.modelParse}`,`writes: ${e.conformance.staticWrites.length} verified, ${n} waived`,`reads: ${e.conformance.staticReads.length} verified, ${r} waived`,`calls: ${o===0?"checked":`${o} missing`}`,`traces: ${e.conformance.traceStepsChecked} steps (key-diff; 'tla trace-check' proves acceptance)`,...i>0?[`referents: ${i} waived`]:[]].join(" | ")}function EA(e){let t=[],n=e.conformance.waivers.filter(i=>i.kind==="write").length,r=e.conformance.waivers.filter(i=>i.kind==="read").length;return n>0&&e.conformance.staticWrites.length===0&&t.push("NOTHING PROVEN ABOUT WRITES: every write fact found in this run was waived or unobserved."),r>0&&e.conformance.staticReads.length===0&&t.push("NOTHING PROVEN ABOUT READS: every read fact found in this run was waived or unobserved."),t}function Uy(e){let t=e.file&&e.startLine!==void 0&&e.endLine!==void 0?` ${U(e.file,e.startLine,e.endLine)}`:e.file?` ${e.file}`:"";console.log(`
|
|
641
641
|
[${e.severity}] ${e.category} (${e.evidence})${t}`),console.log(` ${e.message}`);for(let n of e.why)console.log(` why: ${n}`);console.log(` fix: ${e.remediation}`)}var Jy=["stats","files","methods","refs","trace","deps","rdeps","system","surface","dead","hotspots","imports","imported-by","unused-imports","outline","members","fan-in","fan-out","coupling","cycles","architecture","bottlenecks","isolated","by-kind","kind-counts","deep-chains","hierarchy","call-graph","similar","similar-files","react-component-duplicates","react-hook-candidates","react-large-component-pressure","vue-component-duplicates","vue-composable-candidates","vue-large-view-pressure","similar-chains","extract-candidates","locality-candidates","affected","change-surface","cleanup-plan","cleanup-apply","co-change","recent-duplicates","doc-drift","unused-params","diff-gate","incomplete-migration","tla","plan-context","drift","wrapper-candidates","passthrough-candidates","stale-abstractions","complexity-hotspots","self-audit","convergence","code","complexity","dataflow","slice","redundant-reexports","duplicate-bodies","twin-drift","twin-ab","not-implemented","decorative-checkers","test-quality","similar-signatures"],IA=[Xh,ny,Zh,Ci,ty,oy,Gy,ey],Ky=IA.flat(),AA=new Map(Ky.map(e=>[e.id,e]));for(let e of Ky)if(!Jy.includes(e.id))throw new Error(`Query command descriptor is not ordered: ${e.id}`);var rn=Jy.map(e=>jA(e));function jA(e){let t=AA.get(e);if(!t)throw new Error(`Unknown query command descriptor: ${e}`);return t}var OA=rn.slice(0,na("plan-context")),LA=rn.slice(Di("drift"),na("self-audit")),DA=rn.slice(Di("convergence"),na("slice")),MA=rn.slice(Di("redundant-reexports")),Cq=[{id:"reindex",command:"reindex",agent:w("Can the repository index be refreshed, and which language shards succeeded?","index generation, shard statuses, reuse diagnostics, and failures",[],"complete","repository"),description:"Index the codebase and convert to SQLite",options:T([p("-l, --language <lang>","Index only this language (can be repeated)",lt,[]),p("--pnpm-workspaces","Enable pnpm workspace support (TypeScript)"),p("--force","Rebuild even if source inputs are unchanged"),p("--allow-partial","Write an incomplete index when one or more detected languages fail"),p("--trust-project-tools","Permit reviewed indexers from this repository for this run"),p("--install-missing","Install missing global tools at reviewed immutable versions for this run"),p("--indexer-concurrency <n>","Number of language indexers to run at once",Ze)]),renderShape:"custom",docs:P("Indexing",["scip-query reindex"]),handler:Sg},{id:"augment-sources",command:"augment-sources",agent:w("Can source files omitted by upstream indexers be added to the index?","added document counts and augmentation status",[],"complete","repository"),description:"Add source files skipped by upstream SCIP indexers to the SQLite documents table",renderShape:"custom",docs:P("Indexing"),handler:vg},{id:"augment-vue",command:"augment-vue",agent:w("Can Vue SFC references be compiler-resolved and added to the index?","Vue augmentation counts, project, and diagnostics",[],"complete","repository"),description:"Add compiler-resolved Vue SFC references to the SQLite index using Volar",options:[p("--project <tsconfig>","Vue tsconfig path",void 0,"frontend/tsconfig.scip.json")],renderShape:"custom",docs:P("Indexing"),handler:Rg},...OA,{id:wt,command:wt,description:"Internal bounded diff-gate worker",hidden:!0,options:[p("--json","Emit the private worker envelope without transport pagination")],renderShape:"custom",handler:kg},{id:yn,command:yn,description:"Internal diff-impact batch worker",hidden:!0,options:[p("--json","Emit the private worker envelope without transport pagination"),p("--base <ref>","Git ref to diff against (default: HEAD)")],renderShape:"custom",handler:xg},{id:"diff-impact",command:"diff-impact",agent:w("Which symbols changed in this diff and which downstream consumers are affected?","changed symbols, downstream consumer identities, and impact paths",[],"bounded","diff"),description:"Compute changed symbols and downstream consumers from current git diff",options:T([p("--base <ref>","Git ref to diff against (default: HEAD)")]),renderShape:"custom",docs:P("Impact"),handler:wg},...LA,{id:hn,command:hn,description:"Internal health phase worker",hidden:!0,arguments:[{name:"<phase>"}],options:[p("--json","Emit the private worker envelope without transport pagination"),p("-s, --scope <path>","Limit to files matching path"),p("--full","Run unbounded candidate analyses on large indexes")],renderShape:"custom",handler:$g},{id:"health",command:"health",agent:w("What are the highest-priority verified health problems in this codebase?","health score, findings, priorities, baselines, and coverage notes",[],"bounded","repository"),description:"Composite codebase health report with prioritized action list",options:T([p("-s, --scope <path>","Limit to files matching path"),p("--full","Run unbounded candidate analyses on large indexes"),p("--baseline","Compare findings against the committed baseline; exit 1 on new findings"),p("--write-baseline","Snapshot current finding identities to the baseline file")]),renderShape:"custom",docs:P("Health",["scip-query health --json","scip-query health --baseline"]),handler:Cg},{id:"bench",command:"bench",agent:w("How fast are indexing and selected commands under this benchmark matrix?","timings, command outcomes, environment, and optional profiles",[],"sampled","repository"),description:"Benchmark indexing and command runtimes for this repository",options:T([p("--cold-index","Temporarily clear this project index cache and measure a cold rebuild"),p("--include-heavy","Include expensive full-detector commands in the command matrix"),p("--command <cmd>","Benchmark a specific scip-query command (can be repeated)",lt,[]),p("--timeout-ms <n>","Per-command timeout in milliseconds",Ze,18e4),p("--progress","Print benchmark command start/finish progress to stderr"),p("--profile","Enable low-overhead phase profiling in benchmarked commands"),p("--profile-out <path>","Append benchmark and phase profile events as JSONL")]),renderShape:"custom",docs:P("Maintenance",["scip-query bench","scip-query bench --json --cold-index"]),handler:Pg},{id:"work-audit",command:"work-audit <profile>",agent:w("Which repeated computations in this profile waste the most measured time?","ranked repeated-work groups, counts, and avoidable duration",["path"],"bounded"),description:"Rank exact repeated computations in a profiling JSONL file by measured avoidable time",options:T([p("--top <n>","Maximum repeated-work groups to show",Ze,20)]),evidence:"mixed",renderShape:"custom",docs:P("Maintenance",["scip-query work-audit profile.jsonl","scip-query work-audit profile.jsonl --json"]),handler:Tg},{id:"typescript-semantic-compare",command:"typescript-semantic-compare",description:"Compare tsserver reference answers against the ts-morph baseline",hidden:!0,options:[p("-s, --scope <path>","Limit compared definitions to files matching path"),p("--limit <n>","Maximum definitions to compare unless --full is set",Ze),p("--max-mismatches <n>","Maximum mismatch details to include in output",qt),p("--full","Compare every indexed TypeScript-like definition"),p("--json","Output as JSON for programmatic consumption")],evidence:"mixed",renderShape:"custom",handler:Eg},...DA,{id:"install-skills",command:"install-skills",agent:w("Which scip-query skills were installed, updated, skipped, or conflicted?","skill target paths and install outcomes",[],"complete","repository"),description:`Install skills (${Wr.join(", ")}) into Claude Code, Codex, and shared agent roots`,renderShape:"custom",docs:P("Maintenance"),handler:Og},{id:"setup-hooks",command:"setup-hooks",agent:w("Were project-local agent hooks installed or removed safely?","hook config targets, changes, skips, and warnings",[],"complete","repository"),description:"Install or refresh project-local Codex and Claude Code lifecycle hooks",options:T([p("--shared","Deprecated compatibility flag; hooks remain checkout-local and untracked"),p("--remove","Remove managed project hooks and remember the opt-out"),p("--force","Reinstall hooks even after a previous --remove opt-out"),p("--dry-run","With --remove, preview exact hook changes without writing")]),renderShape:"custom",docs:P("Maintenance",["scip-query setup-hooks","scip-query setup-hooks --json"]),handler:Lg},{id:"hook-context",command:"hook-context",description:"Internal agent lifecycle hook context renderer",hidden:!0,renderShape:"custom",handler:dp},{id:"hook-pretool",command:"hook-pretool",description:"Internal Claude PreToolUse evidence-integrity guard",hidden:!0,renderShape:"custom",handler:up},{id:"hook-stop",command:"hook-stop",description:"Internal agent Stop hook wrapper for diff-gate",hidden:!0,renderShape:"custom",handler:mp},{id:"check-deps",command:"check-deps",agent:w("Which scip-query and language-indexer dependencies are runnable?","dependency readiness statuses and remediation",[],"complete","repository"),description:"Check whether scip-query and the detected language indexers are actually runnable",renderShape:"custom",docs:P("Maintenance"),handler:Dg},{id:"capabilities",command:"capabilities",agent:w("Which evidence and verification capabilities are available here?","capability matrix with availability and reasons",[],"complete","repository"),description:"Report which evidence and verification capabilities are available in this project",options:T([p("--matrix","Render the project capability matrix (default output)")]),renderShape:"custom",docs:P("Maintenance"),handler:Mg},{id:"capability-matrix",command:"capability-matrix",agent:w("Which evidence and verification capabilities are available here?","deprecated alias of the capability matrix",[],"complete","repository"),description:"Deprecated alias for capabilities --matrix",options:T(),renderShape:"custom",docs:P("Maintenance"),handler:Ng},...MA,{id:"init",command:"init",agent:w("Can a starter scip-query configuration be created for this project?","configuration path and creation outcome",[],"complete","repository"),description:"Create a .scipquery.json config file for this project",renderShape:"custom",docs:P("Maintenance"),handler:_g},{id:"config-validate",command:"config-validate",agent:w("Is this project configuration valid and internally consistent?","validation diagnostics with config paths",[],"complete","repository"),description:"Validate .scipquery.json, including structured suppressions and declared coupling groups",options:T(),renderShape:"custom",docs:P("Maintenance",["scip-query config-validate"]),handler:Bg},{id:"suppress",command:"suppress <id>",agent:w("Can this accepted finding be recorded with an auditable reason?","suppression identity, path, scope, and expiry",["finding"],"complete"),description:"Record an accepted finding as a file under .scipquery/suppressions/ with a required reason",options:T([p("--reason <text>","Required concrete claim explaining why the detector remediation is inapplicable"),p("--reason-code <code>","Required adjudication code: compatibility-shim, generated-code, detector-counterexample, and related policies"),p("--evidence <kind:referent>","Required counterevidence; repeat source/config/test paths or exact graph commands",lt,[]),p("--check <check>","Optional detector/check name to narrow the suppression"),p("--file <path>","Optional file path to narrow the suppression"),p("--expires-at <iso>","Optional ISO date after which the suppression expires"),p("--replace <revision>","Replace a different existing decision only when it still has this reported SHA-256 revision")]),renderShape:"custom",docs:P("Maintenance",['scip-query suppress SQABC123DEF456 --reason-code compatibility-shim --evidence source:src/compat.ts --reason "v1 remains public"']),handler:qg},{id:"effectiveness",command:"effectiveness",agent:w("What handling outcomes has diff-gate observed, and what authority produced those observations?","per-check caught, fixed, suppressed, unresolved, provenance, and resolution-vs-suppression telemetry",[],"complete","repository"),description:"Per-check repository telemetry from the committed outcome ledger: verified fixes, suppressions, unresolved findings, observer authority, and anomalies",options:T([p("--since <window>","Only count findings first caught in this window (30d, 12w, or an ISO date)"),p("--check <check>","Restrict to one diff-gate check")]),renderShape:"custom",docs:P("Maintenance",["scip-query effectiveness --since 30d","scip-query effectiveness --check echo --json"]),handler:Vg},{id:"doctor",command:"doctor",agent:w("Why is scip-query unhealthy or unavailable in this project?","config, freshness, dependency, and capability diagnostics",[],"complete","repository"),description:"Diagnose config, index freshness, dependency readiness, and project capabilities",options:T(),renderShape:"custom",docs:P("Maintenance"),handler:Wg},{id:"setup",command:"setup",agent:w("Can scip-query be bootstrapped end to end in this project?","setup step outcomes, files, capabilities, smoke tests, and warnings",[],"complete","repository"),description:"Bootstrap this project: enable automatic indexing, install agent skills, refresh the index, verify capabilities, and report health",options:T([p("--guided","Require and open the interactive terminal checklist (the default in a terminal)"),p("--yes","Accept recommended setup defaults without prompting"),p("--git-hook","Also install a git pre-commit hook that runs diff-gate"),p("--no-hooks","Skip Codex and Claude Code lifecycle hook installation"),p("--no-skills","Skip user-level agent skill installation"),p("--no-parsers","Skip Tree-sitter AST parser installation and repair"),p("--install-missing","Install missing global tools at reviewed immutable versions"),p("--no-health","Skip the optional full health audit and dossier"),p("--dossier-dir <path>","Directory for generated setup health dossier files")]),renderShape:"custom",docs:P("Maintenance",["scip-query setup","scip-query setup --install-missing","scip-query setup --json"]),handler:Ug},{id:"setup-agent",command:"setup-agent",agent:w("Can project agent guidance and optional git enforcement be seeded?","written, unchanged, and skipped agent files or hooks",[],"complete","repository"),description:"Seed agent guidance for this project: AGENTS.md/CLAUDE.md block pointing agents at the scip-query skills and diff gate, plus an optional git pre-commit backstop",options:[p("--git-hook","Also install a git pre-commit hook that runs diff-gate")],renderShape:"custom",docs:P("Maintenance",["scip-query setup-agent","scip-query setup-agent --git-hook"]),handler:Gg},{id:"setup-ci",command:"setup-ci",agent:w("Can a CI workflow enforce reindex and diff-gate on pull requests?","workflow path, rendered content, and write outcome",[],"complete","repository"),description:"Write a GitHub Actions workflow that runs scip-query reindex and diff-gate on pull requests",options:[p("--force","Overwrite an existing workflow"),p("--dry-run","Print the workflow without writing it")],renderShape:"custom",docs:P("Maintenance",["scip-query setup-ci"]),handler:Jg},{id:"uninstall",command:"uninstall",agent:w("Which scip-query-owned integrations can be removed without touching user-owned files?","removed, retained, skipped, and dry-run targets",[],"complete","repository"),description:"Remove selected scip-query-owned integrations; real removal requires exactly one of --global or --project",options:T([p("--global","Remove scip-query-owned skill symlinks from user-level agent skill roots"),p("--project","Remove project-local hooks and managed AGENTS.md/CLAUDE.md blocks"),p("--dry-run","List what would be removed without changing files"),p("--verbose","List every unrelated global skill entry left in place")]),renderShape:"custom",docs:P("Maintenance",["scip-query uninstall --dry-run","scip-query uninstall --project"]),handler:Kg},{id:"watch",command:"watch",agent:w("What is the watcher doing, or can its background service be started or stopped?","watcher/service state, generation, activity, and errors",[],"complete","repository"),description:"Watch in the foreground or manage the per-project background refresh service",options:T([p("--daemon","Ensure the demand-started background service is running; timing flags apply only at start"),p("--status","Show background/foreground watcher state"),p("--stop","Stop the watcher or background service for this project"),p("--debounce <ms>","Process-local ms to wait after last change (default: 250)",qt),p("--cooldown <ms>","Process-local min ms between reindexes; 0 disables spacing (default: 5000)",qt),p("--git-poll <ms>","Process-local ms between Git HEAD/index checks (default: 2000)",qt),p("--idle-timeout <ms>","Process-local ms before clean-idle daemon exit; 0 keeps it running (default: 600000)",qt)]),renderShape:"custom",docs:P("Maintenance",["scip-query watch","scip-query watch --daemon","scip-query watch --status --json","scip-query watch --stop"]),handler:zg},{id:"status",command:"status",agent:w("Is the index fresh, complete, and usable for this project?","freshness, generation, language shards, watcher, and optional capabilities",[],"complete","repository"),description:"Show index status for this project",options:T([p("--capabilities","Include the project capability matrix")]),renderShape:"custom",docs:P("Maintenance"),handler:Xg}];function Di(e){let t=rn.findIndex(n=>n.id===e);if(t<0)throw new Error(`Ordered query command descriptor is missing: ${e}`);return t}function na(e){return Di(e)+1}export{Cq as commandDescriptors};
|
|
642
|
-
//# sourceMappingURL=command-descriptors-
|
|
642
|
+
//# sourceMappingURL=command-descriptors-DSS46KXI.js.map
|
package/dist/postinstall.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import"./chunk-KFZNKUNT.js";import{existsSync as n,mkdirSync as i,symlinkSync as o,readlinkSync as
|
|
2
|
+
import"./chunk-KFZNKUNT.js";import{existsSync as n,mkdirSync as i,symlinkSync as o,readlinkSync as r,unlinkSync as l,readdirSync as c}from"fs";import{join as u,dirname as p,resolve as d,relative as k,isAbsolute as g}from"path";import{homedir as m,platform as e}from"os";import{fileURLToPath as h}from"url";var y=e()==="win32";function s(){console.log("scip-query installed (Node.js 24 LTS recommended; minimum Node.js 22) -- run 'scip-query setup' in a repo to enable skills, hooks, and the index.")}s();
|
|
3
3
|
//# sourceMappingURL=postinstall.js.map
|
package/dist/runtime.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as B,b as K,c as Y}from"./chunk-RXOXSKY3.js";import{e as k,i as ke,j as Pe,k as Te,o as q,s as J,t as H}from"./chunk-JN4NMBEX.js";import{a as U}from"./chunk-7PIO7NKH.js";import"./chunk-DHEQMPLW.js";import{e as C,g as F,l as D,o as
|
|
2
|
-
`}import{createHash as Q}from"crypto";import{closeSync as Ie,fstatSync as Z,openSync as Oe,rmSync as je}from"fs";import{dirname as Ne}from"path";var Me=2e3,Ae=10,$e=3,b=class extends Error{constructor(r,n,i){super(`Concurrent edit detected for ${r}; expected revision ${te(n)}, but found ${te(i)}. The latest file was left untouched.`);this.path=r;this.original=n;this.latest=i;this.name="FileRevisionConflictError"}path;original;latest};function re(e,t,r={}){let n=We(e,r.lockTimeoutMs??Me,r.monotonicNow??C);try{let i=Math.max(0,Math.floor(r.maxRetries??$e));for(let o=0;;o+=1){let s=x(e),a=t(s,o);if(a.kind==="unchanged")return{changed:!1,attempts:o+1,previous:s,current:s};r.onBeforeCommit?.({attempt:o,snapshot:s,mutation:a});let c=x(e);if(!De(s.revision,c.revision)){if(o<i)continue;throw new b(e,s.revision,c.revision)}try{Fe(e,a,s.revision)}catch(u){if(u.code==="EEXIST"){let p=x(e);if(o<i)continue;throw new b(e,s.revision,p.revision)}throw u}return{changed:!0,attempts:o+1,previous:s,current:x(e)}}}finally{n.release()}}function x(e){for(let t=0;t<4;t+=1){let r;try{r=Oe(e,"r");let n=ee(Z(r)),i=W(r,{maxBytes:A,inputKind:"revisioned text file"}),o=ee(Z(r));if(!ne(n,o))continue;return{path:e,text:i,revision:{exists:!0,hash:Q("sha256").update(i).digest("hex"),identity:o}}}catch(n){if(n.code==="ENOENT")return{path:e,text:"",revision:{exists:!1,hash:Q("sha256").update("").digest("hex")}};throw n}finally{r!==void 0&&Ie(r)}}throw new Error(`Could not read a stable revision of ${e}; the file is changing continuously.`)}function We(e,t,r){let n=`${e}.scip-query-write.lock`,i=r()+Math.max(0,t);for(;;){let o=F(n,{kind:"revisioned-file-mutation",detail:{target:e}});if(o.kind==="acquired")return o.lock;if(r()>=i)throw new Error(`Timed out after ${t}ms waiting to update ${e}; the file was left untouched.`);Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,Ae)}}function Fe(e,t,r){if(t.kind==="delete"){if(!r.exists)return;je(e),D(Ne(e));return}let n=t.mode??r.identity?.mode;r.exists?V(e,t.text,{durability:"durable",mode:n}):L(e,t.text,{durability:"durable",mode:n})}function De(e,t){return e.exists===t.exists&&e.hash===t.hash&&(e.identity===void 0?t.identity===void 0:t.identity!==void 0&&ne(e.identity,t.identity))}function ee(e){return{dev:e.dev,ino:e.ino,size:e.size,mtimeMs:e.mtimeMs,mode:e.mode&511}}function ne(e,t){return e.dev===t.dev&&e.ino===t.ino&&e.size===t.size&&e.mtimeMs===t.mtimeMs&&e.mode===t.mode}function te(e){return e.exists?e.hash.slice(0,12):"<absent>"}var S=".scipquery.json",oe=250,se=5e3,ae=10*6e4,Le={enabled:!1,debounceMs:oe,cooldownMs:se,gitPollMs:2e3,idleTimeoutMs:ae,autoRefresh:!0,ignore:[]};var Bt=new Set(N);function T(e){let t=ie(e,S);if(!Ve(t))return{};let r;try{r=$(t,{maxBytes:M,inputKind:"scip-query project config"})}catch(n){let i=n instanceof Error?n.message:String(n);throw new Error(`unable to read ${S} at ${t}: ${i}`,{cause:n})}return Je(z(r),t,"read").config}function ce(e){return{...Le,...e.watch}}function Ge(e,t){return Ue(e,t).configPath}function Ue(e,t){let r=ie(e,S),n={languages:t,watch:{enabled:!0,debounceMs:oe,cooldownMs:se,gitPollMs:2e3,idleTimeoutMs:ae,autoRefresh:!0}},i=re(r,o=>o.revision.exists?{kind:"unchanged"}:{kind:"write",text:qe(n)});return{configPath:r,changed:i.changed}}function qe(e){return X(e)}function Je(e,t,r){if(e.kind==="legacy"||e.kind==="supported")return e;if(e.kind==="malformed"){let i=r==="read"?`invalid ${S} at ${t}: ${e.reason}`:`Cannot update ${t}: the latest project config is ${e.reason}.`;throw new Error(`${i} The file was left untouched.`)}let n=r==="read"?`invalid ${S} at ${t}`:`Cannot update ${t}: the latest project config is invalid`;throw new Error(`${n} (unsupported ${e.direction} schemaVersion ${e.schemaVersion}; this scip-query reads legacy v${h} and current v${g}). Upgrade scip-query before retrying; the file was left untouched.`)}import{statSync as He}from"fs";import{basename as Be,isAbsolute as Ke,join as Ye,relative as ze}from"path";import{watch as Xe}from"chokidar";import Qe from"ignore";var pe=5e3,_=class{projectRoot;config;watchConfig;languages;pnpmWorkspaces;typescriptProjectMode;typescriptProjects;clojureConfigPath;indexerConcurrency;onStatus;onReindexComplete;onReindexError;onRefreshSuppressed;onError;reindexRunner;subscriptionFactory;clock;activeOperation=null;stopPromise=null;stopInProgress=!1;status={state:"idle"};debounceTimer=null;cooldownTimer=null;dirty=!1;changedFiles=0;pendingTrigger=null;reindexInFlight=!1;lastReindexEnd=0;fsWatchers=[];sourcePollingFallbackStarted=!1;gitPollTimer=null;lastGitState=null;gitignoreFilter;extraIgnore;stopped=!1;constructor(t){this.projectRoot=t.projectRoot,this.config=t.config,this.watchConfig=ce(t.config),this.languages=t.languages,this.pnpmWorkspaces=t.config.indexer?.typescript?.pnpmWorkspaces??!1,this.typescriptProjectMode=t.config.indexer?.typescript?.projectMode,this.typescriptProjects=t.config.indexer?.typescript?.projects,this.clojureConfigPath=t.config.indexer?.clojure?.configPath,this.indexerConcurrency=t.config.indexerConcurrency,this.onStatus=t.onStatus??(()=>{}),this.onReindexComplete=t.onReindexComplete??(()=>{}),this.onReindexError=t.onReindexError??(()=>{}),this.onRefreshSuppressed=t.onRefreshSuppressed??(()=>{}),this.onError=t.onError??(r=>console.error(r.message)),this.clock=t.clock??rt,he.set(this,lt(t.stopTimeoutMs??pe,"watcher stop timeout")),this.reindexRunner=t.reindexRunner??ge(),this.subscriptionFactory=t.subscriptionFactory??nt,this.gitignoreFilter=U(t.projectRoot),this.extraIgnore=Qe(),this.watchConfig.ignore.length>0&&this.extraIgnore.add(this.watchConfig.ignore)}start(){if(this.stopInProgress)throw new Error("Cannot restart a watcher while its previous ownership is still draining.");this.stopped=!1,this.stopPromise=null,E(this).errors=[],this.sourcePollingFallbackStarted=!1,this.setStatus({state:"idle"}),this.startGitStatePolling();try{this.startSourceWatcher()}catch(t){this.onError(new Error(`Failed to watch ${this.projectRoot}: ${String(t)}`))}}stop(){if(this.stopPromise)return this.stopPromise;this.stopped=!0,this.stopInProgress=!0;let t=this.fsWatchers;this.fsWatchers=[],this.clearDebounceTimer(),this.clearCooldownTimer(),this.clearGitPollTimer();let r=this.activeOperation;r&&this.setStatus({state:"draining",startedAt:this.wallNow(),reason:"waiting for the active reindex worker to exit"});let n=[...E(this).closures],i=et(this),o=this.clock.now()+i;return this.stopPromise=this.finishStop(t,n,r,o,i).catch(s=>{throw this.stopInProgress=!1,s}),this.stopPromise}requestRefresh(t,r={}){if(!this.stopped){if(!r.immediate||this.reindexInFlight||this.status.state==="cooldown"){this.scheduleReindex(t);return}this.pendingTrigger=de(this.pendingTrigger,t),this.changedFiles+=1,this.clearDebounceTimer(),this.triggerReindex()}}startSourceWatcher(t=!1){let r=this.subscriptionFactory(this.projectRoot,{ignoreInitial:!0,ignored:(n,i)=>this.isIgnoredWatchPath(n,i?.isDirectory()??!1),usePolling:t,...t?{interval:500,binaryInterval:1e3}:{}});r.on("all",(n,i)=>{this.stopped||this.handleFileChange(i)}),r.on("error",n=>this.handleSourceWatcherError(r,n,t)),this.fsWatchers.push(r)}handleSourceWatcherError(t,r,n){if(n||this.sourcePollingFallbackStarted||!ct(r)||this.stopped){this.onError(new Error(`Failed to watch ${this.projectRoot}: ${String(r)}`));return}this.sourcePollingFallbackStarted=!0,this.fsWatchers=this.fsWatchers.filter(i=>i!==t),tt(E(this),t,i=>this.onError(i));try{this.startSourceWatcher(!0)}catch(i){this.onError(new Error(`Failed to watch ${this.projectRoot}: ${String(i)}`))}}isIgnoredWatchPath(t,r){let n=this.relativeWatchPath(t);if(!n)return!1;let i=r?`${n}/`:n;return i===".git/"||i.startsWith(".git/")?!0:this.gitignoreFilter.isIgnored(i)||this.extraIgnore.ignores(i)}handleFileChange(t){let r=this.relativeWatchPath(t);!r||r===".."||r.startsWith("../")||r===".git"||r.startsWith(".git/")||this.gitignoreFilter.isIgnored(r)||this.extraIgnore.ignores(r)||r.endsWith("index.db")||r.endsWith("index.scip")||r.endsWith("index.db.tmp")||Be(r).startsWith(q)||this.scheduleReindex({kind:"watch-source",detail:r})}relativeWatchPath(t){let r=Ke(t)?t:Ye(this.projectRoot,t);return ze(this.projectRoot,r).replaceAll("\\","/")}scheduleReindex(t){if(this.pendingTrigger=de(this.pendingTrigger,t),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 r=this.wallNow()+this.watchConfig.debounceMs;this.setStatus({state:"waiting",changedFiles:this.changedFiles,reindexAt:r}),this.debounceTimer=this.clock.setTimeout(()=>{this.debounceTimer=null,this.triggerReindex()},this.watchConfig.debounceMs)}triggerReindex(){if(this.reindexInFlight||this.stopped)return;let t=this.clock.now()-this.lastReindexEnd;if(this.lastReindexEnd>0&&t<this.watchConfig.cooldownMs){let o=this.watchConfig.cooldownMs-t;this.dirty=!0;let s=this.wallNow()+o;this.setStatus({state:"cooldown",until:s,dirty:!0}),this.cooldownTimer=this.clock.setTimeout(()=>{this.cooldownTimer=null,this.dirty&&!this.stopped&&(this.dirty=!1,this.triggerReindex())},o);return}this.reindexInFlight=!0,this.dirty=!1,this.changedFiles=0;let r=this.pendingTrigger??{kind:"watch-source"};this.pendingTrigger=null;let n=this.wallNow();this.setStatus({state:"indexing",startedAt:n});let i=this.reindexRunner.start(this.reindexRequest(r));this.activeOperation=i,i.completion.then(o=>{if(this.reindexInFlight=!1,this.lastReindexEnd=this.clock.now(),this.stopped)return;let s=!1;try{s=this.onReindexComplete(o,r)===!0}catch(a){this.onError(a instanceof Error?a:new Error(String(a)))}if(this.dirty&&!this.stopped){if(s){let c=this.pendingTrigger??{kind:"unknown"};this.dirty=!1,this.changedFiles=0,this.pendingTrigger=null,this.onRefreshSuppressed(c),this.setStatus({state:"idle"});return}let a=this.wallNow()+this.watchConfig.cooldownMs;this.setStatus({state:"cooldown",until:a,dirty:!0}),this.cooldownTimer=this.clock.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(o=>{if(this.reindexInFlight=!1,this.lastReindexEnd=this.clock.now(),this.stopped)return;let s=o instanceof Error?o:new Error(String(o));this.onReindexError(s,r),this.onError(s),this.setStatus({state:"idle"})}).finally(()=>{this.activeOperation===i&&(this.activeOperation=null)})}async finishStop(t,r,n,i,o){let s=[],a=t.map(async d=>{try{await d.close()}catch(R){s.push(`watch subscription close failed: ${String(R)}`)}});a.push(...r),n&&a.push((async()=>{try{let d=await n.cancel();d.state==="degraded"&&s.push(d.reason)}catch(d){s.push(`reindex cancellation failed: ${d instanceof Error?d.message:String(d)}`)}})());let c=a.length,u=a.map(d=>d.finally(()=>{c-=1})),p=await Ze(u,i,this.clock),l=E(this);return s.push(...l.errors),l.errors=[],p?this.stopInProgress=!1:(s.push(`watch shutdown exceeded the ${o}ms deadline with ${c} operation(s) still pending`),Promise.all(u).then(()=>{this.stopInProgress=!1})),s.length>0?(this.setStatus({state:"draining",startedAt:this.wallNow(),reason:s.join("; ")}),{state:"degraded",reasons:s}):(this.setStatus({state:"idle"}),{state:"stopped"})}wallNow(){return this.clock.wallNow?.()??this.clock.now()}reindexRequest(t){return{projectRoot:this.projectRoot,config:this.config,languages:this.languages,pnpmWorkspaces:this.pnpmWorkspaces,typescriptProjectMode:this.typescriptProjectMode,typescriptProjects:this.typescriptProjects,clojureConfigPath:this.clojureConfigPath,indexerConcurrency:this.indexerConcurrency,trigger:t}}setStatus(t){this.status=t,this.onStatus(t)}clearDebounceTimer(){this.debounceTimer&&(this.clock.clearTimeout(this.debounceTimer),this.debounceTimer=null)}clearCooldownTimer(){this.cooldownTimer&&(this.clock.clearTimeout(this.cooldownTimer),this.cooldownTimer=null)}startGitStatePolling(){this.lastGitState=this.readGitState(),this.lastGitState&&(this.gitPollTimer=this.clock.setInterval(()=>this.pollGitState(),this.watchConfig.gitPollMs),this.gitPollTimer.unref?.())}pollGitState(){let t=this.lastGitState,r=this.readGitState();if(!t||!r||this.stopped){this.lastGitState=r;return}this.lastGitState=r;let n=t.head!==r.head,i=t.indexPath!==r.indexPath||t.indexMtimeMs!==r.indexMtimeMs||t.indexSize!==r.indexSize;n&&i?this.scheduleReindex({kind:"watch-git-state",detail:"HEAD and index changed"}):n?this.scheduleReindex({kind:"watch-git-head",detail:"HEAD changed"}):i&&this.scheduleReindex({kind:"watch-git-index",detail:r.indexPath??"index changed"})}readGitState(){let t=w(this.projectRoot,["rev-parse","--git-path","index"]);if(!t)return null;let r=G(this.projectRoot,t),n={head:w(this.projectRoot,["rev-parse","--verify","HEAD"]),indexPath:r};try{let i=He(r);n.indexMtimeMs=i.mtimeMs,n.indexSize=i.size}catch{n.indexMtimeMs=void 0,n.indexSize=void 0}return n}clearGitPollTimer(){this.gitPollTimer&&(this.clock.clearInterval(this.gitPollTimer),this.gitPollTimer=null)}};async function Ze(e,t,r){if(e.length===0)return!0;let n=Promise.all(e).then(()=>!0),i=Math.max(0,t-r.now()),o=null,s=new Promise(c=>{o=r.setTimeout(()=>c(!1),i)}),a=await Promise.race([n,s]);return a&&o&&r.clearTimeout(o),a}var le=new WeakMap,he=new WeakMap;function E(e){let t=le.get(e);if(t)return t;let r={closures:new Set,errors:[]};return le.set(e,r),r}function et(e){return he.get(e)??pe}function tt(e,t,r){let n=Promise.resolve().then(()=>t.close()).catch(i=>{let o=`watch subscription close failed during polling fallback: ${String(i)}`;e.errors.push(o),r(new Error(o))});e.closures.add(n),n.then(()=>e.closures.delete(n))}function fe(e){let{projectRoot:t,config:r,languages:n,pnpmWorkspaces:i,typescriptProjectMode:o,typescriptProjects:s,clojureConfigPath:a,indexerConcurrency:c,trigger:u}=e,p=T(t),l=Object.keys(p).length>0?p:r,d=k(t,l),R=l.indexer?.typescript,we=l.indexer?.clojure;return{workerPath:new URL("./reindex-worker.js",import.meta.url).pathname,env:{...process.env,SCIP_REINDEX_PROJECT_ROOT:t,SCIP_REINDEX_OUTPUT_SCIP:d.indexPath,SCIP_REINDEX_OUTPUT_DB:d.dbPath,SCIP_REINDEX_LANGUAGES:(l.languages??n)?.join(",")??"",SCIP_REINDEX_INDEXER_CONCURRENCY:String(l.indexerConcurrency??c??""),SCIP_REINDEX_PNPM_WORKSPACES:R?.pnpmWorkspaces??i?"1":"",SCIP_REINDEX_TYPESCRIPT_CONFIG:JSON.stringify({projectMode:R?.projectMode??o,projects:R?.projects??s??[]}),SCIP_REINDEX_CLOJURE_CONFIG_PATH:we?.configPath??a??"",SCIP_REINDEX_TRIGGER_KIND:u.kind,SCIP_REINDEX_TRIGGER_DETAIL:u.detail??"",SCIP_REINDEX_PROCESS_GROUP_LEADER:"1"}}}var rt={now:C,wallNow:()=>Date.now(),setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e)},nt=(e,t)=>Xe(e,t),it=15*6e4,ot=1e3,st=64*1024;function at(){return{stdoutTail:"",stderrTail:"",stdoutTruncated:!1,stderrTruncated:!1}}function ue(e,t){let r=e instanceof Error?e.message:String(e),n=t.stderrTail.trim()||t.stdoutTail.trim();return n?`${r}
|
|
1
|
+
import{a as B,b as K,c as Y}from"./chunk-RXOXSKY3.js";import{e as k,i as ke,j as Pe,k as Te,o as q,s as J,t as H}from"./chunk-JN4NMBEX.js";import{a as U}from"./chunk-7PIO7NKH.js";import"./chunk-DHEQMPLW.js";import{e as C,g as F,l as D,o as L,p as V,x as w,y as G}from"./chunk-BS2NMXQZ.js";import{a as f,d as N,f as M,g as A,l as $,n as W}from"./chunk-2KAZEZ6M.js";import"./chunk-C3KV2II6.js";import{existsSync as Le}from"fs";import{isAbsolute as Lt,join as ie,relative as Vt,resolve as Gt}from"path";var h=1,g=2,_e="./node_modules/scip-query/docs/schemas/project-config.schema.json";function z(e){let t=e;if(typeof e=="string")try{t=JSON.parse(e)}catch(a){return{kind:"malformed",reason:`invalid JSON: ${a instanceof Error?a.message:String(a)}`}}if(!f(t))return{kind:"malformed",reason:"project config must be a JSON object"};let r=t.schemaVersion;if(r!==void 0&&!Number.isInteger(r))return{kind:"malformed",reason:"schemaVersion must be an integer"};let n=r===void 0?h:r;if(n!==h&&n!==g)return{kind:"unsupported",schemaVersion:n,direction:n<h?"older":"future"};let i=t.$schema;if(i!==void 0&&(typeof i!="string"||i.trim()===""))return{kind:"malformed",reason:"$schema must be a non-empty string when present"};let o=P(t),s=n!==g||typeof t.$schema!="string";return n===h?{kind:"legacy",sourceVersion:h,config:o,needsMigration:s}:{kind:"supported",sourceVersion:g,config:o,needsMigration:s}}function P(e){let t=e,{$schema:r,schemaVersion:n,...i}=t;return{$schema:typeof r=="string"&&r.trim()!==""?r:_e,schemaVersion:g,...i}}function X(e){return`${JSON.stringify(P(e),null,2)}
|
|
2
|
+
`}import{createHash as Q}from"crypto";import{closeSync as Ie,fstatSync as Z,openSync as Oe,rmSync as je}from"fs";import{dirname as Ne}from"path";var Me=2e3,Ae=10,$e=3,b=class extends Error{constructor(r,n,i){super(`Concurrent edit detected for ${r}; expected revision ${te(n)}, but found ${te(i)}. The latest file was left untouched.`);this.path=r;this.original=n;this.latest=i;this.name="FileRevisionConflictError"}path;original;latest};function re(e,t,r={}){let n=We(e,r.lockTimeoutMs??Me,r.monotonicNow??C);try{let i=Math.max(0,Math.floor(r.maxRetries??$e));for(let o=0;;o+=1){let s=x(e),a=t(s,o);if(a.kind==="unchanged")return{changed:!1,attempts:o+1,previous:s,current:s};r.onBeforeCommit?.({attempt:o,snapshot:s,mutation:a});let c=x(e);if(!De(s.revision,c.revision)){if(o<i)continue;throw new b(e,s.revision,c.revision)}try{Fe(e,a,s.revision)}catch(u){if(u.code==="EEXIST"){let p=x(e);if(o<i)continue;throw new b(e,s.revision,p.revision)}throw u}return{changed:!0,attempts:o+1,previous:s,current:x(e)}}}finally{n.release()}}function x(e){for(let t=0;t<4;t+=1){let r;try{r=Oe(e,"r");let n=ee(Z(r)),i=W(r,{maxBytes:A,inputKind:"revisioned text file"}),o=ee(Z(r));if(!ne(n,o))continue;return{path:e,text:i,revision:{exists:!0,hash:Q("sha256").update(i).digest("hex"),identity:o}}}catch(n){if(n.code==="ENOENT")return{path:e,text:"",revision:{exists:!1,hash:Q("sha256").update("").digest("hex")}};throw n}finally{r!==void 0&&Ie(r)}}throw new Error(`Could not read a stable revision of ${e}; the file is changing continuously.`)}function We(e,t,r){let n=`${e}.scip-query-write.lock`,i=r()+Math.max(0,t);for(;;){let o=F(n,{kind:"revisioned-file-mutation",detail:{target:e}});if(o.kind==="acquired")return o.lock;if(r()>=i)throw new Error(`Timed out after ${t}ms waiting to update ${e}; the file was left untouched.`);Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,Ae)}}function Fe(e,t,r){if(t.kind==="delete"){if(!r.exists)return;je(e),D(Ne(e));return}let n=t.mode??r.identity?.mode;r.exists?L(e,t.text,{durability:"durable",mode:n}):V(e,t.text,{durability:"durable",mode:n})}function De(e,t){return e.exists===t.exists&&e.hash===t.hash&&(e.identity===void 0?t.identity===void 0:t.identity!==void 0&&ne(e.identity,t.identity))}function ee(e){return{dev:e.dev,ino:e.ino,size:e.size,mtimeMs:e.mtimeMs,mode:e.mode&511}}function ne(e,t){return e.dev===t.dev&&e.ino===t.ino&&e.size===t.size&&e.mtimeMs===t.mtimeMs&&e.mode===t.mode}function te(e){return e.exists?e.hash.slice(0,12):"<absent>"}var S=".scipquery.json",oe=250,se=5e3,ae=10*6e4,Ve={enabled:!1,debounceMs:oe,cooldownMs:se,gitPollMs:2e3,idleTimeoutMs:ae,autoRefresh:!0,ignore:[]};var Bt=new Set(N);function T(e){let t=ie(e,S);if(!Le(t))return{};let r;try{r=$(t,{maxBytes:M,inputKind:"scip-query project config"})}catch(n){let i=n instanceof Error?n.message:String(n);throw new Error(`unable to read ${S} at ${t}: ${i}`,{cause:n})}return Je(z(r),t,"read").config}function ce(e){return{...Ve,...e.watch}}function Ge(e,t){return Ue(e,t).configPath}function Ue(e,t){let r=ie(e,S),n={languages:t,watch:{enabled:!0,debounceMs:oe,cooldownMs:se,gitPollMs:2e3,idleTimeoutMs:ae,autoRefresh:!0}},i=re(r,o=>o.revision.exists?{kind:"unchanged"}:{kind:"write",text:qe(n)});return{configPath:r,changed:i.changed}}function qe(e){return X(e)}function Je(e,t,r){if(e.kind==="legacy"||e.kind==="supported")return e;if(e.kind==="malformed"){let i=r==="read"?`invalid ${S} at ${t}: ${e.reason}`:`Cannot update ${t}: the latest project config is ${e.reason}.`;throw new Error(`${i} The file was left untouched.`)}let n=r==="read"?`invalid ${S} at ${t}`:`Cannot update ${t}: the latest project config is invalid`;throw new Error(`${n} (unsupported ${e.direction} schemaVersion ${e.schemaVersion}; this scip-query reads legacy v${h} and current v${g}). Upgrade scip-query before retrying; the file was left untouched.`)}import{statSync as He}from"fs";import{basename as Be,isAbsolute as Ke,join as Ye,relative as ze}from"path";import{watch as Xe}from"chokidar";import Qe from"ignore";var pe=5e3,_=class{projectRoot;config;watchConfig;languages;pnpmWorkspaces;typescriptProjectMode;typescriptProjects;clojureConfigPath;indexerConcurrency;onStatus;onReindexComplete;onReindexError;onRefreshSuppressed;onError;reindexRunner;subscriptionFactory;clock;activeOperation=null;stopPromise=null;stopInProgress=!1;status={state:"idle"};debounceTimer=null;cooldownTimer=null;dirty=!1;changedFiles=0;pendingTrigger=null;reindexInFlight=!1;lastReindexEnd=0;fsWatchers=[];sourcePollingFallbackStarted=!1;gitPollTimer=null;lastGitState=null;gitignoreFilter;extraIgnore;stopped=!1;constructor(t){this.projectRoot=t.projectRoot,this.config=t.config,this.watchConfig=ce(t.config),this.languages=t.languages,this.pnpmWorkspaces=t.config.indexer?.typescript?.pnpmWorkspaces??!1,this.typescriptProjectMode=t.config.indexer?.typescript?.projectMode,this.typescriptProjects=t.config.indexer?.typescript?.projects,this.clojureConfigPath=t.config.indexer?.clojure?.configPath,this.indexerConcurrency=t.config.indexerConcurrency,this.onStatus=t.onStatus??(()=>{}),this.onReindexComplete=t.onReindexComplete??(()=>{}),this.onReindexError=t.onReindexError??(()=>{}),this.onRefreshSuppressed=t.onRefreshSuppressed??(()=>{}),this.onError=t.onError??(r=>console.error(r.message)),this.clock=t.clock??rt,he.set(this,lt(t.stopTimeoutMs??pe,"watcher stop timeout")),this.reindexRunner=t.reindexRunner??ge(),this.subscriptionFactory=t.subscriptionFactory??nt,this.gitignoreFilter=U(t.projectRoot),this.extraIgnore=Qe(),this.watchConfig.ignore.length>0&&this.extraIgnore.add(this.watchConfig.ignore)}start(){if(this.stopInProgress)throw new Error("Cannot restart a watcher while its previous ownership is still draining.");this.stopped=!1,this.stopPromise=null,E(this).errors=[],this.sourcePollingFallbackStarted=!1,this.setStatus({state:"idle"}),this.startGitStatePolling();try{this.startSourceWatcher()}catch(t){this.onError(new Error(`Failed to watch ${this.projectRoot}: ${String(t)}`))}}stop(){if(this.stopPromise)return this.stopPromise;this.stopped=!0,this.stopInProgress=!0;let t=this.fsWatchers;this.fsWatchers=[],this.clearDebounceTimer(),this.clearCooldownTimer(),this.clearGitPollTimer();let r=this.activeOperation;r&&this.setStatus({state:"draining",startedAt:this.wallNow(),reason:"waiting for the active reindex worker to exit"});let n=[...E(this).closures],i=et(this),o=this.clock.now()+i;return this.stopPromise=this.finishStop(t,n,r,o,i).catch(s=>{throw this.stopInProgress=!1,s}),this.stopPromise}requestRefresh(t,r={}){if(!this.stopped){if(!r.immediate||this.reindexInFlight||this.status.state==="cooldown"){this.scheduleReindex(t);return}this.pendingTrigger=de(this.pendingTrigger,t),this.changedFiles+=1,this.clearDebounceTimer(),this.triggerReindex()}}startSourceWatcher(t=!1){let r=this.subscriptionFactory(this.projectRoot,{ignoreInitial:!0,ignored:(n,i)=>this.isIgnoredWatchPath(n,i?.isDirectory()??!1),usePolling:t,...t?{interval:500,binaryInterval:1e3}:{}});r.on("all",(n,i)=>{this.stopped||this.handleFileChange(i)}),r.on("error",n=>this.handleSourceWatcherError(r,n,t)),this.fsWatchers.push(r)}handleSourceWatcherError(t,r,n){if(n||this.sourcePollingFallbackStarted||!ct(r)||this.stopped){this.onError(new Error(`Failed to watch ${this.projectRoot}: ${String(r)}`));return}this.sourcePollingFallbackStarted=!0,this.fsWatchers=this.fsWatchers.filter(i=>i!==t),tt(E(this),t,i=>this.onError(i));try{this.startSourceWatcher(!0)}catch(i){this.onError(new Error(`Failed to watch ${this.projectRoot}: ${String(i)}`))}}isIgnoredWatchPath(t,r){let n=this.relativeWatchPath(t);if(!n)return!1;let i=r?`${n}/`:n;return i===".git/"||i.startsWith(".git/")?!0:this.gitignoreFilter.isIgnored(i)||this.extraIgnore.ignores(i)}handleFileChange(t){let r=this.relativeWatchPath(t);!r||r===".."||r.startsWith("../")||r===".git"||r.startsWith(".git/")||this.gitignoreFilter.isIgnored(r)||this.extraIgnore.ignores(r)||r.endsWith("index.db")||r.endsWith("index.scip")||r.endsWith("index.db.tmp")||Be(r).startsWith(q)||this.scheduleReindex({kind:"watch-source",detail:r})}relativeWatchPath(t){let r=Ke(t)?t:Ye(this.projectRoot,t);return ze(this.projectRoot,r).replaceAll("\\","/")}scheduleReindex(t){if(this.pendingTrigger=de(this.pendingTrigger,t),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 r=this.wallNow()+this.watchConfig.debounceMs;this.setStatus({state:"waiting",changedFiles:this.changedFiles,reindexAt:r}),this.debounceTimer=this.clock.setTimeout(()=>{this.debounceTimer=null,this.triggerReindex()},this.watchConfig.debounceMs)}triggerReindex(){if(this.reindexInFlight||this.stopped)return;let t=this.clock.now()-this.lastReindexEnd;if(this.lastReindexEnd>0&&t<this.watchConfig.cooldownMs){let o=this.watchConfig.cooldownMs-t;this.dirty=!0;let s=this.wallNow()+o;this.setStatus({state:"cooldown",until:s,dirty:!0}),this.cooldownTimer=this.clock.setTimeout(()=>{this.cooldownTimer=null,this.dirty&&!this.stopped&&(this.dirty=!1,this.triggerReindex())},o);return}this.reindexInFlight=!0,this.dirty=!1,this.changedFiles=0;let r=this.pendingTrigger??{kind:"watch-source"};this.pendingTrigger=null;let n=this.wallNow();this.setStatus({state:"indexing",startedAt:n});let i=this.reindexRunner.start(this.reindexRequest(r));this.activeOperation=i,i.completion.then(o=>{if(this.reindexInFlight=!1,this.lastReindexEnd=this.clock.now(),this.stopped)return;let s=!1;try{s=this.onReindexComplete(o,r)===!0}catch(a){this.onError(a instanceof Error?a:new Error(String(a)))}if(this.dirty&&!this.stopped){if(s){let c=this.pendingTrigger??{kind:"unknown"};this.dirty=!1,this.changedFiles=0,this.pendingTrigger=null,this.onRefreshSuppressed(c),this.setStatus({state:"idle"});return}let a=this.wallNow()+this.watchConfig.cooldownMs;this.setStatus({state:"cooldown",until:a,dirty:!0}),this.cooldownTimer=this.clock.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(o=>{if(this.reindexInFlight=!1,this.lastReindexEnd=this.clock.now(),this.stopped)return;let s=o instanceof Error?o:new Error(String(o));this.onReindexError(s,r),this.onError(s),this.setStatus({state:"idle"})}).finally(()=>{this.activeOperation===i&&(this.activeOperation=null)})}async finishStop(t,r,n,i,o){let s=[],a=t.map(async d=>{try{await d.close()}catch(R){s.push(`watch subscription close failed: ${String(R)}`)}});a.push(...r),n&&a.push((async()=>{try{let d=await n.cancel();d.state==="degraded"&&s.push(d.reason)}catch(d){s.push(`reindex cancellation failed: ${d instanceof Error?d.message:String(d)}`)}})());let c=a.length,u=a.map(d=>d.finally(()=>{c-=1})),p=await Ze(u,i,this.clock),l=E(this);return s.push(...l.errors),l.errors=[],p?this.stopInProgress=!1:(s.push(`watch shutdown exceeded the ${o}ms deadline with ${c} operation(s) still pending`),Promise.all(u).then(()=>{this.stopInProgress=!1})),s.length>0?(this.setStatus({state:"draining",startedAt:this.wallNow(),reason:s.join("; ")}),{state:"degraded",reasons:s}):(this.setStatus({state:"idle"}),{state:"stopped"})}wallNow(){return this.clock.wallNow?.()??this.clock.now()}reindexRequest(t){return{projectRoot:this.projectRoot,config:this.config,languages:this.languages,pnpmWorkspaces:this.pnpmWorkspaces,typescriptProjectMode:this.typescriptProjectMode,typescriptProjects:this.typescriptProjects,clojureConfigPath:this.clojureConfigPath,indexerConcurrency:this.indexerConcurrency,trigger:t}}setStatus(t){this.status=t,this.onStatus(t)}clearDebounceTimer(){this.debounceTimer&&(this.clock.clearTimeout(this.debounceTimer),this.debounceTimer=null)}clearCooldownTimer(){this.cooldownTimer&&(this.clock.clearTimeout(this.cooldownTimer),this.cooldownTimer=null)}startGitStatePolling(){this.lastGitState=this.readGitState(),this.lastGitState&&(this.gitPollTimer=this.clock.setInterval(()=>this.pollGitState(),this.watchConfig.gitPollMs),this.gitPollTimer.unref?.())}pollGitState(){let t=this.lastGitState,r=this.readGitState();if(!t||!r||this.stopped){this.lastGitState=r;return}this.lastGitState=r;let n=t.head!==r.head,i=t.indexPath!==r.indexPath||t.indexMtimeMs!==r.indexMtimeMs||t.indexSize!==r.indexSize;n&&i?this.scheduleReindex({kind:"watch-git-state",detail:"HEAD and index changed"}):n?this.scheduleReindex({kind:"watch-git-head",detail:"HEAD changed"}):i&&this.scheduleReindex({kind:"watch-git-index",detail:r.indexPath??"index changed"})}readGitState(){let t=w(this.projectRoot,["rev-parse","--git-path","index"]);if(!t)return null;let r=G(this.projectRoot,t),n={head:w(this.projectRoot,["rev-parse","--verify","HEAD"]),indexPath:r};try{let i=He(r);n.indexMtimeMs=i.mtimeMs,n.indexSize=i.size}catch{n.indexMtimeMs=void 0,n.indexSize=void 0}return n}clearGitPollTimer(){this.gitPollTimer&&(this.clock.clearInterval(this.gitPollTimer),this.gitPollTimer=null)}};async function Ze(e,t,r){if(e.length===0)return!0;let n=Promise.all(e).then(()=>!0),i=Math.max(0,t-r.now()),o=null,s=new Promise(c=>{o=r.setTimeout(()=>c(!1),i)}),a=await Promise.race([n,s]);return a&&o&&r.clearTimeout(o),a}var le=new WeakMap,he=new WeakMap;function E(e){let t=le.get(e);if(t)return t;let r={closures:new Set,errors:[]};return le.set(e,r),r}function et(e){return he.get(e)??pe}function tt(e,t,r){let n=Promise.resolve().then(()=>t.close()).catch(i=>{let o=`watch subscription close failed during polling fallback: ${String(i)}`;e.errors.push(o),r(new Error(o))});e.closures.add(n),n.then(()=>e.closures.delete(n))}function fe(e){let{projectRoot:t,config:r,languages:n,pnpmWorkspaces:i,typescriptProjectMode:o,typescriptProjects:s,clojureConfigPath:a,indexerConcurrency:c,trigger:u}=e,p=T(t),l=Object.keys(p).length>0?p:r,d=k(t,l),R=l.indexer?.typescript,we=l.indexer?.clojure;return{workerPath:new URL("./reindex-worker.js",import.meta.url).pathname,env:{...process.env,SCIP_REINDEX_PROJECT_ROOT:t,SCIP_REINDEX_OUTPUT_SCIP:d.indexPath,SCIP_REINDEX_OUTPUT_DB:d.dbPath,SCIP_REINDEX_LANGUAGES:(l.languages??n)?.join(",")??"",SCIP_REINDEX_INDEXER_CONCURRENCY:String(l.indexerConcurrency??c??""),SCIP_REINDEX_PNPM_WORKSPACES:R?.pnpmWorkspaces??i?"1":"",SCIP_REINDEX_TYPESCRIPT_CONFIG:JSON.stringify({projectMode:R?.projectMode??o,projects:R?.projects??s??[]}),SCIP_REINDEX_CLOJURE_CONFIG_PATH:we?.configPath??a??"",SCIP_REINDEX_TRIGGER_KIND:u.kind,SCIP_REINDEX_TRIGGER_DETAIL:u.detail??"",SCIP_REINDEX_PROCESS_GROUP_LEADER:"1"}}}var rt={now:C,wallNow:()=>Date.now(),setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e)},nt=(e,t)=>Xe(e,t),it=15*6e4,ot=1e3,st=64*1024;function at(){return{stdoutTail:"",stderrTail:"",stdoutTruncated:!1,stderrTruncated:!1}}function ue(e,t){let r=e instanceof Error?e.message:String(e),n=t.stderrTail.trim()||t.stdoutTail.trim();return n?`${r}
|
|
3
3
|
${n}`:r}function ge(e={}){let t=e.timeoutMs??it,r=e.terminationGraceMs??ot,n=e.maxOutputBytes??st,i=e.resolveLaunch??fe;return{start(o){let s=i(o),a=new AbortController,c=at(),u=!1,p=H({command:process.execPath,args:[...process.execArgv,s.workerPath],label:"watch reindex worker",env:s.env,timeoutMs:t,terminationGraceMs:r,maxStdoutBytes:n,maxStderrBytes:n,outputLimitBehavior:"truncate-tail",signal:a.signal,detached:!0}).then(l=>{if(c={stdoutTail:l.stdout,stderrTail:l.stderr,stdoutTruncated:l.stdoutTruncated,stderrTruncated:l.stderrTruncated},l.status!==0)throw new Error(ue(new Error(`Reindex worker exited with ${l.signal?`signal ${l.signal}`:`code ${l.status}`}`),c));return l.durationMs}).catch(l=>{throw l instanceof J&&(c={stdoutTail:l.stdout,stderrTail:l.stderr,stdoutTruncated:l.stdoutTruncated,stderrTruncated:l.stderrTruncated}),new Error(ue(l,c),{cause:l})}).finally(()=>{u=!0});return{completion:p,async cancel(){u||a.abort();try{await p}catch{}return{state:"exited",diagnostics:c}},diagnostics:()=>c}}}}function de(e,t){return e?e.kind===t.kind?e.detail===t.detail?e:{kind:e.kind,detail:"multiple changes"}:{kind:"watch-git-state",detail:`${e.kind}, ${t.kind}`}:t}function ct(e){return e instanceof Error&&"code"in e&&e.code==="EMFILE"||String(e).includes("EMFILE: too many open files")}function lt(e,t){if(!Number.isSafeInteger(e)||e<=0)throw new Error(`${t} must be a positive integer.`);return e}import{existsSync as I,mkdirSync as ut,symlinkSync as dt,readlinkSync as me,unlinkSync as ye,readdirSync as pt}from"fs";import{join as m,dirname as j,resolve as y,relative as ht,isAbsolute as ft}from"path";import{homedir as O,platform as gt}from"os";import{fileURLToPath as mt}from"url";import{createHash as cr}from"crypto";import{resolve as ur}from"path";var yt=gt()==="win32",ve=["_shared","scip-query","scip-setup","scip-explore","scip-plan","scip-diagnose","scip-audit","scip-improve","scip-verify"];function vt(e={}){let t=e.quiet?()=>{}:console.log,r=mt(import.meta.url),n=y(j(r),"..","skills"),i=[m(O(),".claude","skills"),m(O(),".codex","skills"),m(O(),".agents","skills")],o={installed:[],skipped:[],alreadyLinked:[],pruned:[]};for(let s of i){let a=j(s);if(!I(a))continue;ut(s,{recursive:!0});let c=Ct(s);Rt(s,n,c,o,t);for(let u of ve){let p=m(n,u),l=m(s,u);if(!I(p)){o.skipped.push(`${c}/${u}`);continue}if(I(l)){try{let d=me(l);if(y(d)===y(p)){o.alreadyLinked.push(`${c}/${u}`),t(` ok: ${u} \u2192 ${c} (already linked)`);continue}}catch{o.skipped.push(`${c}/${u}`),t(` skip: ${u} \u2192 ${c} (exists, not a symlink)`);continue}ye(l)}dt(p,l,yt?"junction":"dir"),o.installed.push(`${c}/${u}`),t(` done: ${u} \u2192 ${c}`)}}return o}function Rt(e,t,r,n,i){let o=new Set(ve);for(let s of pt(e)){if(o.has(s))continue;let a=m(e,s),c;try{c=y(j(a),me(a))}catch{continue}St(c,t)&&(ye(a),n.pruned.push(`${r}/${s}`),i(` prune: ${s} \u2192 ${r} (removed stale scip-query skill link)`))}}function St(e,t){let r=ht(y(t),y(e));return r===""||!r.startsWith("..")&&!ft(r)}function Ct(e){return e.includes(".codex")?"Codex":e.includes(".agents")?"Agents":"Claude"}var Ce="scip-query-result",xe=0,v=1,xt=1;function be(e){if(!f(e))return{kind:"malformed",reason:"CLI JSON output must be an object."};let t=Object.hasOwn(e,"kind"),r=Object.hasOwn(e,"schemaVersion");if(!t&&!r){let s=Re(e);return s?{kind:"malformed",reason:`Legacy CLI JSON envelope: ${s}`}:{kind:"legacy",schemaVersion:xe,envelope:e}}if(!t||!r)return{kind:"malformed",reason:"CLI JSON envelope must contain both kind and schemaVersion."};if(e.kind!==Ce)return{kind:"malformed",reason:`Unsupported CLI JSON envelope kind: ${kt(e.kind)}.`};let n=e.schemaVersion;if(!Number.isSafeInteger(n)||Number(n)<1)return{kind:"malformed",reason:"CLI JSON envelope schemaVersion must be a positive safe integer."};if(n!==v)return{kind:"unsupported",schemaVersion:Number(n),direction:Number(n)<v?"older":"future",...Se(e.producer)?{producer:e.producer}:{}};let i=Re(e);if(i)return{kind:"malformed",reason:`CLI JSON envelope v1: ${i}`};if(!Se(e.producer))return{kind:"malformed",reason:"CLI JSON envelope v1: producer must identify scip-query and its non-empty version."};if(!wt(e.resultSchemaVersion))return{kind:"malformed",reason:"CLI JSON envelope v1: resultSchemaVersion must be a positive safe integer."};let o=Ee(e.command);return o.includes(e.resultSchemaVersion)?{kind:"supported",schemaVersion:v,envelope:e}:{kind:"unsupported-result",schemaVersion:v,command:e.command,resultSchemaVersion:e.resultSchemaVersion,supportedResultSchemaVersions:o}}function bt(e){let t=be(e);if(t.kind==="legacy"||t.kind==="supported")return t;if(t.kind==="unsupported"){let r=t.producer?` from ${t.producer.name}@${t.producer.version}`:"";throw new Error(`Unsupported scip-query CLI JSON schemaVersion ${t.schemaVersion}${r}; this consumer supports the legacy unversioned envelope and schemaVersion ${v}.`)}throw t.kind==="unsupported-result"?new Error(`Unsupported resultSchemaVersion ${t.resultSchemaVersion} for scip-query command ${JSON.stringify(t.command)}; this consumer supports ${t.supportedResultSchemaVersions.join(", ")}.`):new Error(`Malformed scip-query CLI JSON envelope: ${t.reason}`)}function Ee(e){return Et[e]??[xt]}var Et={};function Re(e){return typeof e.command!="string"||e.command.length===0?"command must be a non-empty string.":Array.isArray(e.args)?f(e.options)?Object.hasOwn(e,"result")?null:"result is required.":"options must be an object.":"args must be an array."}function Se(e){return f(e)&&e.name==="scip-query"&&typeof e.version=="string"&&e.version.length>0}function wt(e){return Number.isSafeInteger(e)&&Number(e)>0}function kt(e){return typeof e=="string"?JSON.stringify(e):String(e)}export{Ce as CLI_JSON_ENVELOPE_KIND,v as CURRENT_CLI_JSON_ENVELOPE_SCHEMA_VERSION,xe as LEGACY_CLI_JSON_ENVELOPE_SCHEMA_VERSION,B as OBSERVATION_RECEIPT_SCHEMA_VERSION,_ as Watcher,K as compareObservationReceipts,ge as createReindexRunner,be as decodeCliJsonEnvelope,Pe as getScipVersion,Ge as initProjectConfig,vt as installSkills,Y as isObservationReceipt,ke as isScipInstalled,T as loadProjectConfig,Te as printScipInstallInstructions,bt as requireCompatibleCliJsonEnvelope,k as resolveIndexStoragePaths,fe as resolveReindexWorkerLaunch,Ee as supportedCliResultSchemaVersions};
|
|
4
4
|
//# sourceMappingURL=runtime.js.map
|
package/docs/CLI_JSON_OUTPUT.md
CHANGED
|
@@ -39,7 +39,7 @@ The current envelope is schema version 1:
|
|
|
39
39
|
{
|
|
40
40
|
"kind": "scip-query-result",
|
|
41
41
|
"schemaVersion": 1,
|
|
42
|
-
"producer": { "name": "scip-query", "version": "0.
|
|
42
|
+
"producer": { "name": "scip-query", "version": "0.20.0" },
|
|
43
43
|
"command": "refs",
|
|
44
44
|
"resultSchemaVersion": 1,
|
|
45
45
|
"evidence": "graph-fact",
|
|
@@ -103,7 +103,7 @@ exact command that opts into output pages. The paged command returns:
|
|
|
103
103
|
{
|
|
104
104
|
"kind": "scip-query-output-page",
|
|
105
105
|
"schemaVersion": 1,
|
|
106
|
-
"producer": { "name": "scip-query", "version": "0.
|
|
106
|
+
"producer": { "name": "scip-query", "version": "0.20.0" },
|
|
107
107
|
"command": "architecture",
|
|
108
108
|
"contentType": "application/json",
|
|
109
109
|
"agentInstruction": "INCOMPLETE EVIDENCE: do not draw conclusions or report completion from this partial page. Run page.continuation.command exactly, then repeat until page.complete is true.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scip-query",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Evidence and verification for AI coding agents: map code, reuse concepts, finish migrations, and gate diffs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -358,14 +358,14 @@
|
|
|
358
358
|
],
|
|
359
359
|
"license": "Apache-2.0",
|
|
360
360
|
"engines": {
|
|
361
|
-
"node": ">=
|
|
361
|
+
"node": ">=22.0.0"
|
|
362
362
|
},
|
|
363
363
|
"dependencies": {
|
|
364
364
|
"@bufbuild/protobuf": "^2.11.0",
|
|
365
365
|
"@c4312/scip": "^0.1.0",
|
|
366
366
|
"@vue/compiler-dom": "^3.5.40",
|
|
367
367
|
"@vue/compiler-sfc": "^3.5.40",
|
|
368
|
-
"better-sqlite3": "^
|
|
368
|
+
"better-sqlite3": "^13.0.2",
|
|
369
369
|
"chokidar": "^4.0.3",
|
|
370
370
|
"commander": "^13.1.0",
|
|
371
371
|
"ignore": "^7.0.3",
|
|
@@ -403,7 +403,7 @@
|
|
|
403
403
|
"vitest": "^3.2.7"
|
|
404
404
|
},
|
|
405
405
|
"allowScripts": {
|
|
406
|
-
"better-sqlite3
|
|
406
|
+
"better-sqlite3": false,
|
|
407
407
|
"esbuild@0.27.7": true,
|
|
408
408
|
"fsevents@2.3.3": true,
|
|
409
409
|
"tree-sitter@0.21.1": true,
|