@rulemetric/cli 0.7.36 → 0.7.38

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.
Files changed (42) hide show
  1. package/dist/{chunk-C5PSIJ7S.js → chunk-5KP66L7P.js} +1 -1
  2. package/dist/{chunk-MDPN46EY.js → chunk-6QKI756T.js} +1 -1
  3. package/dist/{chunk-6NML7IVJ.js → chunk-7LBD5POI.js} +1 -1
  4. package/dist/{chunk-TVHT6H42.js → chunk-7SI6KWSX.js} +1 -1
  5. package/dist/{chunk-XA4KSQEC.js → chunk-G6XGDHGC.js} +1 -1
  6. package/dist/chunk-GIRPEMTW.js +1 -0
  7. package/dist/chunk-GPTPK6QX.js +38 -0
  8. package/dist/{chunk-3HSEVXMQ.js → chunk-GWDZNGUP.js} +1 -1
  9. package/dist/chunk-QXPYGN7I.js +1 -0
  10. package/dist/chunk-SHYP27B7.js +2 -0
  11. package/dist/chunk-SNJ2NIIE.js +1 -0
  12. package/dist/{chunk-BUWWFHGO.js → chunk-W2MOTOQE.js} +1 -1
  13. package/dist/{chunk-CRIFP3QP.js → chunk-WFYQ6SPJ.js} +1 -1
  14. package/dist/commands/capture/scope.js +2 -2
  15. package/dist/commands/diagnostics.js +1 -1
  16. package/dist/commands/evals/agent.js +1 -1
  17. package/dist/commands/hooks/run.js +3 -3
  18. package/dist/commands/sessions/list.js +1 -1
  19. package/dist/dashboard/Dashboard.js +1 -1
  20. package/dist/dashboard/data.js +1 -1
  21. package/dist/{dist-BC6GMBXV.js → dist-FAVALJ5C.js} +1 -1
  22. package/dist/lib/agent-loop.js +1 -1
  23. package/dist/lib/capture-scope-config.js +1 -1
  24. package/dist/lib/codex-capture-scope.js +1 -1
  25. package/dist/lib/detect-languages.js +1 -1
  26. package/dist/lib/handlers/cron-suggest-instructions.js +1 -1
  27. package/dist/lib/handlers/process-changelog.js +1 -1
  28. package/dist/lib/handlers/process-insights.js +1 -1
  29. package/dist/lib/handlers/process-launch.js +1 -1
  30. package/dist/lib/handlers/process-run-cleanup.js +1 -1
  31. package/dist/lib/hooks-capture-gate.js +1 -0
  32. package/dist/lib/manual-tasks.js +1 -1
  33. package/dist/lib/transcript-sync.js +1 -1
  34. package/dist/lib/worktree.js +1 -1
  35. package/oclif.manifest.json +352 -338
  36. package/package.json +7 -7
  37. package/dist/chunk-DKGKOSW3.js +0 -1
  38. package/dist/chunk-RUZ36O55.js +0 -2
  39. package/dist/chunk-TDD7IOV2.js +0 -1
  40. package/dist/chunk-VX2GJCQ4.js +0 -1
  41. package/dist/chunk-ZL4MZMUK.js +0 -34
  42. /package/dist/{chunk-5DIOZDDZ.js → chunk-7DFNBRLY.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulemetric/cli",
3
- "version": "0.7.36",
3
+ "version": "0.7.38",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -77,9 +77,9 @@
77
77
  "postgres": "^3.4.0",
78
78
  "react": "^19.0.0",
79
79
  "zod": "^3.24.0",
80
- "@rulemetric/hooks": "0.7.36",
81
- "@rulemetric/proxy": "0.7.36",
82
- "@rulemetric/skills-registry": "0.7.36"
80
+ "@rulemetric/proxy": "0.7.38",
81
+ "@rulemetric/hooks": "0.7.38",
82
+ "@rulemetric/skills-registry": "0.7.38"
83
83
  },
84
84
  "//deps": "Worker (`evals agent`) runtime deps: the @opentelemetry/* set, @sentry/node, and postgres are STATIC top-level imports loaded at worker startup (via bundled @rulemetric/{telemetry,db}) — they MUST be runtime deps or a clean `npm i -g` crashes with ModuleLoadError. `better-sqlite3` is optionalDependencies (below): it's a native module, lazy `require()`'d inside a try/catch (packages/session providers cursor/opencode) so a missing binary degrades gracefully — making it a hard dep would break `npm i -g` on platforms without prebuilt binaries. `resend` stays a devDep: lazy `await import('resend')` guarded by RESEND_API_KEY, which end-user workers never set (provider falls back to noop). Classification verified via import-graph scan of dist/commands/evals/agent.js + per-importer static/lazy check.",
85
85
  "optionalDependencies": {
@@ -98,13 +98,13 @@
98
98
  "typescript": "^5.9.0",
99
99
  "vitest": "^3.2.0",
100
100
  "@rulemetric/api": "0.0.1",
101
+ "@rulemetric/core": "0.0.1",
101
102
  "@rulemetric/db": "0.0.1",
102
- "@rulemetric/effectiveness": "0.0.1",
103
103
  "@rulemetric/email": "0.0.1",
104
+ "@rulemetric/effectiveness": "0.0.1",
104
105
  "@rulemetric/session": "0.2.1",
105
106
  "@rulemetric/telemetry": "0.0.1",
106
- "@rulemetric/typescript-config": "0.0.0",
107
- "@rulemetric/core": "0.0.1"
107
+ "@rulemetric/typescript-config": "0.0.0"
108
108
  },
109
109
  "scripts": {
110
110
  "build": "node scripts/build.mjs",
@@ -1 +0,0 @@
1
- import{b as j}from"./chunk-ZL4MZMUK.js";import{a as k}from"./chunk-TDD7IOV2.js";import{a as p}from"./chunk-MODXEGCU.js";import{d as y,f as S}from"./chunk-B3BHB26P.js";import{e as i,f as l}from"./chunk-H2ORWIEY.js";import{a as g}from"./chunk-ZLLER3HP.js";import{readFileSync as b}from"node:fs";import E from"node:path";import $ from"node:os";var N=5,L=Number(process.env.RULEMETRIC_MAX_SUGGESTION_PROJECTS??10),T=48,M=.5,d=400;async function O(){let m=E.join($.homedir(),".config","rulemetric","skills-registry.json");try{let o=b(m,"utf-8"),s=JSON.parse(o);return Date.now()-new Date(s.generatedAt).getTime()>T*60*60*1e3}catch{return!0}}g(O,"checkSkillsRegistryStale");var X=g(async(m,o)=>{let s=y();if(s==="none"){o.logger.warn("No LLM backend available (claude CLI missing and ANTHROPIC_API_KEY unset); skipping suggestion compute");return}o.logger.info(`Scoring backend: ${s}`);let r;try{r=(await i("/api/sessions/project-paths?limit="+L)).projectPaths}catch(e){o.logger.warn(`Failed to fetch project paths: ${e instanceof Error?e.message:String(e)}`);return}if(r.length===0){o.logger.info("No recent project paths; nothing to score");return}let u=new Map;try{let e=await i("/api/projects?limit=200");for(let t of e.projects??[])t.primaryCheckoutPath&&u.set(p(t.primaryCheckoutPath),t.id)}catch(e){o.logger.warn(`Failed to fetch projects for id resolution: ${e instanceof Error?e.message:String(e)}`)}let a=new Map;try{let e=await i(`/api/catalog?limit=200&contentPreview=${d}`);for(let t of e)a.set(t.id,{id:t.id,name:t.name,description:t.description??"",tags:t.tags??[],contentPreview:(t.contentPreview??"").slice(0,d)})}catch(e){o.logger.warn(`Failed to fetch catalog: ${e instanceof Error?e.message:String(e)}`)}try{let e=await i("/api/instructions?limit=100");for(let t of e.instructions??[])a.has(t.id)||a.set(t.id,{id:t.id,name:t.name,description:t.description??"",tags:t.tags??[],contentPreview:(t.content??"").slice(0,d)})}catch(e){o.logger.warn(`Failed to fetch personal instructions: ${e instanceof Error?e.message:String(e)}`)}let c=[...a.values()];if(c.length===0){o.logger.info("No candidate instructions; nothing to score");return}o.logger.info(`Scoring ${c.length} candidates across ${r.length} project(s)`);let f=0;for(let e of r)try{let t=p(e),w=k(t);if(w.length===0){o.logger.info(`Skipping ${t}: insufficient language signals`);continue}let C={name:E.basename(t),description:null,languages:w,topics:[],dependencies:[]},I=j(C,c),P=await S(I,"",4096);if(!P){o.logger.warn(`LLM returned null for ${t} (backend ${s})`);continue}let h=(P.recommendations??[]).filter(n=>typeof n.instructionId=="string"&&typeof n.score=="number"&&typeof n.reason=="string").map(n=>({instructionId:n.instructionId,score:n.score,reason:n.reason})).filter(n=>n.score>=M).sort((n,_)=>_.score-n.score).slice(0,N);if(h.length===0){o.logger.info(`No suggestions over threshold for ${t}`);continue}let R=u.get(t);await l("/api/instruction-suggestions/batch-upsert",{projectPath:t,...R?{projectId:R}:{},suggestions:h.map(n=>({instructionId:n.instructionId,score:n.score,reason:n.reason}))}),f++}catch(t){o.logger.warn(`Failed to score ${e}: ${t instanceof Error?t.message:String(t)}`)}if(await O())try{await l("/api/instruction-suggestions/mark-stale",{}),o.logger.warn("Skills registry is stale (>48h); marked all suggestions stale")}catch{}o.logger.info(`Done: scored ${f}/${r.length} projects`)},"cronSuggestInstructions");export{X as a};
@@ -1,2 +0,0 @@
1
- import{a as d}from"./chunk-VX2GJCQ4.js";import{a as n}from"./chunk-ZLLER3HP.js";import{copyFileSync as C,mkdirSync as y,readFileSync as x,writeFileSync as w}from"node:fs";import{homedir as p}from"node:os";import{isAbsolute as S,join as f,resolve as b}from"node:path";function i(e){return f(e,d)}n(i,"captureConfigPath");function E(e){let r;try{r=x(i(e),"utf-8")}catch{return{}}try{let t=JSON.parse(r);if(!t||typeof t!="object"||Array.isArray(t))throw new Error("not a JSON object");return t}catch(t){throw new Error(`${i(e)} is not valid JSON (${t instanceof Error?t.message:String(t)}). Fix or delete it \u2014 refusing to overwrite what you wrote.`)}}n(E,"readCaptureConfig");function v(e,r){y(e,{recursive:!0});let t=i(e);return w(t,JSON.stringify(r,null,2)+`
2
- `),t}n(v,"writeCaptureConfig");function m(e,r=p()){let t=e.trim(),o=t==="~"?r:t.startsWith("~/")?f(r,t.slice(2)):t;return b(o)}n(m,"normaliseRoot");function F(e,r=p()){let t=e.trim();if(!t)return!1;let o=t==="~"?r:t.startsWith("~/")?f(r,t.slice(2)):t;return S(o)}n(F,"isUsableRoot");function N(e,r,t=p()){let o={...e.codex??{}},l=Array.isArray(o.roots)?o.roots.map(s=>m(String(s),t)):[],u=!1;if(r.op==="mode")o.mode=r.mode,r.mode==="all"&&delete o.roots;else if(r.op==="clear")delete o.mode,delete o.roots;else{let s=r.roots.map(c=>m(c,t)),g=r.op==="add"?[...new Set([...l,...s])]:l.filter(c=>!s.includes(c));g.length===0&&r.op==="remove"?(delete o.roots,o.mode="off",u=!0):(o.roots=g.sort(),o.mode="allowlist")}let a={...e};return Object.keys(o).length===0?delete a.codex:a.codex=o,{config:a,emptiedToOff:u}}n(N,"applyScopeEdit");function j(e){let r=i(e),t=`${r}.broken`;try{C(r,t)}catch{}return t}n(j,"backupUnparseableConfig");export{i as a,E as b,v as c,m as d,F as e,N as f,j as g};
@@ -1 +0,0 @@
1
- import{a as o}from"./chunk-ZLLER3HP.js";import{existsSync as p,statSync as u,readdirSync as h}from"node:fs";import y from"node:path";var g=new Set(["node_modules",".git","dist","build",".next",".turbo",".worktrees","target","venv","__pycache__",".cache"]),f=3;function P(r){if(!p(r))return[];let t=new Set,d=o((n,s)=>{if(s>f)return;let a;try{a=h(n)}catch{return}for(let e of a)e==="package.json"&&t.add("JavaScript/TypeScript"),e==="tsconfig.json"&&t.add("TypeScript-config"),e==="pyproject.toml"&&t.add("Python-pyproject"),e==="setup.py"&&t.add("Python-setup"),e==="requirements.txt"&&t.add("Python-requirements"),e==="Pipfile"&&t.add("Python-pipfile"),e==="Cargo.toml"&&t.add("Rust-cargo"),e==="go.mod"&&t.add("Go-mod"),e==="pom.xml"&&t.add("Java-pom"),(e==="build.gradle"||e==="build.gradle.kts")&&t.add("Java-gradle"),e==="Gemfile"&&t.add("Ruby-gemfile"),e==="composer.json"&&t.add("PHP-composer"),(e.endsWith(".ts")||e.endsWith(".tsx"))&&t.add("TypeScript-source"),e.endsWith(".py")&&t.add("Python-source"),e.endsWith(".rs")&&t.add("Rust-source"),e.endsWith(".go")&&t.add("Go-source");if(!(s>=f))for(let e of a){if(g.has(e))continue;let c=y.join(n,e);try{u(c).isDirectory()&&d(c,s+1)}catch{}}},"walk");d(r,0);let i=new Set;return t.has("TypeScript-source")||t.has("TypeScript-config")?i.add("TypeScript"):t.has("JavaScript/TypeScript")&&i.add("JavaScript"),(t.has("Python-pyproject")||t.has("Python-setup")||t.has("Python-requirements")||t.has("Python-pipfile")||t.has("Python-source"))&&i.add("Python"),(t.has("Rust-cargo")||t.has("Rust-source"))&&i.add("Rust"),(t.has("Go-mod")||t.has("Go-source"))&&i.add("Go"),(t.has("Java-pom")||t.has("Java-gradle"))&&i.add("Java"),t.has("Ruby-gemfile")&&i.add("Ruby"),t.has("PHP-composer")&&i.add("PHP"),t.size<2?[]:[...i]}o(P,"detectLanguages");export{P as a};
@@ -1 +0,0 @@
1
- import{a as s}from"./chunk-ZLLER3HP.js";import{readFile as v,stat as w}from"node:fs/promises";import{homedir as E}from"node:os";import{isAbsolute as O,join as d,resolve as S,sep as m}from"node:path";var l="capture.json";function R(e,o){return e==="~"?o:e.startsWith("~/")?d(o,e.slice(2)):e}s(R,"expandTilde");function x(e,o){return e.map(r=>typeof r=="string"?r.trim():"").filter(Boolean).map(r=>R(r,o)).filter(r=>O(r)).map(r=>S(r))}s(x,"normaliseRoots");function h(e){return{mode:"off",roots:[],source:"config",error:e}}s(h,"failClosed");async function y(e){let o=e.env??process.env,r=e.home??E(),t=o.RULEMETRIC_CODEX_CAPTURE?.trim().toLowerCase();if(t==="off"||t==="none"||t==="0")return{mode:"off",roots:[],source:"env"};if(t==="all"||t==="1")return{mode:"all",roots:[],source:"env"};let i=o.RULEMETRIC_CODEX_ROOTS?.trim();if(i){let g=x(i.split(","),r);return g.length>0?{mode:"allowlist",roots:g,source:"env"}:{mode:"off",roots:[],source:"env",error:"RULEMETRIC_CODEX_ROOTS had no absolute paths"}}let n=d(e.configDir,l),c;try{c=await v(n,"utf8")}catch{return{mode:"all",roots:[],source:"default"}}let u;try{u=JSON.parse(c)}catch{return h(`${l} is present but is not valid JSON \u2014 Codex capture is OFF until it parses.`)}let a=u?.codex;if(!a||typeof a!="object")return{mode:"all",roots:[],source:"default"};let f=typeof a.mode=="string"?a.mode.trim().toLowerCase():void 0;if(f==="off")return{mode:"off",roots:[],source:"config"};if(f==="all")return{mode:"all",roots:[],source:"config"};let p=Array.isArray(a.roots)?a.roots:[];if(f===void 0&&p.length===0)return{mode:"all",roots:[],source:"default"};let C=x(p,r);return C.length===0?h(`${l} selects an allowlist but lists no roots (absolute paths required) \u2014 Codex capture is OFF.`):{mode:"allowlist",roots:C,source:"config"}}s(y,"loadCodexCaptureScope");function $(e,o){if(e.mode==="off")return!1;if(e.mode==="all")return!0;if(!o)return!1;let r=S(o);return e.roots.some(t=>r===t||r.startsWith(t.endsWith(m)?t:t+m))}s($,"isPathInScope");function T(e){if(e.error)return`OFF \u2014 ${e.error}`;switch(e.mode){case"off":return`off (${e.source}) \u2014 no Codex transcripts are swept`;case"allowlist":return`scoped to ${e.roots.length} path${e.roots.length===1?"":"s"} (${e.source})`;default:return"all projects (unscoped)"}}s(T,"describeCodexCaptureScope");function _(e){let o=null,r=null;return async()=>{let t=d(e.configDir,l),i;try{let u=await w(t);i=`${u.mtimeMs}:${u.size}`}catch{i="absent"}if(o&&r===i)return o;let n=await y(e),c=o===null||o.mode!==n.mode||o.error!==n.error||o.roots.join("\0")!==n.roots.join("\0");return o=n,r=i,c&&e.onChange?.(n),n}}s(_,"createCodexScopeWatcher");export{l as a,y as b,$ as c,T as d,_ as e};
@@ -1,34 +0,0 @@
1
- import{a as e}from"./chunk-ZLLER3HP.js";function R(r){if(!r||typeof r!="object")return r;let a=r,i=a.project_areas;if(i!==void 0&&!Array.isArray(i)){let n=i&&typeof i=="object"?i.areas:void 0;a.project_areas=Array.isArray(n)?n:void 0}return r}e(R,"normalizeRecommendations");import{z as o}from"zod";var g=["org","team","project","personal"],w=o.object({name:o.string().min(1),description:o.string().min(1),type:o.literal("instruction").default("instruction"),scope:o.enum(g),version:o.string().min(1),tags:o.array(o.string()).optional(),compatibility:o.array(o.string()).optional(),slots:o.record(o.string(),o.string()).optional(),metadata:o.record(o.string(),o.unknown()).optional()});import{z as s}from"zod";var v=s.object({name:s.string().min(1),description:s.string().min(1),type:s.literal("prompt"),version:s.string().min(1),tags:s.array(s.string()).optional(),variables:s.array(s.string()).optional(),metadata:s.record(s.string(),s.unknown()).optional()});function y(r,a){let i=a.map(n=>`- ID: ${n.id}
2
- Name: ${n.name}
3
- Description: ${n.description}
4
- Tags: ${n.tags.join(", ")}
5
- Preview: ${n.contentPreview}`).join(`
6
-
7
- `);return`You are an expert at matching AI coding instructions to software projects.
8
-
9
- ## Project
10
- - Name: ${r.name}
11
- - Description: ${r.description??"No description"}
12
- - Languages: ${r.languages.join(", ")||"Unknown"}
13
- - Topics: ${r.topics.join(", ")||"None"}
14
- - Dependencies: ${r.dependencies.join(", ")||"None"}
15
-
16
- ## Available Instructions
17
-
18
- ${i}
19
-
20
- ## Task
21
-
22
- Analyze the project and recommend which instructions would be most useful. Consider:
23
- 1. Language and framework alignment
24
- 2. Project purpose and what standards/practices would help
25
- 3. Security, testing, and quality needs based on the project type
26
-
27
- Return your response as JSON in this exact format:
28
- {
29
- "recommendations": [
30
- { "instructionId": "<id>", "score": <0.0-1.0>, "reason": "<one sentence explanation>" }
31
- ]
32
- }
33
-
34
- Only include instructions with a relevance score >= 0.5. Order by score descending. Return valid JSON only, no markdown fences.`}e(y,"buildRecommendationPrompt");var x=["Added","Changed","Fixed","Removed","Deprecated","Security"],M=/^##\s+\[([^\]]+)\](?:\s*[-–]\s*(\d{4}-\d{2}-\d{2}))?\s*$/,b=/^###\s+(.+?)\s*$/,k=/^[-*]\s+(.*\S)\s*$/,S=/^ {2,}(\S.*)$/;function T(r){let a=r.split(/\r?\n/),i=[],n=null,l=null,c=null;for(let u of a){let p=u.match(M);if(p){n&&i.push(n);let d=p[1].trim();n={version:d,date:p[2]??null,unreleased:d.toLowerCase()==="unreleased",sections:{}},l=null,c=null;continue}if(!n)continue;let m=u.match(b);if(m){let d=m[1].trim();x.includes(d)?(l=d,n.sections[l]||(n.sections[l]=[]),c=n.sections[l]):(l=null,c=null);continue}if(!l||!c)continue;let f=u.match(k);if(f){c.push(f[1]);continue}let h=u.match(S);if(h&&c.length>0){c[c.length-1]+=" "+h[1].trim();continue}}return n&&i.push(n),{entries:i}}e(T,"parseChangelog");function I(r){return r.entries.filter(a=>a.unreleased?!1:Object.values(a.sections).some(i=>i&&i.length>0))}e(I,"announceableEntries");import re from"gray-matter";import{z as _}from"zod";var ce=_.object({type:_.enum(["instruction","prompt"])});export{R as a,y as b,T as c,I as d};
File without changes