rapidkit 0.27.0 → 0.27.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@ FastAPI, NestJS, Spring Boot, Go/Fiber, and Go/Gin scaffolding with production-r
6
6
  **27+ plug-and-play modules** are available for FastAPI & NestJS projects. Spring Boot and Go kits run as npm-level generators.
7
7
  Clean architecture • Zero boilerplate • Instant deployment.
8
8
 
9
- > **💡 Recommended:** Install the [Workspai VS Code extension](https://github.com/getrapidkit/rapidkit-vscode) for AI-powered project creation, a visual workspace explorer, and context-aware coding assistance — all backed by this CLI.
9
+ > **💡 Recommended:** Install the [Workspai VS Code extension](https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode) for AI-powered project creation, a visual workspace explorer, and context-aware coding assistance — all backed by this CLI.
10
10
 
11
11
  [![npm version](https://img.shields.io/npm/v/rapidkit.svg?style=flat-square)](https://www.npmjs.com/package/rapidkit)
12
12
  [![Downloads](https://img.shields.io/npm/dm/rapidkit.svg?style=flat-square)](https://www.npmjs.com/package/rapidkit)
@@ -93,6 +93,7 @@ npx rapidkit create # Prompts: workspace | project
93
93
  npx rapidkit create workspace <name> [--profile <profile>] [--author <name>] [--yes]
94
94
  npx rapidkit bootstrap [--profile <profile>] [--json]
95
95
  npx rapidkit setup <python|node|go|java> [--warm-deps]
96
+ npx rapidkit readiness [--json] [--strict]
96
97
  npx rapidkit workspace policy show
97
98
  npx rapidkit workspace policy set <key> <value>
98
99
  npx rapidkit doctor
@@ -133,18 +134,32 @@ RapidKit keeps the wrapper boundary explicit so users know which layer owns each
133
134
  | `create workspace`, `workspace`, `cache`, `mirror` | RapidKit wrapper | Platform-level orchestration |
134
135
  | `init` | Wrapper orchestrated | Chooses the right runtime flow for the current project |
135
136
  | `dev`, `test`, `build`, `start` | Runtime aware | Delegates to the active project/runtime when available |
137
+ | `readiness` | Wrapper release gate | Generates release-readiness evidence (`--json` for CI, `--strict` for fail-fast) |
136
138
  | `doctor` | Wrapper system check | Checks host prerequisites by default |
137
139
  | `doctor workspace` | Workspace health | Full workspace scan with project-level details and fixes |
138
140
 
139
141
  Use `npx rapidkit doctor` for a quick host pre-flight and `npx rapidkit doctor workspace` inside a workspace for the full health picture.
142
+ Use `npx rapidkit readiness` when you need machine-readable release evidence or strict CI gating.
140
143
 
141
144
  ### Doctor workspace fix behavior
142
145
 
143
146
  - `npx rapidkit doctor workspace` reuses cached project scans when valid and refreshes evidence under `.rapidkit/reports/doctor-last-run.json`.
144
147
  - `npx rapidkit doctor workspace --fix` only executes actionable fix commands.
148
+ - Advisory warnings (for example, detected vulnerabilities or optional env metadata gaps) are reported in workspace health, but they do not automatically become shell fix commands.
149
+ - It is valid to see `No fixes needed` after `--fix` when only advisory warnings are present.
145
150
  - URL-based fixes are recorded as manual guidance (for example, install pages) and are not executed as shell commands.
146
151
  - Go project fixes that require `go mod tidy` are skipped when the Go toolchain is not available, with a clear install-and-rerun hint.
147
152
 
153
+ ### Doctor workspace JSON fields (AI/automation)
154
+
155
+ `npx rapidkit doctor workspace --json` includes project-level runtime/profile metadata used by extension and AI tooling:
156
+
157
+ - `framework`
158
+ - `runtimeFamily`
159
+ - `projectKind`
160
+ - `supportTier`
161
+ - `frameworkConfidence`
162
+
148
163
  ### Project lifecycle
149
164
 
150
165
  ```bash
@@ -234,7 +249,7 @@ visual workspace explorer, AI-powered project creation, and context-aware coding
234
249
  Search **Workspai** in the VS Code Extensions marketplace, or:
235
250
 
236
251
  ```bash
237
- code --install-extension getrapidkit.workspai
252
+ ext install rapidkit.rapidkit-vscode
238
253
  ```
239
254
 
240
255
  > The extension calls this CLI under the hood — both tools work together seamlessly.
@@ -0,0 +1,39 @@
1
+ import {b,f,d,a as a$2,k,g,i as i$1}from'./chunk-Z5LKRG57.js';import {a as a$1}from'./chunk-VM2TOHNX.js';import a from'chalk';import {execa}from'execa';import i from'fs-extra';import o from'path';import ae from'inquirer';function re(e){return [...new Set(e.filter(s=>s&&s.trim().length>0))]}function ce(){let e=k().map(r=>o.join(r,a$2()?"poetry.exe":"poetry")),s=a$2()?[o.join(process.env.APPDATA||"","Python","Scripts","poetry.exe"),o.join(process.env.USERPROFILE||"","AppData","Roaming","Python","Scripts","poetry.exe")]:[],t=a$2()?[]:["/usr/local/bin/poetry","/usr/bin/poetry"];return re([...e,...s,...t])}function le(e){let s=k().map(d=>({location:"Global (user-local)",path:o.join(d,a$2()?"rapidkit.exe":"rapidkit")})),t=[{location:"Global (pipx)",path:o.join(e,".local","bin","rapidkit")},{location:"Global (pipx)",path:o.join(e,"AppData","Roaming","Python","Scripts","rapidkit.exe")},{location:"Global (pyenv)",path:o.join(e,".pyenv","shims","rapidkit")},{location:"Global (system)",path:"/usr/local/bin/rapidkit"},{location:"Global (system)",path:"/usr/bin/rapidkit"}],r=g(o.join(process.cwd(),".venv")),n=i$1(process.cwd()),c=[{location:"Workspace (.venv)",path:r},...n.map(d=>({location:"Workspace (launcher)",path:d}))],u=[...s,...t,...c],p=new Set;return u.filter(d=>p.has(d.path)?false:(p.add(d.path),true))}function de(e){let s=new Map([["Workspace (.venv)",0],["Global (user-local)",1],["Global (pipx)",2],["Global (pyenv)",3],["Global (system)",4]]);return [...e].sort((t,r)=>{let n=s.get(t.location)??Number.MAX_SAFE_INTEGER,c=s.get(r.location)??Number.MAX_SAFE_INTEGER;return n!==c?n-c:t.path.localeCompare(r.path)})}function B(e){let s=0,t=e.issues.some(r=>r.toLowerCase().includes("environment file missing"));return e.hasEnvFile===false&&!t&&(s+=1),typeof e.vulnerabilities=="number"&&e.vulnerabilities>0&&(s+=1),s}function O(e){return e.filter(s=>B(s)>0).length}function te(e){return e.reduce((s,t)=>s+B(t),0)}var ue="doctor-project-scan-v2";function $(e,s){return a$2()?`cd "${e}"; ${s}`:`cd ${e} && ${s}`}function K(e){return a$2()?$(e,"Copy-Item .env.example .env"):$(e,"cp .env.example .env")}function pe(e){return e==="FastAPI"||e==="NestJS"||e==="Go/Fiber"||e==="Go/Gin"||e==="Spring Boot"?"first-class":e==="Django"||e==="Flask"||e==="Express"||e==="Fastify"||e==="Koa"||e==="PHP"||e==="Laravel"||e==="Ruby"||e==="Ruby on Rails"||e==="ASP.NET"?"extended":"observed"}function me(e){return e==="Next.js"||e==="Nuxt"||e==="React"||e==="Vue"||e==="Angular"||e==="SvelteKit"?"frontend":e==="Unknown"||e==="Node.js"||e==="Python"?"generic":"backend"}function fe(e){return e==="NestJS"||e==="Next.js"||e==="Nuxt"||e==="React"||e==="Vue"||e==="Angular"||e==="SvelteKit"||e==="Express"||e==="Fastify"||e==="Koa"||e==="Node.js"?"node":e==="FastAPI"||e==="Django"||e==="Flask"||e==="Python"?"python":e==="Go/Fiber"||e==="Go/Gin"?"go":e==="Spring Boot"?"java":e==="Laravel"||e==="PHP"?"php":e==="Ruby on Rails"||e==="Ruby"?"ruby":e==="ASP.NET"?"dotnet":"unknown"}function A(e,s,t){e.framework=s,e.frameworkConfidence=t,e.supportTier=pe(s),e.projectKind=me(s),e.runtimeFamily=fe(s);}function he(e){let s=e.dependencies,t=e.scripts??{},r=(e.kitName??"").toLowerCase(),n=u=>!!s[u],c=Object.values(t).filter(u=>typeof u=="string").join(" ").toLowerCase();return n("next")||c.includes("next ")?{framework:"Next.js",confidence:"high"}:n("nuxt")||c.includes("nuxt ")?{framework:"Nuxt",confidence:"high"}:n("@nestjs/core")||r.startsWith("nestjs.")?{framework:"NestJS",confidence:"high"}:n("express")?{framework:"Express",confidence:"high"}:n("fastify")?{framework:"Fastify",confidence:"high"}:n("koa")?{framework:"Koa",confidence:"high"}:n("@angular/core")?{framework:"Angular",confidence:"high"}:n("@sveltejs/kit")||c.includes("svelte-kit")?{framework:"SvelteKit",confidence:"high"}:n("vue")?{framework:"Vue",confidence:"medium"}:n("react")&&n("react-dom")?{framework:"React",confidence:"medium"}:{framework:"Node.js",confidence:"low"}}async function ge(e){let s=[o.join(e,"pyproject.toml"),o.join(e,"requirements.txt")],t=[];for(let n of s)if(await i.pathExists(n))try{t.push((await i.readFile(n,"utf8")).toLowerCase());}catch{continue}let r=t.join(`
2
+ `);return r.includes("fastapi")?{framework:"FastAPI",confidence:"high"}:r.includes("django")?{framework:"Django",confidence:"high"}:r.includes("flask")?{framework:"Flask",confidence:"high"}:{framework:"Python",confidence:t.length>0?"medium":"low"}}async function X(e){try{let s=await i.stat(e);return `${o.basename(e)}:${s.isDirectory()?"d":"f"}:${s.size}:${s.mtimeMs}`}catch{return `${o.basename(e)}:missing`}}async function ye(e){try{let s=new Set([".git",".venv","node_modules",".rapidkit","dist","build","coverage","__pycache__"]),t=new Set;await q(e)&&t.add(e);let r=async(n,c)=>{if(c<0)return;let u=await ne(n);for(let p of u){if(ie(p,s))continue;let d=o.join(n,p);if(await q(d)){t.add(d);continue}c>0&&await r(d,c-1);}};return await r(e,1),t.size===0&&(await Fe(e,3,s)).forEach(c=>t.add(c)),Array.from(t).sort((n,c)=>n.localeCompare(c))}catch{return []}}async function we(e,s){let t=[o.join(e,".rapidkit-workspace"),o.join(e,".rapidkit","workspace.json"),o.join(e,".rapidkit","policies.yml"),o.join(e,".rapidkit","toolchain.lock"),o.join(e,".rapidkit","cache-config.yml")],r=[".rapidkit/project.json",".rapidkit/context.json",".rapidkit/file-hashes.json","package.json","pyproject.toml","composer.json","Gemfile","Gemfile.lock","go.mod","go.sum","pom.xml","requirements.txt","Dockerfile","Makefile",".env",".env.example","src","modules","tests","test",".venv","node_modules"],n=await Promise.all(t.map(X)),c=await Promise.all(s.map(async u=>{let p=await Promise.all(r.map(d=>X(o.join(u,d))));return `${u}::${p.join("|")}`}));return [ue,...n,...c].join("||")}async function ve(e,s){try{if(!await i.pathExists(e))return null;let t=await i.readJSON(e);return !t||t.signature!==s||!Array.isArray(t.projects)?null:t}catch{return null}}async function ke(e,s){try{await i.ensureDir(o.dirname(e)),await i.writeJSON(e,s,{spaces:2});}catch{}}async function xe(e,s,t){let r=o.join(e,".rapidkit","reports","doctor-last-run.json");try{return await i.ensureDir(o.dirname(r)),await i.writeJSON(r,{generatedAt:new Date().toISOString(),workspacePath:e,workspaceName:s.workspaceName,projectScanCached:s.projectScanCached??false,projectScanSignature:s.projectScanSignature,cachePath:t,healthScore:s.healthScore,system:{python:s.python,poetry:s.poetry,pipx:s.pipx,go:s.go,rapidkitCore:s.rapidkitCore,versions:{core:s.coreVersion,npm:s.npmVersion}},projects:s.projects,summary:{totalProjects:s.projects.length,totalIssues:s.projects.reduce((n,c)=>n+c.issues.length,0),projectAdvisoryWarningProjects:O(s.projects),projectAdvisoryWarnings:te(s.projects),hasSystemErrors:[s.python,s.rapidkitCore].some(n=>n.status==="error")}},{spaces:2}),r}catch{return}}async function se(){let[e,s,t,r,n]=await Promise.all([be(),Ce(),je(),Pe(),Ee()]);return {python:e,poetry:s,pipx:t,go:r,rapidkitCore:n}}async function be(){let e=d();for(let s of e)try{let{stdout:t}=await execa(s,["--version"],{timeout:3e3}),r=t.match(/Python (\d+\.\d+\.\d+)/);if(r){let n=r[1],[c,u]=n.split(".").map(Number);return c<3||c===3&&u<10?{status:"warn",message:`Python ${n} (requires 3.10+)`,details:`${s} found but version is below minimum requirement`}:{status:"ok",message:`Python ${n}`,details:`Using ${s}`}}}catch{continue}return {status:"error",message:"Python not found",details:"Install Python 3.10+ and ensure it's in PATH"}}async function Ce(){try{let{stdout:e}=await execa("poetry",["--version"],{timeout:3e3}),s=e.match(/Poetry .*version ([\d.]+)/);return s?{status:"ok",message:`Poetry ${s[1]}`,details:"Available for dependency management"}:{status:"warn",message:"Poetry version unknown"}}catch{let e=d().map(s=>({cmd:s,args:s==="py"?["-3","-m","poetry","--version"]:["-m","poetry","--version"]}));for(let s of e)try{let{stdout:t}=await execa(s.cmd,s.args,{timeout:3e3,shell:b()}),r=t.match(/Poetry .*version ([\d.]+)/)||t.match(/([\d.]+)/);return {status:"ok",message:r?.[1]?`Poetry ${r[1]}`:"Poetry detected",details:`Available via ${s.cmd} ${s.args.join(" ")}`}}catch{continue}for(let s of ce())try{if(!await i.pathExists(s))continue;let{stdout:t}=await execa(s,["--version"],{timeout:3e3,shell:b()}),r=t.match(/Poetry .*version ([\d.]+)/)||t.match(/([\d.]+)/);return {status:"ok",message:r?.[1]?`Poetry ${r[1]}`:"Poetry detected",details:`Available at ${s}`}}catch{continue}return {status:"warn",message:"Poetry not installed",details:"Optional: Install for better dependency management"}}}async function je(){try{let{stdout:e}=await execa("pipx",["--version"],{timeout:3e3});return {status:"ok",message:`pipx ${e.trim()}`,details:"Available for global tool installation"}}catch{let e=d();for(let s of e)try{let t=s==="py"?["-3","-m","pipx","--version"]:["-m","pipx","--version"],{stdout:r}=await execa(s,t,{timeout:3e3,shell:b()});return {status:"ok",message:`pipx ${r.trim()}`,details:`Available via ${s} ${t.join(" ")}`}}catch{continue}return {status:"warn",message:"pipx not installed",details:"Optional: Install for isolated Python tools"}}}async function Pe(){try{let{stdout:e}=await execa("go",["version"],{timeout:3e3}),s=e.match(/go version go(\d+\.\d+(?:\.\d+)?)/);return s?{status:"ok",message:`Go ${s[1]}`,details:"Available for Go/Fiber and Go/Gin projects"}:{status:"ok",message:"Go (version unknown)",details:"go found in PATH"}}catch{return {status:"warn",message:"Go not installed",details:"Optional: Required only for gofiber.standard / gogin.standard projects \u2014 https://go.dev/dl/"}}}async function Ee(){let e=process.env.HOME||process.env.USERPROFILE||"",s=[],t=le(e);for(let{location:n,path:c}of t)try{if(await i.pathExists(c)){let{stdout:u,exitCode:p}=await execa(c,["--version"],{timeout:3e3,reject:false});if(p===0&&(u.includes("RapidKit Version")||u.includes("RapidKit"))){let d=u.match(/v?([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);d&&s.push({location:n,path:c,version:d[1]});}}}catch{continue}if(s.length>0){let n=s.filter(u=>u.location!=="Workspace (launcher)");if(n.length>0){let u=de(n);return {status:"ok",message:`RapidKit Core ${u[0].version}`,paths:u.map(d=>({location:d.location,path:d.path,version:d.version}))}}return {status:"ok",message:`RapidKit Core ${s[0].version}`,details:"Detected via workspace launcher"}}try{let{stdout:n,exitCode:c}=await execa("rapidkit",["--version"],{timeout:3e3,reject:false});if(c===0&&(n.includes("RapidKit Version")||n.includes("RapidKit"))){let u=n.match(/v?([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);if(u)return {status:"ok",message:`RapidKit Core ${u[1]}`,details:"Available via PATH"}}}catch{}try{let{stdout:n,exitCode:c}=await execa("poetry",["run","rapidkit","--version"],{timeout:3e3,reject:false});if(c===0&&(n.includes("RapidKit Version")||n.includes("RapidKit"))){let u=n.match(/v?([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);if(u)return {status:"ok",message:`RapidKit Core ${u[1]}`,details:"Available via Poetry"}}}catch{}let r=d();for(let n of r)try{let{stdout:c,exitCode:u}=await execa(n,["-c","import rapidkit_core; print(rapidkit_core.__version__)"],{timeout:3e3,reject:false});if(u===0&&c&&!c.includes("Traceback")&&!c.includes("ModuleNotFoundError")){let p=c.trim();if(p)return {status:"ok",message:`RapidKit Core ${p}`,details:`Available in ${n} environment`}}}catch{continue}return {status:"error",message:"RapidKit Core not installed",details:"Install with: pipx install rapidkit-core"}}async function H(e,s){let t=o.join(e,"Dockerfile");s.hasDocker=await i.pathExists(t);let r=o.join(e,"tests"),n=o.join(e,"test"),c=o.join(e,"src","test"),u=await i.pathExists(r)||await i.pathExists(n)||await i.pathExists(c),p=false;if(s.framework==="Go/Fiber"||s.framework==="Go/Gin")try{let d=[{dir:e,depth:0}],l=4,m=new Set([".git",".venv","node_modules","dist","build","vendor"]);for(;d.length>0&&!p;){let f=d.shift();if(!f)break;let w=[];try{w=await i.readdir(f.dir);}catch{continue}for(let x of w){let I=o.join(f.dir,x),R;try{R=await i.stat(I);}catch{continue}if(R.isFile()&&x.endsWith("_test.go")){p=true;break}R.isDirectory()&&f.depth<l&&!m.has(x)&&!x.startsWith(".")&&d.push({dir:I,depth:f.depth+1});}}}catch{}if(s.hasTests=u||p,s.runtimeFamily==="node"){let d=o.join(e,".eslintrc.js"),l=o.join(e,".eslintrc.json");s.hasCodeQuality=await i.pathExists(d)||await i.pathExists(l);}else if(s.framework==="Go/Fiber"||s.framework==="Go/Gin"){let d=o.join(e,".golangci.yml"),l=o.join(e,".golangci.yaml"),m=o.join(e,"Makefile"),f=await i.pathExists(m)&&(await i.readFile(m,"utf8")).includes("golangci-lint");s.hasCodeQuality=await i.pathExists(d)||await i.pathExists(l)||f;}else if(s.runtimeFamily==="python"){let d=o.join(e,"ruff.toml"),l=o.join(e,"pyproject.toml");if(await i.pathExists(l))try{let m=await i.readFile(l,"utf8");s.hasCodeQuality=m.includes("[tool.ruff]")||await i.pathExists(d);}catch{s.hasCodeQuality=await i.pathExists(d);}}else if(s.framework==="Spring Boot"){let d=o.join(e,"pom.xml");if(await i.pathExists(d))try{let l=await i.readFile(d,"utf8");s.hasCodeQuality=l.includes("spotless")||l.includes("checkstyle")||l.includes("pmd")||l.includes("maven-enforcer-plugin");}catch{s.hasCodeQuality=false;}}try{if(s.runtimeFamily==="node"){let{stdout:d}=await execa("npm",["audit","--json"],{cwd:e,reject:false});if(d)try{let m=JSON.parse(d).metadata?.vulnerabilities;m&&(s.vulnerabilities=(m.high||0)+(m.critical||0)+(m.moderate||0));}catch{}}else if(s.runtimeFamily==="python"){let d=o.join(e,".venv"),l=f(d);if(await i.pathExists(l))try{let{stdout:m}=await execa(l,["-m","pip","list","--format=json"],{timeout:5e3,reject:false});if(m){JSON.parse(m);s.vulnerabilities=0;}}catch{}}}catch{}}async function $e(e){let t={name:o.basename(e),path:e,venvActive:false,depsInstalled:false,coreInstalled:false,issues:[],fixCommands:[]},r=o.join(e,".rapidkit");if(!await i.pathExists(r))return t.issues.push("Not a valid RapidKit project (missing .rapidkit directory)"),t;try{let g=o.join(e,"registry.json");if(await i.pathExists(g)){let h=await i.readJson(g);h.installed_modules&&(t.stats={modules:h.installed_modules.length});}}catch{}let n=null;try{let g=o.join(r,"project.json");if(await i.pathExists(g)){n=await i.readJson(g);let h=n?.kit_name||n?.kit;h&&(t.kit=h);}}catch{}try{let g=o.join(e,".git");if(await i.pathExists(g)){let{stdout:h}=await execa("git",["log","-1","--format=%cr"],{cwd:e,reject:false});h&&(t.lastModified=h.trim());}else {let h=await i.stat(e),P=Date.now()-h.mtime.getTime(),v=Math.floor(P/(1e3*60*60*24));t.lastModified=v===0?"today":`${v} day${v>1?"s":""} ago`;}}catch{}let c=o.join(e,"package.json"),u=o.join(e,"pyproject.toml"),p=o.join(e,"requirements.txt"),d=o.join(e,"go.mod"),l=o.join(e,"pom.xml"),m=o.join(e,"composer.json"),f$1=o.join(e,"Gemfile"),w=await i.pathExists(c),x=await i.pathExists(u)||await i.pathExists(p),I=await i.pathExists(m),R=await i.pathExists(f$1),_=false;try{_=(await i.readdir(e)).some(h=>h.endsWith(".csproj")||h.endsWith(".sln"));}catch{_=false;}if(await i.pathExists(d)||n?.runtime==="go"||typeof n?.kit_name=="string"&&(n.kit_name.startsWith("gofiber")||n.kit_name.startsWith("gogin"))){let g=n?.kit_name??"";A(t,g.startsWith("gogin")?"Go/Gin":"Go/Fiber","high"),t.isGoProject=true,t.venvActive=true,t.coreInstalled=false;try{await execa("go",["version"],{timeout:3e3});}catch{t.issues.push("Go toolchain not found \u2014 install from https://go.dev/dl/"),t.fixCommands?.push("https://go.dev/dl/");}let h=o.join(e,"go.sum");return await i.pathExists(h)?t.depsInstalled=true:(t.depsInstalled=false,t.issues.push("Go dependencies not downloaded (go.sum missing)"),t.fixCommands?.push($(e,"go mod tidy"))),await H(e,t),t}if(await i.pathExists(l)||n?.runtime==="java"||typeof n?.kit_name=="string"&&n.kit_name.startsWith("springboot")){A(t,"Spring Boot","high"),t.venvActive=true,t.coreInstalled=false;let g=await i.pathExists(l),h=await i.pathExists(o.join(e,"build.gradle"))||await i.pathExists(o.join(e,"build.gradle.kts")),j=await i.pathExists(o.join(e,"mvnw"))||await i.pathExists(o.join(e,"mvnw.cmd")),P=await i.pathExists(o.join(e,"gradlew"))||await i.pathExists(o.join(e,"gradlew.bat"));try{await execa("java",["-version"],{timeout:3e3,reject:false});}catch{t.issues.push("Java runtime not found \u2014 install JDK 21+ and ensure java is on PATH"),t.fixCommands?.push("https://adoptium.net/");}if(g){if(!j)try{await execa("mvn",["-version"],{timeout:3e3,reject:false});}catch{t.issues.push("Maven not found \u2014 install Maven 3.9+ or add Maven Wrapper"),t.fixCommands?.push("https://maven.apache.org/install.html");}}else if(h&&!P)try{await execa("gradle",["--version"],{timeout:3e3,reject:false});}catch{t.issues.push("Gradle not found \u2014 install Gradle 8+ or add Gradle Wrapper"),t.fixCommands?.push("https://gradle.org/install/");}let v=o.join(e,"target"),k=o.join(e,"build","libs"),C=o.join(e,".rapidkit","cache","java","m2"),b=o.join(e,".rapidkit","cache","java","gradle");t.depsInstalled=await i.pathExists(v)||await i.pathExists(k)||await i.pathExists(C)||await i.pathExists(b),t.depsInstalled||(t.issues.push("Java dependencies are not warmed or built yet"),t.fixCommands?.push($(e,"rapidkit init")));let E=o.join(e,".env");if(t.hasEnvFile=await i.pathExists(E),!t.hasEnvFile){let D=o.join(e,".env.example");await i.pathExists(D)&&(t.issues.push("Environment file missing (found .env.example)"),t.fixCommands?.push(K(e)));}let F=o.join(e,"src","main","resources","application.yml");if(await i.pathExists(F))try{let D=await i.readFile(F,"utf-8");/include:\s*[^\n]*health/i.test(D)||/management:\s*[\s\S]*endpoint:\s*[\s\S]*health:/i.test(D)||(t.issues.push("Actuator health endpoint exposure is not clearly configured in application.yml"),t.fixCommands?.push($(e,"Ensure management.endpoints.web.exposure.include contains health in src/main/resources/application.yml")));}catch{t.issues.push("Unable to read application.yml for Spring Actuator health checks");}return await H(e,t),t}if(w){let g=null;try{g=await i.readJson(c);}catch{g=null;}let h={...g?.dependencies??{},...g?.devDependencies??{}},j=g?.scripts??{},P=typeof n?.kit_name=="string"?n.kit_name.toLowerCase():typeof n?.kit=="string"?n.kit.toLowerCase():"",v=he({dependencies:h,scripts:j,kitName:P});A(t,v.framework,v.confidence),t.venvActive=true;let k=o.join(e,"node_modules");if(await i.pathExists(k))try{let E=(await i.readdir(k)).filter(F=>!F.startsWith(".")&&!F.startsWith("_"));t.depsInstalled=E.length>0;}catch{t.depsInstalled=false;}if(t.depsInstalled||(t.issues.push("Dependencies not installed (node_modules empty or missing)"),t.fixCommands?.push($(e,"rapidkit init"))),t.coreInstalled=false,t.projectKind==="frontend"){let b=[".env",".env.local",".env.development",".env.development.local",".env.production",".env.production.local"];if((await Promise.all(b.map(F=>i.pathExists(o.join(e,F))))).some(Boolean))t.hasEnvFile=true;else {let F=o.join(e,".env.example");await i.pathExists(F)&&(t.hasEnvFile=false,t.issues.push("Environment file missing (found .env.example)"),t.fixCommands?.push(K(e)));}}else {let b=o.join(e,".env");if(t.hasEnvFile=await i.pathExists(b),!t.hasEnvFile){let E=o.join(e,".env.example");await i.pathExists(E)&&(t.issues.push("Environment file missing (found .env.example)"),t.fixCommands?.push(K(e)));}}let C=o.join(e,"src");if(t.modulesHealthy=true,t.missingModules=[],await i.pathExists(C))try{let b=await i.readdir(C);t.modulesHealthy=b.length>0;}catch{t.modulesHealthy=false;}return await H(e,t),t}if(x){let g=await ge(e);A(t,g.framework,g.confidence);let h=o.join(e,".venv");if(await i.pathExists(h)){t.venvActive=true;let k=f(h);if(await i.pathExists(k)){try{let{stdout:E}=await execa(k,["-c","import rapidkit_core; print(rapidkit_core.__version__)"],{timeout:2e3});t.coreInstalled=true,t.coreVersion=E.trim();}catch{t.coreInstalled=false;}let C="fastapi";t.framework==="Django"?C="django":t.framework==="Flask"?C="flask":t.framework==="Python"&&(C="");let b=true;if(C)try{await execa(k,["-c",`import ${C}`],{timeout:2e3}),t.depsInstalled=true,b=false;}catch{b=true;}if(b)try{let E=o.join(h,"lib");if(await i.pathExists(E)){let D=(await i.readdir(E)).find(M=>M.startsWith("python"));if(D){let M=o.join(E,D,"site-packages");if(await i.pathExists(M)){let oe=(await i.readdir(M)).filter(V=>!V.startsWith("_")&&!V.includes("dist-info")&&!["pip","setuptools","wheel","pkg_resources"].includes(V));t.depsInstalled=oe.length>0;}}}t.depsInstalled||(t.issues.push("Dependencies not installed"),t.fixCommands?.push($(e,"rapidkit init")));}catch{t.issues.push("Could not verify dependency installation");}}else t.issues.push("Virtual environment exists but Python executable not found");}else t.issues.push("Virtual environment not created"),t.fixCommands?.push($(e,"rapidkit init"));let j=o.join(e,".env");if(t.hasEnvFile=await i.pathExists(j),!t.hasEnvFile){let k=o.join(e,".env.example");await i.pathExists(k)&&(t.issues.push("Environment file missing (found .env.example)"),t.fixCommands?.push(K(e)));}let P=o.join(e,"src"),v=o.join(e,"modules");if(t.modulesHealthy=true,t.missingModules=[],await i.pathExists(P)){let k=o.join(P,"__init__.py");await i.pathExists(k)||(t.modulesHealthy=false,t.missingModules.push("src/__init__.py"));}if(await i.pathExists(v))try{let k=await ne(v);for(let C of k){let b=o.join(v,C,"__init__.py");await i.pathExists(b)||(t.modulesHealthy=false,t.missingModules.push(`modules/${C}/__init__.py`));}}catch{}return !t.modulesHealthy&&t.missingModules.length>0&&t.issues.push(`Missing module init files: ${t.missingModules.join(", ")}`),await H(e,t),t}if(I){let g="PHP",h="medium";try{let v=await i.readJson(m);({...v?.require??{},...v?.["require-dev"]??{}})["laravel/framework"]?(g="Laravel",h="high"):(g="PHP",h="medium");}catch{g="PHP",h="low";}A(t,g,h),t.venvActive=true,t.coreInstalled=false;let j=o.join(e,"vendor");t.depsInstalled=await i.pathExists(j),t.depsInstalled||(t.issues.push("PHP dependencies not installed (vendor missing)"),t.fixCommands?.push($(e,"composer install")));let P=o.join(e,".env");if(t.hasEnvFile=await i.pathExists(P),!t.hasEnvFile){let v=o.join(e,".env.example");await i.pathExists(v)&&(t.issues.push("Environment file missing (found .env.example)"),t.fixCommands?.push(K(e)));}return await H(e,t),t}if(R){let g="Ruby",h="low";try{let k=(await i.readFile(f$1,"utf8")).toLowerCase();k.includes("gem 'rails'")||k.includes('gem "rails"')?(g="Ruby on Rails",h="high"):(g="Ruby",h="medium");}catch{h="low";}A(t,g,h),t.venvActive=true,t.coreInstalled=false;let j=await i.pathExists(o.join(e,"Gemfile.lock")),P=await i.pathExists(o.join(e,"vendor","bundle"));t.depsInstalled=j||P,t.depsInstalled||(t.issues.push("Ruby dependencies not installed (Gemfile.lock/vendor missing)"),t.fixCommands?.push($(e,"bundle install")));let v=o.join(e,".env");return t.hasEnvFile=await i.pathExists(v),await H(e,t),t}if(_){A(t,"ASP.NET","medium"),t.venvActive=true,t.coreInstalled=false;let g=o.join(e,"obj"),h=o.join(e,"packages.lock.json");t.depsInstalled=await i.pathExists(g)||await i.pathExists(h),t.depsInstalled||(t.issues.push(".NET restore/build artifacts not found"),t.fixCommands?.push($(e,"dotnet restore")));let j=o.join(e,".env");return t.hasEnvFile=await i.pathExists(j),await H(e,t),t}return A(t,"Unknown","low"),t.issues.push("Unknown project type (no recognized runtime marker files)"),await H(e,t),t}async function ne(e){try{return (await i.readdir(e,{withFileTypes:true})).filter(t=>t.isDirectory()).map(t=>t.name)}catch{try{let s=await i.readdir(e),t=[];for(let r of s)try{(await i.stat(o.join(e,r))).isDirectory()&&t.push(r);}catch{continue}return t}catch{return []}}}async function q(e){let s=o.join(e,".rapidkit");if(!await i.pathExists(s))return false;let t=["project.json","context.json","file-hashes.json"];for(let r of t)if(await i.pathExists(o.join(s,r)))return true;return false}function ie(e,s){if(s.has(e))return true;let t=e.toLowerCase();return !!(t==="dist"||t.startsWith("dist-")||t.startsWith("dist_")||t==="build"||t.startsWith("build-")||t.startsWith("build_"))}async function Fe(e,s,t){let r=new Set,n=[{dir:e,depth:0}];for(;n.length>0;){let c=n.shift();if(!c)break;try{let u=await i.readdir(c.dir);for(let p of u){if(ie(p,t))continue;let d=o.join(c.dir,p),l;try{l=await i.stat(d);}catch{continue}if(l.isDirectory()){if(await q(d)){r.add(d);continue}c.depth<s&&n.push({dir:d,depth:c.depth+1});}}}catch{continue}}return Array.from(r)}async function z(e){let s=e,t=o.parse(s).root;for(;s!==t;){let r=[o.join(s,".rapidkit-workspace"),o.join(s,".rapidkit","workspace-marker.json"),o.join(s,".rapidkit","config.json")];for(let n of r)if(await i.pathExists(n))return s;s=o.dirname(s);}return null}function Se(e,s){let t=0,r=0,n=0;return e.forEach(u=>{u.status==="ok"?t++:u.status==="warn"?r++:u.status==="error"&&n++;}),s.forEach(u=>{let p=B(u),d=u.isGoProject?u.issues.length===0&&u.depsInstalled:u.issues.length===0&&u.venvActive&&u.depsInstalled;if(u.issues.length>0||p>0||!d){r++;return}t++;}),{total:t+r+n,passed:t,warnings:r,errors:n}}async function Y(e,s=true){let t=o.basename(e);try{let m=o.join(e,".rapidkit-workspace");await i.pathExists(m)&&(t=(await i.readJSON(m)).name||t);}catch{try{let m=o.join(e,".rapidkit","config.json");t=(await i.readJSON(m)).workspace_name||t;}catch{}}let[r,n]=await Promise.all([se(),ye(e)]),c={workspacePath:e,workspaceName:t,python:r.python,poetry:r.poetry,pipx:r.pipx,go:r.go,rapidkitCore:r.rapidkitCore,projects:[]};a$1.debug(`Workspace scan found ${n.length} project(s)`);let u=await we(e,n),p=o.join(e,".rapidkit","reports","doctor-workspace-cache.json"),d=s?await ve(p,u):null;if(d)c.projects=d.projects,c.projectScanCached=true,a$1.debug(`Workspace project health cache hit: ${p}`);else try{let m=await Promise.all(n.map(f=>$e(f)));c.projects=m,c.projectScanCached=false,await ke(p,{signature:u,generatedAt:new Date().toISOString(),projects:m}),a$1.debug(`Workspace project health cache refreshed: ${p}`);}catch(m){a$1.debug(`Failed to scan workspace projects: ${m}`);}c.projectScanSignature=u,c.projectScanCachePath=p;let l=[c.python,c.poetry,c.pipx,c.go,c.rapidkitCore];if(c.healthScore=Se(l,c.projects),c.rapidkitCore.status==="ok"){let m=c.rapidkitCore.message.match(/([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);m&&(c.coreVersion=m[1]);}return c.evidencePath=await xe(e,c,d?p:null),c}function S(e,s){let t=e.status==="ok"?"\u2705":e.status==="warn"?"\u26A0\uFE0F":"\u274C",r=e.status==="ok"?a.green:e.status==="warn"?a.yellow:a.red;console.log(`${t} ${a.bold(s)}: ${r(e.message)}`),e.paths&&e.paths.length>0?e.paths.forEach(n=>{let c=n.version?a.cyan(` -> ${n.version}`):"";console.log(` ${a.cyan("\u2022")} ${a.gray(n.location)}: ${a.dim(n.path)}${c}`);}):e.details&&console.log(` ${a.gray(e.details)}`);}function Re(e){let s=e.issues.length>0,t=s?"\u26A0\uFE0F":"\u2705",r=s?a.yellow:a.green;if(console.log(`
3
+ ${t} ${a.bold("Project")}: ${r(e.name)}`),e.framework){let u=e.framework==="FastAPI"||e.framework==="Django"||e.framework==="Flask"?"\u{1F40D}":e.framework==="NestJS"?"\u{1F985}":e.framework==="Next.js"||e.framework==="Nuxt"?"\u25B2":e.framework==="React"?"\u269B\uFE0F":e.framework==="Vue"?"\u{1F7E2}":e.framework==="Angular"?"\u{1F170}\uFE0F":e.framework==="SvelteKit"?"\u{1F9E1}":e.framework==="Spring Boot"?"\u2615":e.framework==="Go/Fiber"||e.framework==="Go/Gin"?"\u{1F439}":e.framework==="Laravel"||e.framework==="PHP"?"\u{1F418}":e.framework==="Ruby on Rails"||e.framework==="Ruby"?"\u{1F48E}":e.framework==="ASP.NET"?"\u{1F537}":"\u{1F4E6}";console.log(` ${u} Framework: ${a.cyan(e.framework)}${e.kit?a.gray(` (${e.kit})`):""}`);let p=[];e.runtimeFamily&&p.push(`runtime: ${e.runtimeFamily}`),e.projectKind&&p.push(`kind: ${e.projectKind}`),e.supportTier&&p.push(`support: ${e.supportTier}`),e.frameworkConfidence&&p.push(`confidence: ${e.frameworkConfidence}`),p.length>0&&console.log(` ${a.dim("\u21B3")} ${a.gray(p.join(" \u2022 "))}`);}if(console.log(` ${a.gray(`Path: ${e.path}`)}`),e.runtimeFamily==="python"&&(e.venvActive?console.log(` \u2705 Virtual environment: ${a.green("Active")}`):console.log(` \u274C Virtual environment: ${a.red("Not found")}`),e.coreInstalled?console.log(` ${a.dim("\u2139")} RapidKit Core: ${a.gray(e.coreVersion||"In venv")} ${a.dim("(optional)")}`):console.log(` ${a.dim("\u2139")} RapidKit Core: ${a.gray("Using global installation")} ${a.dim("(recommended)")}`)),e.depsInstalled?console.log(` \u2705 Dependencies: ${a.green("Installed")}`):console.log(` \u26A0\uFE0F Dependencies: ${a.yellow("Not installed")}`),e.hasEnvFile!==void 0&&(e.hasEnvFile?console.log(` \u2705 Environment: ${a.green(".env configured")}`):console.log(` \u26A0\uFE0F Environment: ${a.yellow(".env missing")}`)),e.modulesHealthy!==void 0&&(e.modulesHealthy?console.log(` \u2705 Modules: ${a.green("Healthy")}`):e.missingModules&&e.missingModules.length>0&&console.log(` \u26A0\uFE0F Modules: ${a.yellow(`Missing ${e.missingModules.length} init file(s)`)}`)),e.stats){let u=[];e.stats.modules!==void 0&&u.push(`${e.stats.modules} module${e.stats.modules!==1?"s":""}`),u.length>0&&console.log(` \u{1F4CA} Stats: ${a.cyan(u.join(" \u2022 "))}`);}e.lastModified&&console.log(` \u{1F552} Last Modified: ${a.gray(e.lastModified)}`);let c=[];if(e.hasTests!==void 0&&c.push(e.hasTests?"\u2705 Tests":a.dim("\u2298 No tests")),e.hasDocker!==void 0&&c.push(e.hasDocker?"\u2705 Docker":a.dim("\u2298 No Docker")),e.hasCodeQuality!==void 0){let u=e.runtimeFamily==="node"?"ESLint":e.framework==="Spring Boot"?"Static analysis":e.framework==="Go/Fiber"||e.framework==="Go/Gin"?"golangci-lint":e.runtimeFamily==="python"?"Ruff":"Lint";c.push(e.hasCodeQuality?`\u2705 ${u}`:a.dim(`\u2298 No ${u}`));}c.length>0&&console.log(` ${c.join(" \u2022 ")}`),e.vulnerabilities!==void 0&&e.vulnerabilities>0&&console.log(` \u26A0\uFE0F Security: ${a.yellow(`${e.vulnerabilities} vulnerability(ies) found`)}`),e.issues.length>0&&(console.log(` ${a.bold("Issues:")}`),e.issues.forEach(u=>{console.log(` \u2022 ${a.yellow(u)}`);}),e.fixCommands&&e.fixCommands.length>0&&(console.log(`
4
+ ${a.bold.cyan("\u{1F527} Quick Fix:")}`),e.fixCommands.forEach(u=>{console.log(` ${a.cyan("$")} ${a.white(u)}`);})));}async function Z(){try{return (await execa("go",["version"],{timeout:3e3,reject:false})).exitCode===0}catch{return false}}async function ee(e,s=false){let t=e.filter(l=>l.fixCommands&&l.fixCommands.length>0),r=null;if(t.length===0){console.log(a.green(`
5
+ \u2705 No fixes needed - all projects are healthy!`));return}console.log(a.bold.cyan(`
6
+ \u{1F527} Available Fixes:
7
+ `));for(let l of t){let m=l.fixCommands??[];console.log(a.bold(`Project: ${a.yellow(l.name)}`)),m.forEach((f,w)=>{console.log(` ${w+1}. ${a.cyan(f)}`);}),console.log();}let n=0;for(let l of t){let m=l.fixCommands??[];for(let f of m){if(/^https?:\/\//i.test(f.trim()))continue;if(p(f,"cp\\s+\\.env\\.example\\s+\\.env")||p(f,"copy-item\\s+\\.env\\.example\\s+\\.env")||p(f,"rapidkit\\s+init")){n+=1;continue}if(p(f,"go\\s+mod\\s+tidy")){r===null&&(r=await Z()),r&&(n+=1);continue}n+=1;}}if(n===0){console.log(a.gray("\u{1F4A1} No automatic fixes can be applied right now.")),r===false&&console.log(a.gray(" Install Go to enable go mod tidy fixes, then rerun `rapidkit doctor workspace --fix`."));return}if(!s){console.log(a.gray('\u{1F4A1} Run "npx rapidkit doctor workspace --fix" to apply fixes automatically'));return}let{confirm:c}=await ae.prompt([{type:"confirm",name:"confirm",message:`Apply ${t.reduce((l,m)=>l+(m.fixCommands?.length??0),0)} fix(es)?`,default:false}]);if(!c){console.log(a.yellow(`
8
+ \u26A0\uFE0F Fixes cancelled by user`));return}console.log(a.bold.cyan(`
9
+ \u{1F680} Applying fixes...
10
+ `));let u=l=>/^https?:\/\//i.test(l.trim());function p(l,m){let f=[new RegExp(`^cd\\s+"([^"]+)"\\s*(?:&&|;)\\s*${m}\\s*$`,"i"),new RegExp(`^cd\\s+'([^']+)'\\s*(?:&&|;)\\s*${m}\\s*$`,"i"),new RegExp(`^cd\\s+(.+?)\\s*(?:&&|;)\\s*${m}\\s*$`,"i")];for(let w of f){let x=l.match(w);if(x?.[1])return {projectPath:x[1].trim()}}return null}function d(l){return p(l,"cp\\s+\\.env\\.example\\s+\\.env")||p(l,"copy-item\\s+\\.env\\.example\\s+\\.env")}for(let l of t){let m=l.fixCommands??[];console.log(a.bold(`Fixing ${a.cyan(l.name)}...`));for(let f of m)try{if(console.log(a.gray(` $ ${f}`)),u(f)){console.log(a.yellow(` \u2139 Manual action required: open ${f}`)),console.log(a.green(` \u2705 Recorded as guidance
11
+ `));continue}let w=d(f);if(w){let R=o.join(w.projectPath,".env.example"),_=o.join(w.projectPath,".env");if(!await i.pathExists(R))throw new Error(`.env.example not found at ${R}`);if(await i.pathExists(_)){console.log(a.green(` \u2705 .env already exists
12
+ `));continue}await i.copy(R,_,{overwrite:false,errorOnExist:false}),console.log(a.green(` \u2705 Success
13
+ `));continue}let x=p(f,"rapidkit\\s+init");if(x){await execa("rapidkit",["init"],{cwd:x.projectPath,shell:b(),stdio:"inherit"}),console.log(a.green(` \u2705 Success
14
+ `));continue}let I=p(f,"go\\s+mod\\s+tidy");if(I){if(r===null&&(r=await Z()),!r){console.log(a.yellow(" \u26A0 Go toolchain is not installed \u2014 skipping go mod tidy; install Go to apply this fix.")),console.log(a.green(` \u2705 Recorded as guidance
15
+ `));continue}await execa("go",["mod","tidy"],{cwd:I.projectPath,shell:b(),stdio:"inherit"}),console.log(a.green(` \u2705 Success
16
+ `));continue}await execa(f,{shell:true,stdio:"inherit"}),console.log(a.green(` \u2705 Success
17
+ `));}catch(w){console.log(a.red(` \u274C Failed: ${w instanceof Error?w.message:String(w)}
18
+ `));}}console.log(a.bold.green(`
19
+ \u2705 Fix process completed!`));}async function Je(e={}){let s=!e.workspace&&e.fix?await z(process.cwd()):null,t=e.workspace||!!s;if(e.json||console.log(a.bold.cyan(`
20
+ \u{1FA7A} RapidKit Health Check
21
+ `)),t){let r=s??await z(process.cwd());r||(a$1.error("No RapidKit workspace found in current directory or parents"),a$1.info('Run this command from within a workspace, or use "rapidkit doctor" for system check'),process.exit(1)),e.json||(s&&console.log(a.gray("\u2139\uFE0F Detected workspace context; enabling workspace checks for --fix")),console.log(a.bold(`Workspace: ${a.cyan(o.basename(r))}`)),console.log(a.gray(`Path: ${r}`)));let n=await Y(r);if(e.json||(n.projectScanCached&&console.log(a.gray(`\u2139\uFE0F Reused cached project scan${n.projectScanCachePath?` (${o.basename(n.projectScanCachePath)})`:""}`)),n.evidencePath&&console.log(a.gray(`\u2139\uFE0F Evidence saved: ${n.evidencePath}`))),e.json){let d={workspace:{name:o.basename(r),path:r},cache:{projectScan:n.projectScanCached??false,projectScanPath:n.projectScanCachePath,evidencePath:n.evidencePath},healthScore:n.healthScore,system:{python:n.python,poetry:n.poetry,pipx:n.pipx,rapidkitCore:n.rapidkitCore,versions:{core:n.coreVersion,npm:n.npmVersion}},projects:n.projects.map(l=>({name:l.name,path:l.path,framework:l.framework,runtimeFamily:l.runtimeFamily,projectKind:l.projectKind,supportTier:l.supportTier,frameworkConfidence:l.frameworkConfidence,venvActive:l.venvActive,depsInstalled:l.depsInstalled,hasEnvFile:l.hasEnvFile,vulnerabilities:l.vulnerabilities,coreInstalled:l.coreInstalled,coreVersion:l.coreVersion,issues:l.issues,fixCommands:l.fixCommands})),summary:{totalProjects:n.projects.length,totalIssues:n.projects.reduce((l,m)=>l+m.issues.length,0),projectAdvisoryWarningProjects:O(n.projects),projectAdvisoryWarnings:te(n.projects),hasSystemErrors:[n.python,n.rapidkitCore].some(l=>l.status==="error")}};console.log(JSON.stringify(d,null,2));return}if(n.healthScore){let d=n.healthScore,l=Math.round(d.passed/d.total*100),m=l>=80?a.green:l>=50?a.yellow:a.red,f="\u2588".repeat(Math.floor(l/5))+"\u2591".repeat(20-Math.floor(l/5));console.log(a.bold(`
22
+ \u{1F4CA} Health Score:`)),console.log(` ${m(`${l}%`)} ${a.gray(f)}`),console.log(` ${a.green(`\u2705 ${d.passed} passed`)} ${a.gray("|")} ${a.yellow(`\u26A0\uFE0F ${d.warnings} warnings`)} ${a.gray("|")} ${a.red(`\u274C ${d.errors} errors`)}`);}if(console.log(a.bold(`
23
+
24
+ System Tools:
25
+ `)),S(n.python,"Python"),S(n.poetry,"Poetry"),S(n.pipx,"pipx"),S(n.go,"Go"),S(n.rapidkitCore,"RapidKit Core"),n.coreVersion&&n.npmVersion){let d=n.coreVersion.split(".")[1],l=n.npmVersion.split(".")[1];d!==l&&(console.log(a.yellow(`
26
+ \u26A0\uFE0F Version mismatch: Core ${n.coreVersion} / CLI ${n.npmVersion}`)),console.log(a.gray(" Consider updating to matching versions for best compatibility")));}n.projects.length>0?(console.log(a.bold(`
27
+ \u{1F4E6} Projects (${n.projects.length}):`)),n.projects.forEach(d=>Re(d))):(console.log(a.bold(`
28
+ \u{1F4E6} Projects:`)),console.log(a.gray(" No RapidKit projects found in workspace")));let c=n.projects.reduce((d,l)=>d+l.issues.length,0),u=O(n.projects),p=[n.python,n.rapidkitCore].some(d=>d.status==="error");if(p||c>0||u>0){let d=u>0?` and ${u} advisory warning project(s)`:"";if(console.log(a.bold.yellow(`
29
+ \u26A0\uFE0F Found ${c} project issue(s)${d}`)),p&&console.log(a.bold.red("\u274C System requirements not met")),e.fix){if(await ee(n.projects,true),!e.json){let l=await Y(r,false),m=l.projects.reduce((w,x)=>w+x.issues.length,0),f=[l.python,l.rapidkitCore].some(w=>w.status==="error");f||m>0?(console.log(a.bold.yellow(`
30
+ \u26A0\uFE0F Post-fix verification found ${m} remaining issue(s)`)),f&&console.log(a.bold.red("\u274C System requirements still not met"))):console.log(a.bold.green(`
31
+ \u2705 Post-fix verification passed. Workspace is healthy.`)),l.projectScanCached&&console.log(a.gray(`\u2139\uFE0F Reused cached project scan${l.projectScanCachePath?` (${o.basename(l.projectScanCachePath)})`:""}`)),l.evidencePath&&console.log(a.gray(`\u2139\uFE0F Evidence refreshed: ${l.evidencePath}`));}}else c>0&&await ee(n.projects,false);}else console.log(a.bold.green(`
32
+ \u2705 All checks passed! Workspace is healthy.`));}else {console.log(a.bold(`System Tools:
33
+ `));let r=await se(),n=r.python,c=r.poetry,u=r.pipx,p=r.go,d=r.rapidkitCore;S(n,"Python"),S(c,"Poetry"),S(u,"pipx"),S(p,"Go"),S(d,"RapidKit Core"),[n,d].some(m=>m.status==="error")?(console.log(a.bold.red(`
34
+ \u274C Some required tools are missing`)),e.fix&&console.log(a.gray(`
35
+ Tip: Project auto-fix runs in workspace mode. Run from a workspace and use "rapidkit doctor workspace --fix"`)),console.log(a.gray(`
36
+ Tip: Run "rapidkit doctor workspace" for detailed project checks`))):(console.log(a.bold.green(`
37
+ \u2705 All required tools are installed!`)),e.fix&&console.log(a.gray(`
38
+ Tip: Project auto-fix runs in workspace mode. Run from a workspace and use "rapidkit doctor workspace --fix"`)),console.log(a.gray(`
39
+ Tip: Run "rapidkit doctor workspace" for detailed project checks`)));}console.log("");}export{Je as runDoctor};
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  declare function handleCreateOrFallback(args: string[]): Promise<number>;
3
- declare const NPM_ONLY_TOP_LEVEL_COMMANDS: readonly ["doctor", "workspace", "bootstrap", "setup", "cache", "mirror", "ai", "config", "shell"];
3
+ declare const NPM_ONLY_TOP_LEVEL_COMMANDS: readonly ["readiness", "doctor", "workspace", "bootstrap", "setup", "cache", "mirror", "ai", "config", "shell"];
4
4
  declare const WRAPPER_ORCHESTRATED_PROJECT_COMMANDS: readonly ["init"];
5
5
  interface DoctorWorkspaceShadowDiagnostic {
6
6
  detected: boolean;