@praneeth_54/agentdoctor 0.1.3-beta → 0.2.0-beta

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
@@ -9,9 +9,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ### Planned
11
11
 
12
- - Deterministic readiness scoring
13
12
  - Safe automatic fixes
14
- - Packaged GitHub Action
13
+ - Terminal readiness line and GitHub Action score-gate inputs (deferred; see scoring.md v2+)
14
+
15
+ ## [0.2.0-beta] — 2026-08-02
16
+
17
+ Minor beta: deterministic readiness scoring and CLI `--min-score` enforcement.
18
+
19
+ ### Added
20
+
21
+ - Deterministic readiness scoring (v1): `scan()` populates `scoringAvailable: true` and
22
+ `scores` (`overall`, `categories`, `agents`) from post-dedupe findings
23
+ ([docs/scoring.md](docs/scoring.md))
24
+ - CLI `--min-score N` enforcement: exit code `1` when `scores.overall < N`
25
+ - `--ci` without `--min-score` remains report-only (exit `0` on successful scan)
26
+ - Scoring specification and compatibility / exit-code docs updated for shipped behavior
27
+
28
+ ### Compatibility
29
+
30
+ - No new JSON top-level fields (`scoringModel` / `scoreExplanation` deferred)
31
+ - Findings, rule IDs, and agent detection unchanged
32
+ - GitHub Action remains `--ci --json` report-only (no score-gate inputs)
33
+ - Default Action `version` input is `0.2.0-beta`
34
+
35
+ ## [0.1.4-beta] — 2026-08-02
36
+
37
+ Backward-compatible distribution release: first-class GitHub Action packaging. CLI and scanner behavior are unchanged from 0.1.3-beta.
38
+
39
+ ### Added
40
+
41
+ - Composite GitHub Action (`action.yml`) that installs the published `@praneeth_54/agentdoctor` package and emits a workspace-contained JSON report
42
+ - CI `action-smoke` matrix covering normal/nested output paths and rejection of traversal, parent-symlink escape, final-file symlink, and directory output targets
43
+ - README GitHub Action usage section and ROADMAP update for CI packaging
44
+
45
+ ### Compatibility
46
+
47
+ - No scanner, rule, or JSON finding-schema changes
48
+ - Scoring remains unavailable (`scoringAvailable: false`)
49
+ - `--min-score` remains accepted but ignored until scoring ships
50
+ - Default Action `version` input is `0.1.4-beta` (exact npm version or `latest` / `beta` dist-tags)
15
51
 
16
52
  ## [0.1.3-beta] — 2026-07-29
17
53
 
@@ -107,7 +143,9 @@ First public beta.
107
143
  - Not a complete secret scanner
108
144
  - Git “tracked secret” detection deferred
109
145
 
110
- [Unreleased]: https://github.com/pranee54/AgentDoctor/compare/v0.1.3-beta...HEAD
146
+ [Unreleased]: https://github.com/pranee54/AgentDoctor/compare/v0.2.0-beta...HEAD
147
+ [0.2.0-beta]: https://github.com/pranee54/AgentDoctor/releases/tag/v0.2.0-beta
148
+ [0.1.4-beta]: https://github.com/pranee54/AgentDoctor/releases/tag/v0.1.4-beta
111
149
  [0.1.3-beta]: https://github.com/pranee54/AgentDoctor/releases/tag/v0.1.3-beta
112
150
  [0.1.2-beta]: https://github.com/pranee54/AgentDoctor/releases/tag/v0.1.2-beta
113
151
  [0.1.1-beta]: https://github.com/pranee54/AgentDoctor/releases/tag/v0.1.1-beta
package/README.md CHANGED
@@ -1,41 +1,43 @@
1
1
  # AgentDoctor
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/@praneeth_54/agentdoctor)](https://www.npmjs.com/package/@praneeth_54/agentdoctor)
4
- [![License](https://img.shields.io/github/license/pranee54/AgentDoctor)](LICENSE)
5
- [![GitHub Stars](https://img.shields.io/github/stars/pranee54/AgentDoctor)](https://github.com/pranee54/AgentDoctor/stargazers)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@praneeth_54/agentdoctor)](https://www.npmjs.com/package/@praneeth_54/agentdoctor)
6
5
  [![CI](https://img.shields.io/github/actions/workflow/status/pranee54/AgentDoctor/ci.yml?branch=main&label=CI)](https://github.com/pranee54/AgentDoctor/actions)
7
6
  [![Node](https://img.shields.io/node/v/@praneeth_54/agentdoctor)](https://nodejs.org)
8
- [![Release](https://img.shields.io/badge/release-v0.1.2--beta-orange)](CHANGELOG.md)
7
+ [![License](https://img.shields.io/github/license/pranee54/AgentDoctor)](LICENSE)
9
8
 
10
9
  **Lighthouse for AI coding agents.**
11
10
 
12
- AgentDoctor audits a repository’s AI coding agent configuration — instructions, ignore rules, permissions, and MCP setup — using local static analysis. No API key. No upload by default.
11
+ Audit coding-agent configuration before it becomes a repository problem.
12
+
13
+ AgentDoctor is a local CLI that inspects project-level AI coding agent setup — Cursor, Claude Code, and Codex — for security, instructions, context, and MCP configuration. Deterministic static analysis. No API key. No code upload by default.
13
14
 
14
15
  ```bash
15
16
  npx @praneeth_54/agentdoctor
16
17
  ```
17
18
 
18
- | | |
19
- | -------------- | ----------------------------------------------------------------------------------- |
20
- | **What it is** | A CLI health check for agent config in your repo |
21
- | **Why use it** | Catch misconfigurations, sensitive context exposure, and instruction problems early |
22
- | **Install** | `npx @praneeth_54/agentdoctor` or `npm install -g @praneeth_54/agentdoctor` |
23
- | **Requires** | Node.js 20+ |
19
+ Public beta (`0.1.x-beta`). Deterministic readiness scores ship in JSON; automatic fixes are not available yet.
24
20
 
25
21
  ---
26
22
 
27
- ## Demo
23
+ ## What you get
24
+
25
+ ![AgentDoctor scanning a repository and reporting coding-agent security findings](docs/images/cli-scan.png)
26
+
27
+ _Real scan of the included `insecure-agent-project` fixture using AgentDoctor v0.2.0-beta._
28
28
 
29
29
  ```text
30
30
  $ npx @praneeth_54/agentdoctor
31
31
 
32
- AgentDoctor v0.1.3-beta
32
+ 🩺 AgentDoctor v0.2.0-beta
33
+
34
+ Scanning repository...
33
35
 
34
36
  Repository
35
- Framework: Next.js
36
- Language: TypeScript
37
+ Framework: Node.js
38
+ Language: JavaScript
37
39
  Package manager: npm
38
- Files scanned: 46
40
+ Files scanned: 7
39
41
 
40
42
  AI Coding Agents
41
43
 
@@ -48,59 +50,134 @@ Findings
48
50
  CRITICAL
49
51
 
50
52
  ✗ Sensitive environment file may enter agent context
51
- .env.production
53
+ .env
52
54
  Affected: Claude Code, Codex
53
- Fix: Exclude the file from agent context and keep it out of version control.
55
+ Fix: Add an agent-specific exclusion (for example .cursorignore or a
56
+ Claude Code Read deny rule), keep the file out of version control,
57
+ and rotate any credentials that may have been exposed.
58
+
59
+ ✗ Private key or credential file present in repository
60
+ test-private-key.pem
61
+ Affected: Claude Code, Codex, Cursor
54
62
 
55
63
  WARNING
56
64
 
57
- ! Large instruction file
58
- CLAUDE.md — 38 KB
65
+ ! Claude Code bypassPermissions mode enabled
66
+ .claude/settings.json
59
67
 
60
68
  Summary
61
69
 
62
- 1 critical
70
+ 3 critical
63
71
  1 warning
64
72
  0 info
65
73
 
66
- Scoring is not included in this beta
74
+ Scoring: not included in this release
67
75
  ```
68
76
 
77
+ Abbreviated text example from the same fixture for accessibility and search. Secret values are never printed.
78
+
69
79
  ---
70
80
 
71
- ## Why AgentDoctor exists
81
+ ## Why AgentDoctor?
82
+
83
+ Repositories accumulate agent configuration quickly:
84
+
85
+ - Multiple instruction formats (`.cursor/rules`, `CLAUDE.md`, `AGENTS.md`)
86
+ - Stale path references in always-on instructions
87
+ - Ignore differences between `.gitignore`, `.cursorignore`, and agent defaults
88
+ - MCP filesystem scopes that are broader than intended
89
+ - Generated directories and large logs that waste context
90
+ - Credential-like files that may be readable by agents
91
+ - Conflicting assumptions about what each agent can see
72
92
 
73
- Teams adopt AI coding agents quickly and accumulate project instructions, ignore rules, MCP servers, and permission settings. Those files are easy to misconfigure and hard to review consistently.
93
+ Manually reviewing all of that across Cursor, Claude Code, and Codex is slow and inconsistent. AgentDoctor provides one deterministic local audit with stable rule IDs, evidence paths, and affected-agent information.
74
94
 
75
- | Tooling analogy | Domain |
95
+ | Analogy | Domain |
76
96
  | --------------- | -------------------------------- |
77
97
  | Lighthouse | Web pages |
78
98
  | `npm audit` | Dependencies |
79
99
  | ESLint | Source code |
80
100
  | **AgentDoctor** | **AI coding agent environments** |
81
101
 
82
- AgentDoctor analyzes configuration files. It does not run agents or edit your project.
102
+ AgentDoctor analyzes configuration. It does not run agents, call an LLM, or modify your repository in this release.
103
+
104
+ ---
105
+
106
+ ## Before / after
107
+
108
+ **Before**
109
+
110
+ A repository may contain:
111
+
112
+ ```text
113
+ .cursor/rules/
114
+ AGENTS.md
115
+ CLAUDE.md
116
+ .claude/settings.json
117
+ .mcp.json
118
+ .env
119
+ ```
120
+
121
+ Potential problems stay invisible until something leaks into model context, CI, or a teammate’s agent session:
122
+
123
+ - environment or credential-like files reachable by agents
124
+ - stale instruction path references
125
+ - broad MCP filesystem access
126
+ - oversized always-on context
127
+
128
+ **Run**
129
+
130
+ ```bash
131
+ npx @praneeth_54/agentdoctor
132
+ ```
133
+
134
+ **After**
135
+
136
+ You get deterministic findings with:
137
+
138
+ - stable rule IDs (for example `security/env-file-exposure`)
139
+ - evidence paths
140
+ - affected agents when exposure claims are supported
141
+ - conservative recommendations
142
+
143
+ Automatic repair is **not** included in this beta. Findings tell you what to review; you decide what to change.
83
144
 
84
145
  ---
85
146
 
86
- ## Installation
147
+ ## Quick start
87
148
 
88
- ### One-shot
149
+ ### One-shot (recommended)
89
150
 
90
151
  ```bash
91
- npx @praneeth_54/agentdoctor@0.1.3-beta
152
+ npx @praneeth_54/agentdoctor
153
+ ```
154
+
155
+ Pin a beta version when you need a fixed install:
156
+
157
+ ```bash
158
+ npx @praneeth_54/agentdoctor@0.2.0-beta
92
159
  ```
93
160
 
94
161
  ### Global (optional)
95
162
 
96
163
  ```bash
97
- npm install -g @praneeth_54/agentdoctor@0.1.3-beta
164
+ npm install -g @praneeth_54/agentdoctor
98
165
  agentdoctor
99
166
  ```
100
167
 
101
- The published package name is `@praneeth_54/agentdoctor` (npm blocks the unscoped name `agentdoctor` as too similar to an existing package). The CLI binary remains `agentdoctor`.
168
+ ### Common commands
169
+
170
+ ```bash
171
+ agentdoctor .
172
+ agentdoctor . --json
173
+ agentdoctor . --verbose
174
+ agentdoctor explain security/env-file-exposure
175
+ agentdoctor doctor
176
+ ```
177
+
178
+ Package name: `@praneeth_54/agentdoctor` (npm blocks the unscoped name). CLI binary: `agentdoctor`. Requires **Node.js 20+**.
102
179
 
103
- ### Library
180
+ ### Programmatic API
104
181
 
105
182
  ```bash
106
183
  npm install @praneeth_54/agentdoctor
@@ -111,218 +188,164 @@ import { scan } from "@praneeth_54/agentdoctor";
111
188
 
112
189
  const result = await scan({ cwd: process.cwd() });
113
190
  console.log(result.summary);
191
+ console.log(result.agentSecurityAnalysis); // "full" | "limited"
114
192
  ```
115
193
 
116
194
  ---
117
195
 
118
- ## Quick start
196
+ ## Supported agents
119
197
 
120
- ```bash
121
- # Scan the current directory
122
- npx @praneeth_54/agentdoctor
198
+ Project-level configuration only (repository files). Global user settings are not scanned.
123
199
 
124
- # Scan a path
125
- npx @praneeth_54/agentdoctor ./my-app
200
+ | Agent | What AgentDoctor inspects |
201
+ | --------------- | ---------------------------------------------------------------------- |
202
+ | **Cursor** | `.cursor/rules/*.mdc`, `.cursorignore`, Cursor MCP config, `AGENTS.md` |
203
+ | **Claude Code** | `CLAUDE.md`, `.claude/settings*.json`, `.claude/rules`, MCP config |
204
+ | **Codex** | `AGENTS.md` / overrides, project `.codex/` configuration |
126
205
 
127
- # Machine-readable output
128
- npx @praneeth_54/agentdoctor --json
206
+ Additional adapters are planned — see [ROADMAP.md](ROADMAP.md).
129
207
 
130
- # Extra detail (paths, timing, finding rationale)
131
- npx @praneeth_54/agentdoctor --verbose
208
+ ---
132
209
 
133
- # Explain a rule
134
- npx @praneeth_54/agentdoctor explain security/env-file-exposure
210
+ ## Finding categories
135
211
 
136
- # Environment health check
137
- npx @praneeth_54/agentdoctor doctor
138
- ```
212
+ | Category | Examples |
213
+ | ---------------- | --------------------------------------------------------------------- |
214
+ | **Security** | Env-file exposure, private-key filenames, broad MCP filesystem scopes |
215
+ | **Context** | Large instruction files, large logs, unignored generated directories |
216
+ | **Instructions** | Empty instructions, duplicate content, missing path references |
217
+ | **MCP** | Malformed MCP config, high-risk filesystem path arguments |
139
218
 
140
- ---
219
+ Full catalog with severities and fixability: [docs/rules.md](docs/rules.md).
141
220
 
142
- ## Features
143
-
144
- | Capability | Status |
145
- | ------------------------------------------------------- | ------- |
146
- | Zero-config first run | ✓ |
147
- | Works offline / no API key | ✓ |
148
- | Detects project-level agent configuration | ✓ |
149
- | Deterministic security / context / instruction findings | ✓ |
150
- | Inspects supported MCP project configuration | ✓ |
151
- | Stable JSON output for CI | ✓ |
152
- | `explain <rule>` documentation | ✓ |
153
- | Readiness scoring | Planned |
154
- | Safe automatic fixes | Planned |
155
- | Official GitHub Action package | Planned |
156
-
157
- ### Feature comparison
158
-
159
- | Concern | Manual review | Generic linters | AgentDoctor |
160
- | -------------------------------------------- | ------------- | --------------- | ---------------- |
161
- | Agent instruction files present and usable | Manual | — | ✓ |
162
- | Empty or duplicated instructions | Manual | — | ✓ |
163
- | Sensitive filenames vs agent access patterns | Manual | Partial | ✓ (conservative) |
164
- | Broad MCP filesystem scopes | Manual | — | ✓ |
165
- | Large always-on instruction files | Manual | — | ✓ |
166
- | Uploads repository by default | — | Sometimes | **Never** |
221
+ Explain any rule:
167
222
 
168
- ---
223
+ ```bash
224
+ npx @praneeth_54/agentdoctor explain security/env-file-exposure
225
+ ```
169
226
 
170
- ## What it detects
227
+ ---
171
228
 
172
- ### Supported agents
229
+ ## Privacy and trust
173
230
 
174
- | Agent | Project-level detection |
175
- | ----------- | ------------------------------------------ |
176
- | Cursor | Rules, ignore files, MCP, `AGENTS.md` |
177
- | Claude Code | Instructions, settings, rules, MCP |
178
- | Codex | `AGENTS.md` / overrides, project `.codex/` |
231
+ **Scans run locally on your machine.**
179
232
 
180
- ### Finding categories
233
+ AgentDoctor:
181
234
 
182
- Security, context efficiency, instruction quality, and MCP configuration. Full catalog: [docs/rules.md](docs/rules.md).
235
+ - does not require an API key
236
+ - does not upload repository contents by default
237
+ - does not call an LLM for core scanning
238
+ - does not execute MCP servers
239
+ - does not execute project code
240
+ - never prints secret values from files it flags by name
241
+ - enforces repository boundary checks for path references and symlink escape
183
242
 
184
- Adapters are pluggable — additional agents can be registered without rewriting the scanner.
243
+ This is still software that reads untrusted repository trees. Treat findings as guidance, not a security certification. AgentDoctor is **not** a complete secret-content scanner.
185
244
 
186
245
  ---
187
246
 
188
- ## Architecture
247
+ ## CI usage
189
248
 
190
- ```text
191
- ┌─────────────┐
192
- │ Discovery │ bounded filesystem walk
193
- └──────┬──────┘
194
- ▼
195
- ┌─────────────────┐
196
- │ Project detect │ language / framework / package manager
197
- └──────┬──────────┘
198
- ▼
199
- ┌─────────────────┐
200
- │ Agent adapters │ Cursor · Claude Code · Codex
201
- └──────┬──────────┘
202
- ▼
203
- ┌─────────────────┐
204
- │ Rule engine │ security · context · instructions · MCP
205
- └──────┬──────────┘
206
- ▼
207
- ┌─────────────────┐
208
- │ Findings │ deterministic IDs · deduped · fixability metadata
209
- └──────┬──────────┘
210
- ▼
211
- ┌─────────────────┐
212
- │ Reporters │ terminal · JSON
213
- └─────────────────┘
214
- ```
249
+ ### GitHub Action
215
250
 
216
- Details: [docs/architecture.md](docs/architecture.md)
251
+ Run AgentDoctor directly in a workflow:
217
252
 
218
- ---
253
+ ```yaml
254
+ permissions:
255
+ contents: read
219
256
 
220
- ## JSON output
257
+ steps:
258
+ - uses: actions/checkout@v4
221
259
 
222
- ```bash
223
- npx @praneeth_54/agentdoctor --json
224
- ```
260
+ - name: Audit coding-agent configuration
261
+ id: agentdoctor
262
+ uses: pranee54/AgentDoctor@v0.2.0-beta
263
+ with:
264
+ path: .
265
+ output-file: agentdoctor-report.json
225
266
 
226
- ```json
227
- {
228
- "version": "0.1.3-beta",
229
- "repository": {
230
- "primaryFramework": "nextjs",
231
- "primaryLanguage": "typescript",
232
- "filesScanned": 46
233
- },
234
- "agents": [
235
- {
236
- "id": "cursor",
237
- "detected": true,
238
- "configured": true,
239
- "status": "configured"
240
- }
241
- ],
242
- "findings": [
243
- {
244
- "id": "security/env-file-exposure:.env.production",
245
- "ruleId": "security/env-file-exposure",
246
- "category": "security",
247
- "severity": "critical",
248
- "title": "Sensitive environment file may enter agent context",
249
- "affectedAgents": ["claude-code", "codex"],
250
- "fixability": "review"
251
- }
252
- ],
253
- "summary": { "critical": 1, "warning": 0, "info": 0, "total": 1 },
254
- "scoringAvailable": false,
255
- "scores": null
256
- }
267
+ - name: Upload AgentDoctor report
268
+ uses: actions/upload-artifact@v4
269
+ with:
270
+ name: agentdoctor-report
271
+ path: ${{ steps.agentdoctor.outputs.report-path }}
257
272
  ```
258
273
 
259
- Exit codes: [docs/exit-codes.md](docs/exit-codes.md)
274
+ The action installs the published `@praneeth_54/agentdoctor@0.2.0-beta` package, runs it with
275
+ `--ci --json`, and writes the report inside the checked-out workspace. It sets up Node.js 20
276
+ for the CLI. The optional `version` input accepts an exact npm version or the `latest` / `beta`
277
+ dist-tag.
260
278
 
261
- ---
279
+ ### CLI
262
280
 
263
- ## Privacy
281
+ Use JSON directly in other CI systems:
264
282
 
265
- **Your code stays on your machine.**
283
+ ```bash
284
+ # Report-only (exit 0 even when findings exist; scores still in JSON)
285
+ npx @praneeth_54/agentdoctor --ci --json
266
286
 
267
- Normal scans do not:
287
+ # Fail CI when overall readiness is below 70
288
+ npx @praneeth_54/agentdoctor --ci --json --min-score 70
289
+ ```
268
290
 
269
- - send source code to external services
270
- - require authentication
271
- - call an LLM
272
- - execute project code
273
- - start MCP servers
274
- - enable telemetry by default
291
+ `--ci` runs non-interactively and does **not** apply an implicit score threshold.
292
+ Use `--min-score N` (with or without `--ci`) to fail with exit code `1` when
293
+ `scores.overall < N`.
275
294
 
276
- If anonymous telemetry is ever introduced, it will be opt-in.
295
+ Exit codes: [docs/exit-codes.md](docs/exit-codes.md). Compatibility promises: [docs/compatibility.md](docs/compatibility.md).
277
296
 
278
- ---
297
+ ### Readiness scoring
279
298
 
280
- ## FAQ
299
+ Scans populate `scoringAvailable: true` and a deterministic `scores` object
300
+ (overall, categories, agents). The terminal report does not render a readiness line yet;
301
+ scores are available in JSON (`--json`).
281
302
 
282
- **Does AgentDoctor require an API key?**
283
- No. Core scanning is local and deterministic.
303
+ `--min-score N` is enforced by the CLI. Details (weights, security caps, threshold rules,
304
+ and deferred v2 items): [docs/scoring.md](docs/scoring.md).
284
305
 
285
- **Is this a secret scanner?**
286
- No. It uses conservative filename and configuration heuristics. It never prints secret values and does not claim complete coverage.
306
+ ---
287
307
 
288
- **Will it modify my repository?**
289
- Not in this release. `agentdoctor fix` is reserved for a future safe-fix mode.
308
+ ## Beta limitations
290
309
 
291
- **Can I use it in CI?**
292
- Yes — prefer `--json`. `--min-score` is ignored until readiness scoring ships.
310
+ Honest limits of the current public beta:
293
311
 
294
- **How do I understand a finding?**
312
+ | Limitation | Status |
313
+ | ----------------------------------- | --------------------------------------------------------------- |
314
+ | Terminal readiness line | Scores ship in JSON only; terminal does not print N/100 yet |
315
+ | GitHub Action score gates | Action remains `--ci --json` report-only (no `min-score` input) |
316
+ | Automatic fixes (`agentdoctor fix`) | Stub only — does not modify files |
317
+ | Secret-content scanning | Filename / config heuristics only |
318
+ | Detection style | Intentionally conservative; false security findings are avoided |
319
+ | Agent coverage | Cursor, Claude Code, Codex project configs |
295
320
 
296
- ```bash
297
- npx @praneeth_54/agentdoctor explain <rule-id>
298
- ```
321
+ See [CHANGELOG.md](CHANGELOG.md) and [docs/release-notes-v0.2.0-beta.md](docs/release-notes-v0.2.0-beta.md).
299
322
 
300
323
  ---
301
324
 
302
- ## Documentation
325
+ ## Architecture
303
326
 
304
- Start at [docs/README.md](docs/README.md).
327
+ ```text
328
+ Discovery → Project detect → Agent adapters → Rule engine → Findings → Scores → Terminal / JSON
329
+ ```
305
330
 
306
- | Doc | Contents |
307
- | ---------------------------------------------- | --------------------------- |
308
- | [docs/architecture.md](docs/architecture.md) | Pipeline and package layout |
309
- | [docs/rules.md](docs/rules.md) | Stable rule IDs |
310
- | [docs/exit-codes.md](docs/exit-codes.md) | Process exit codes |
311
- | [docs/compatibility.md](docs/compatibility.md) | Beta compatibility promises |
312
- | [docs/development.md](docs/development.md) | Local development |
313
- | [ROADMAP.md](ROADMAP.md) | Near- and medium-term plans |
314
- | [CHANGELOG.md](CHANGELOG.md) | Release history |
331
+ Details: [docs/architecture.md](docs/architecture.md)
315
332
 
316
333
  ---
317
334
 
318
- ## Roadmap
319
-
320
- See [ROADMAP.md](ROADMAP.md). Highlights:
335
+ ## Documentation
321
336
 
322
- 1. Deterministic readiness scoring
323
- 2. Conservative auto-fix for safe findings
324
- 3. Packaged GitHub Action
325
- 4. Additional agent adapters
337
+ | Doc | Contents |
338
+ | ------------------------------------------------------------------ | ------------------------------- |
339
+ | [docs/README.md](docs/README.md) | Documentation index |
340
+ | [docs/architecture.md](docs/architecture.md) | Scan pipeline |
341
+ | [docs/rules.md](docs/rules.md) | Stable rule IDs |
342
+ | [docs/exit-codes.md](docs/exit-codes.md) | Process exit codes |
343
+ | [docs/scoring.md](docs/scoring.md) | Readiness scoring specification |
344
+ | [docs/compatibility.md](docs/compatibility.md) | Beta compatibility promises |
345
+ | [docs/development.md](docs/development.md) | Local development |
346
+ | [docs/github-launch-checklist.md](docs/github-launch-checklist.md) | GitHub About / topics / launch |
347
+ | [ROADMAP.md](ROADMAP.md) | Near- and medium-term plans |
348
+ | [CHANGELOG.md](CHANGELOG.md) | Release history |
326
349
 
327
350
  ---
328
351
 
@@ -331,19 +354,29 @@ See [ROADMAP.md](ROADMAP.md). Highlights:
331
354
  Issues and pull requests are welcome.
332
355
 
333
356
  1. Read [CONTRIBUTING.md](CONTRIBUTING.md) and the [Code of Conduct](CODE_OF_CONDUCT.md)
334
- 2. Set up locally with [docs/development.md](docs/development.md)
335
- 3. Report security issues via [SECURITY.md](SECURITY.md)
357
+ 2. Prefer [good first issues](docs/good-first-issues.md) ideas
358
+ 3. Report security issues via [SECURITY.md](SECURITY.md) — never paste real secrets into issues
336
359
 
337
360
  ```bash
338
361
  git clone https://github.com/pranee54/AgentDoctor.git
339
362
  cd AgentDoctor
340
363
  npm install
341
- npm run typecheck && npm run lint && npm test && npm run build
364
+ npm run verify
342
365
  node dist/cli/index.js ./fixtures/clean-configured-project
343
366
  ```
344
367
 
345
368
  ---
346
369
 
370
+ ## Next steps
371
+
372
+ - **Try it:** `npx @praneeth_54/agentdoctor`
373
+ - **Report a false positive / false negative:** use the issue templates (include version, rule ID, anonymized evidence — no secrets)
374
+ - **Propose a rule or adapter:** [feature request](.github/ISSUE_TEMPLATE/feature_request.md) / [rule proposal](.github/ISSUE_TEMPLATE/rule_proposal.md)
375
+ - **Contribute:** [CONTRIBUTING.md](CONTRIBUTING.md)
376
+ - **Useful?** Star or watch the repository so you see updates
377
+
378
+ ---
379
+
347
380
  ## License
348
381
 
349
382
  [MIT](LICENSE) © AgentDoctor Contributors
@@ -15,7 +15,7 @@ export async function runDoctorCommand() {
15
15
  lines.push(` ${symbolOk()} Core scan API available`);
16
16
  lines.push("");
17
17
  lines.push(colors.dim("Environment looks ready."));
18
- lines.push(colors.dim("Readiness scoring and automatic fixes are not available yet."));
18
+ lines.push(colors.dim("Automatic fixes are not available yet."));
19
19
  lines.push("");
20
20
  process.stdout.write(lines.join("\n"));
21
21
  return EXIT_CODES.SUCCESS;
@@ -24,20 +24,12 @@ export async function runScanCommand(options) {
24
24
  verbose: options.verbose === true,
25
25
  }));
26
26
  }
27
- if (options.ci || options.minScore !== undefined) {
28
- if (!result.scoringAvailable || result.scores === null) {
27
+ if (options.minScore !== undefined && result.scores !== null) {
28
+ if (result.scores.overall < options.minScore) {
29
29
  if (!options.json) {
30
- console.error("Note: readiness scoring is not available in this release; --min-score was ignored.");
31
- }
32
- }
33
- else {
34
- const threshold = options.minScore ?? 0;
35
- if (result.scores.overall < threshold) {
36
- if (!options.json) {
37
- console.error(`\nCI check failed: overall score ${result.scores.overall} is below --min-score ${threshold}`);
38
- }
39
- return EXIT_CODES.ISSUES_OR_THRESHOLD;
30
+ console.error(`\nCI check failed: overall score ${result.scores.overall} is below --min-score ${options.minScore}`);
40
31
  }
32
+ return EXIT_CODES.ISSUES_OR_THRESHOLD;
41
33
  }
42
34
  }
43
35
  return EXIT_CODES.SUCCESS;
@@ -29,9 +29,9 @@ export function createProgram() {
29
29
  .version(PACKAGE_VERSION, "-V, --version", "Print AgentDoctor version")
30
30
  .argument("[path]", "Repository path to scan (default: current directory)")
31
31
  .option("--json", "Emit machine-readable JSON (no decorative output)", false)
32
- .option("--ci", "CI mode (non-interactive; --min-score is ignored until scoring ships)", false)
32
+ .option("--ci", "CI mode (non-interactive; report-only unless --min-score is set)", false)
33
33
  .option("--verbose", "Show timing and extra diagnostics", false)
34
- .option("--min-score <number>", "Fail when overall score is below this (no-op until scoring ships)", parseMinScore)
34
+ .option("--min-score <number>", "Exit 1 when overall readiness score is below this (0-100)", parseMinScore)
35
35
  .action(async (pathArg, options) => {
36
36
  const minScore = readMinScore(options);
37
37
  const code = await runScanCommand({
@@ -48,9 +48,9 @@ export function createProgram() {
48
48
  .description("Scan a repository for AI coding agent configuration issues (default command)")
49
49
  .argument("[path]", "Repository path to scan")
50
50
  .option("--json", "Emit machine-readable JSON", false)
51
- .option("--ci", "CI mode (--min-score ignored until scoring ships)", false)
51
+ .option("--ci", "CI mode (non-interactive; report-only unless --min-score is set)", false)
52
52
  .option("--verbose", "Show timing and extra diagnostics", false)
53
- .option("--min-score <number>", "Fail when overall score is below this (no-op until scoring ships)", parseMinScore)
53
+ .option("--min-score <number>", "Exit 1 when overall readiness score is below this (0-100)", parseMinScore)
54
54
  .action(async (pathArg, options) => {
55
55
  const minScore = readMinScore(options);
56
56
  const code = await runScanCommand({
@@ -1,4 +1,4 @@
1
- export declare const PACKAGE_VERSION = "0.1.3-beta";
1
+ export declare const PACKAGE_VERSION = "0.2.0-beta";
2
2
  export declare const DEFAULT_MAX_FILE_SIZE_BYTES: number;
3
3
  /** Directories skipped during normal discovery (unless a rule needs them later). */
4
4
  export declare const DEFAULT_IGNORE_DIRECTORIES: Set<string>;
package/dist/constants.js CHANGED
@@ -1,4 +1,4 @@
1
- export const PACKAGE_VERSION = "0.1.3-beta";
1
+ export const PACKAGE_VERSION = "0.2.0-beta";
2
2
  export const DEFAULT_MAX_FILE_SIZE_BYTES = 2 * 1024 * 1024; // 2 MiB
3
3
  /** Directories skipped during normal discovery (unless a rule needs them later). */
4
4
  export const DEFAULT_IGNORE_DIRECTORIES = new Set([
@@ -1,7 +1,6 @@
1
1
  import type { ScanOptions, ScanResult } from "../../types/index.js";
2
2
  /**
3
3
  * Public scan entry point.
4
- * Pipeline: discovery → project detection → agent adapters → rule engine → findings.
5
- * Readiness scoring is reserved for a later release (`scores` remains null for now).
4
+ * Pipeline: discovery → project detection → agent adapters → rule engine → findings → scores.
6
5
  */
7
6
  export declare function scan(options?: ScanOptions): Promise<ScanResult>;
@@ -4,10 +4,10 @@ import { detectProject } from "../../detectors/project.js";
4
4
  import { sanitizeTerminalText } from "../../security/redaction.js";
5
5
  import { buildRuleContext } from "../rules/build-context.js";
6
6
  import { runRules } from "../rules/run-rules.js";
7
+ import { computeReadinessScores } from "../scoring/compute-scores.js";
7
8
  /**
8
9
  * Public scan entry point.
9
- * Pipeline: discovery → project detection → agent adapters → rule engine → findings.
10
- * Readiness scoring is reserved for a later release (`scores` remains null for now).
10
+ * Pipeline: discovery → project detection → agent adapters → rule engine → findings → scores.
11
11
  */
12
12
  export async function scan(options = {}) {
13
13
  const totalStarted = performance.now();
@@ -51,21 +51,24 @@ export async function scan(options = {}) {
51
51
  if (agentSecurityAnalysis === "limited") {
52
52
  warnings.push("No supported coding-agent configuration detected; agent-specific security exposure checks are limited.");
53
53
  }
54
+ const scoringStarted = performance.now();
55
+ const scores = computeReadinessScores(findings);
56
+ const scoringMs = Math.round(performance.now() - scoringStarted);
54
57
  return {
55
58
  version: PACKAGE_VERSION,
56
59
  repository,
57
60
  agents,
58
61
  findings,
59
62
  summary,
60
- scores: null,
61
- scoringAvailable: false,
63
+ scores,
64
+ scoringAvailable: true,
62
65
  agentSecurityAnalysis,
63
66
  timing: {
64
67
  discoveryMs: discovery.elapsedMs,
65
68
  detectionMs,
66
69
  agentsMs,
67
70
  rulesMs,
68
- scoringMs: 0,
71
+ scoringMs,
69
72
  totalMs: Math.round(performance.now() - totalStarted),
70
73
  },
71
74
  diagnostics: {
@@ -0,0 +1,6 @@
1
+ import type { Finding, Scores } from "../../types/index.js";
2
+ /**
3
+ * v1 readiness scores from post-dedupe findings.
4
+ * Spec: docs/scoring.md
5
+ */
6
+ export declare function computeReadinessScores(findings: readonly Finding[]): Scores;
@@ -0,0 +1,90 @@
1
+ const SEVERITY_BASE = {
2
+ critical: 35,
3
+ warning: 10,
4
+ info: 2,
5
+ };
6
+ const SEVERITY_SORT_RANK = {
7
+ critical: 0,
8
+ warning: 1,
9
+ info: 2,
10
+ };
11
+ /**
12
+ * v1 readiness scores from post-dedupe findings.
13
+ * Spec: docs/scoring.md
14
+ */
15
+ export function computeReadinessScores(findings) {
16
+ const overallRaw = 100 - sumDeductions(findings);
17
+ const overall = clampScore(applySecurityCaps(overallRaw, findings));
18
+ return {
19
+ overall,
20
+ categories: {
21
+ security: scoreSubset(findings.filter((f) => f.category === "security")),
22
+ context: scoreSubset(findings.filter((f) => f.category === "context")),
23
+ instructions: scoreSubset(findings.filter((f) => f.category === "instructions")),
24
+ mcp: scoreSubset(findings.filter((f) => f.category === "mcp")),
25
+ compatibility: scoreSubset(findings.filter((f) => f.category === "compatibility")),
26
+ performance: scoreSubset(findings.filter((f) => f.category === "performance")),
27
+ },
28
+ agents: {
29
+ cursor: scoreSubset(findings.filter((f) => f.affectedAgents.includes("cursor"))),
30
+ "claude-code": scoreSubset(findings.filter((f) => f.affectedAgents.includes("claude-code"))),
31
+ codex: scoreSubset(findings.filter((f) => f.affectedAgents.includes("codex"))),
32
+ },
33
+ };
34
+ }
35
+ function scoreSubset(findings) {
36
+ return clampScore(100 - sumDeductions(findings));
37
+ }
38
+ function sumDeductions(findings) {
39
+ const sorted = sortFindings(findings);
40
+ const severityIndex = {
41
+ critical: 0,
42
+ warning: 0,
43
+ info: 0,
44
+ };
45
+ let total = 0;
46
+ for (const finding of sorted) {
47
+ const occurrence = severityIndex[finding.severity];
48
+ severityIndex[finding.severity] = occurrence + 1;
49
+ total += SEVERITY_BASE[finding.severity] * diminishingMultiplier(occurrence);
50
+ }
51
+ return total;
52
+ }
53
+ function diminishingMultiplier(zeroBasedIndex) {
54
+ if (zeroBasedIndex === 0)
55
+ return 1;
56
+ if (zeroBasedIndex === 1)
57
+ return 0.7;
58
+ if (zeroBasedIndex === 2)
59
+ return 0.5;
60
+ return 0.35;
61
+ }
62
+ function sortFindings(findings) {
63
+ return [...findings].sort((a, b) => {
64
+ const sev = SEVERITY_SORT_RANK[a.severity] - SEVERITY_SORT_RANK[b.severity];
65
+ if (sev !== 0)
66
+ return sev;
67
+ const rule = a.ruleId.localeCompare(b.ruleId);
68
+ if (rule !== 0)
69
+ return rule;
70
+ const pathA = a.evidence?.path ?? "";
71
+ const pathB = b.evidence?.path ?? "";
72
+ const pathCmp = pathA.localeCompare(pathB);
73
+ if (pathCmp !== 0)
74
+ return pathCmp;
75
+ return a.id.localeCompare(b.id);
76
+ });
77
+ }
78
+ function applySecurityCaps(overall, findings) {
79
+ const securityCriticals = findings.filter((f) => f.category === "security" && f.severity === "critical").length;
80
+ if (securityCriticals >= 2) {
81
+ return Math.min(overall, 49);
82
+ }
83
+ if (securityCriticals >= 1) {
84
+ return Math.min(overall, 69);
85
+ }
86
+ return overall;
87
+ }
88
+ function clampScore(value) {
89
+ return Math.max(0, Math.min(100, Math.round(value)));
90
+ }
@@ -1,7 +1,7 @@
1
1
  import type { Scores } from "../../types/index.js";
2
2
  /**
3
- * Internal scoring stub retained for upcoming readiness scores.
4
- * Production scans currently return `scores: null`.
5
- * A clean undetected-agent repo stays below 100 by design.
3
+ * Historical filesScanned-based stub. Kept for unit tests that document the
4
+ * pre-v1 placeholder behavior. Production scans use computeReadinessScores
5
+ * (docs/scoring.md) — do not call this from scan().
6
6
  */
7
7
  export declare function computePlaceholderScores(filesScanned: number): Scores;
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Internal scoring stub retained for upcoming readiness scores.
3
- * Production scans currently return `scores: null`.
4
- * A clean undetected-agent repo stays below 100 by design.
2
+ * Historical filesScanned-based stub. Kept for unit tests that document the
3
+ * pre-v1 placeholder behavior. Production scans use computeReadinessScores
4
+ * (docs/scoring.md) — do not call this from scan().
5
5
  */
6
6
  export function computePlaceholderScores(filesScanned) {
7
7
  const base = 72;
@@ -106,11 +106,11 @@ export interface ScanResult {
106
106
  findings: Finding[];
107
107
  summary: FindingsSummary;
108
108
  /**
109
- * Readiness scores when scoring is available.
110
- * Null while scoring is unavailable — do not treat as readiness.
109
+ * Readiness scores (v1). Always populated when `scoringAvailable` is true.
110
+ * Remains typed as nullable for older consumers / transitional tooling.
111
111
  */
112
112
  scores: Scores | null;
113
- /** False until the readiness scoring model ships. */
113
+ /** True when the readiness scoring model is active and `scores` is populated. */
114
114
  scoringAvailable: boolean;
115
115
  /**
116
116
  * `limited` when no supported coding agent is detected/configured.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praneeth_54/agentdoctor",
3
- "version": "0.1.3-beta",
3
+ "version": "0.2.0-beta",
4
4
  "description": "Audit AI coding agent configuration in a repository — local, deterministic, no API key.",
5
5
  "type": "module",
6
6
  "bin": {