pseolint 0.1.0 → 0.2.1

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
@@ -1,77 +1,257 @@
1
- # pseolint
2
-
3
- > SpamBrain-proof your pSEO before you publish.
4
-
5
- The only tool purpose-built for **programmatic SEO compliance**. Audits page *relationships*, not just pages. Detects the exact patterns Google's SpamBrain targets.
6
-
7
- ## Install
8
-
9
- ```bash
10
- npx pseolint http://localhost:3000
11
- ```
12
-
13
- Or install globally:
14
-
15
- ```bash
16
- npm install -g pseolint
17
- ```
18
-
19
- ## Usage
20
-
21
- ```bash
22
- # Audit your local dev server (recommended)
23
- npx pseolint http://localhost:3000
24
-
25
- # Audit a live site
26
- npx pseolint https://yoursite.com
27
-
28
- # Audit a build directory
29
- npx pseolint ./out --threshold 40
30
-
31
- # Save an HTML report
32
- npx pseolint http://localhost:3000 --format html --output report.html
33
- ```
34
-
35
- ## Options
36
-
37
- ```
38
- -f, --format <type> console, json, markdown, html (default: "console")
39
- -t, --threshold <n> Score threshold for CI exit code (default: 40)
40
- -o, --output <file> Write report to file
41
- --no-color Disable colored output
42
- --concurrency <n> Max parallel HTTP fetches (default: 5)
43
- --timeout <ms> Per-request timeout (default: 30000)
44
- --sample-size <n> Audit a random subset of N pages
45
- --ignore <patterns> Comma-separated glob patterns to exclude
46
- --render Render pages in a browser before auditing
47
- --browser-ws <url> CDP WebSocket endpoint for rendering
48
- --no-crawl Disable crawl-based page discovery
49
- ```
50
-
51
- ## Configuration
52
-
53
- Create `pseolint.config.ts` in your project root:
54
-
55
- ```typescript
56
- export default {
57
- rules: {
58
- nearDuplicateThreshold: 0.85,
59
- thinContentMinWords: 500,
60
- },
61
- pageGroups: {
62
- templates: {
63
- match: '/templates/**',
64
- rules: ['spam/*', 'content/*'],
65
- },
66
- },
67
- ignore: ['/api/**', '/admin/**'],
68
- };
69
- ```
70
-
71
- ## Documentation
72
-
73
- See the full documentation at [github.com/ouranos-labs/pseolint](https://github.com/ouranos-labs/pseolint).
74
-
75
- ## License
76
-
77
- MIT
1
+ # pseolint
2
+
3
+ > SpamBrain-proof your pSEO before you publish.
4
+
5
+ The only tool purpose-built for **programmatic SEO compliance**. Audits page *relationships*, not just pages. Detects the exact patterns Google's SpamBrain targets.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npx pseolint http://localhost:3000
11
+ ```
12
+
13
+ Or install globally:
14
+
15
+ ```bash
16
+ npm install -g pseolint
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```bash
22
+ # Audit your local dev server (recommended)
23
+ npx pseolint http://localhost:3000
24
+
25
+ # Audit a live site
26
+ npx pseolint https://yoursite.com
27
+
28
+ # Audit a build directory
29
+ npx pseolint ./out --threshold 40
30
+
31
+ # Save an HTML report
32
+ npx pseolint http://localhost:3000 --format html --output report.html
33
+ ```
34
+
35
+ ## Options
36
+
37
+ ```
38
+ -f, --format <type> console, json, markdown, html (default: "console")
39
+ -t, --threshold <n> Score threshold for CI exit code (default: 40)
40
+ -o, --output <file> Write report to file
41
+ --no-color Disable colored output
42
+ --concurrency <n> Max parallel HTTP fetches (default: 5)
43
+ --timeout <ms> Per-request timeout (default: 30000)
44
+ --sample-size <n> Audit a random subset of N pages
45
+ --ignore <patterns> Comma-separated glob patterns to exclude
46
+ --render Render pages in a browser before auditing
47
+ --browser-ws <url> CDP WebSocket endpoint for rendering
48
+ --no-crawl Disable crawl-based page discovery
49
+ ```
50
+
51
+ ## Configuration
52
+
53
+ Create `pseolint.config.ts` in your project root:
54
+
55
+ ```typescript
56
+ export default {
57
+ rules: {
58
+ nearDuplicateThreshold: 0.85,
59
+ thinContentMinWords: 500,
60
+ },
61
+ pageGroups: {
62
+ templates: {
63
+ match: '/templates/**',
64
+ rules: ['spam/*', 'content/*'],
65
+ },
66
+ },
67
+ ignore: ['/api/**', '/admin/**'],
68
+ };
69
+ ```
70
+
71
+ ## Caching and delta audits
72
+
73
+ ### HTTP cache
74
+
75
+ Speed up re-runs and cut egress by caching fetches:
76
+
77
+ ```bash
78
+ pseolint https://example.com --cache
79
+ pseolint https://example.com --cache --cache-ttl 30d
80
+ ```
81
+
82
+ Cached entries honor `ETag` / `Last-Modified` for 304 revalidation. When servers strip these headers, entries fall back to TTL-based freshness (default 7 days). Negative responses (4xx) are cached for 24h; 5xx are never cached. Redirects are stored as pointer entries so re-runs resolve without a network round-trip.
83
+
84
+ ### Run state + delta mode
85
+
86
+ Persist audit state across runs for CI/monitoring:
87
+
88
+ ```bash
89
+ # First run (writes baseline state)
90
+ pseolint https://example.com --state
91
+
92
+ # Subsequent run: audit only changed pages
93
+ pseolint https://example.com --state --since
94
+
95
+ # Monitoring: fail on new rule ID regressions
96
+ pseolint https://example.com --state --exit-on-regression
97
+ ```
98
+
99
+ State is stored at `.pseolint/state.json` by default. Commit it to share baseline across CI workers. On the first run (no prior state), `--since` and `--exit-on-regression` bootstrap gracefully — they audit everything and write state without erroring.
100
+
101
+ Switching between `--render` modes invalidates prior state (different renderMode produces different hashes), triggering a full re-audit.
102
+
103
+ ### Stratified sampling
104
+
105
+ When `--sample-size` is set, samples are drawn proportional to `sqrt(cluster_size)` per inferred URL template, ensuring every template is represented instead of biasing toward large clusters:
106
+
107
+ ```bash
108
+ pseolint https://example.com --sample-size 200 --strategy stratified --max-per-template 20
109
+ ```
110
+
111
+ Use `--strategy random` to fall back to uniform Fisher-Yates sampling.
112
+
113
+ ### Static site: zero egress
114
+
115
+ If your site outputs static HTML (`out/`, `dist/`, `public/`, `_site/`), audit the directory directly — no HTTP fetches at all:
116
+
117
+ ```bash
118
+ pseolint ./out
119
+ ```
120
+
121
+ ## AI triage
122
+
123
+ Turn long findings lists into ranked root causes. Opt-in; off by default.
124
+
125
+ ### Supported providers
126
+
127
+ | Provider | SDK package | Env var |
128
+ |----------|--------------------------------|------------------------------------|
129
+ | anthropic | @ai-sdk/anthropic (pre-installed) | ANTHROPIC_API_KEY |
130
+ | openai | @ai-sdk/openai | OPENAI_API_KEY |
131
+ | google | @ai-sdk/google | GOOGLE_GENERATIVE_AI_API_KEY |
132
+ | mistral | @ai-sdk/mistral | MISTRAL_API_KEY |
133
+ | groq | @ai-sdk/groq | GROQ_API_KEY |
134
+ | xai | @ai-sdk/xai | XAI_API_KEY |
135
+ | cohere | @ai-sdk/cohere | COHERE_API_KEY |
136
+ | ollama | ollama-ai-provider-v2 (pre-installed) | — (local, no key) |
137
+
138
+ Install only the providers you use: `npm install @ai-sdk/openai`.
139
+
140
+ ### Quick start
141
+
142
+ ```bash
143
+ # Auto-detect from env vars
144
+ export ANTHROPIC_API_KEY=sk-ant-...
145
+ pseolint ./out --ai
146
+
147
+ # Pick explicitly
148
+ pseolint ./out --ai --ai-provider openai --ai-model gpt-4o-mini
149
+
150
+ # Local + private
151
+ ollama serve &
152
+ pseolint ./out --ai --ai-provider ollama --ai-model llama3.1:8b
153
+ ```
154
+
155
+ ### Flags
156
+
157
+ ```
158
+ --ai Enable AI triage
159
+ --ai-provider <id> Provider (see table above)
160
+ --ai-model <name> Override default model for the chosen provider
161
+ --ai-endpoint <url> Ollama endpoint (default http://localhost:11434)
162
+ --ai-max-tokens <n> Input token cap (default 60000)
163
+ --ai-max-cost <usd> Refuse a call whose pre-flight cost exceeds this USD
164
+ --ai-daily-budget <usd> Refuse triage when today's total spend would exceed this USD
165
+ --ai-cache-ttl <duration> Triage cache TTL (default 30d)
166
+ --no-ai-cache Bypass cache
167
+ --no-ai-suggest Suppress discovery hint
168
+ ```
169
+
170
+ ### How it works
171
+
172
+ After the linter runs, the AI step takes the enriched findings (capped at 200 by severity) and asks the model to identify 1–5 underlying root causes ranked by SEO impact. The findings list is unchanged — triage is an *additional* section above it.
173
+
174
+ ### Model reliability
175
+
176
+ Triage uses structured-output generation (JSON matching a strict schema). Not every model handles this reliably at real-world audit sizes.
177
+
178
+ **Recommended (validated):** `claude-sonnet-4-6`, `claude-opus-4-7`, `gpt-4o`, `gemini-2.5-pro`.
179
+ **Works but marginal:** `gpt-4o-mini`, `gemini-2.5-flash` — cheaper, sometimes truncate.
180
+ **Avoid for triage:** `claude-haiku-4-5-20251001` and similar small models — fails schema validation in our smoke tests (~30 findings). If you want cheap, prefer `gpt-4o-mini` or `gemini-2.5-flash`.
181
+
182
+ If your chosen model fails, you'll see `[ai-triage] skipped: ...` on stderr and the audit completes normally. Check `pseolint stats` for skip-reason counters.
183
+
184
+ ### Cost and budget
185
+
186
+ - Triage runs as **one** model call per audit. Default input cap: 60k tokens.
187
+ - A pre-flight line is printed before every call: `[ai-triage] calling anthropic:claude-sonnet-4-6 — ~12,000 input / ≤4,000 output tokens, ~$0.12`. You can Ctrl-C before the call lands.
188
+ - **Per-call cap:** `--ai-max-cost 0.50` refuses the call if the pre-flight estimate exceeds $0.50. Recommended for any CI use.
189
+ - **Daily budget:** `--ai-max-cost 0.50 --ai-daily-budget 5.00 --telemetry` reads today's successful-triage spend from your local telemetry JSONL and refuses the call when the running total would breach the budget. **"Today" is a UTC calendar day** — the counter rolls over at `00:00 UTC`, which is a fixed offset from your local midnight. Cache hits are excluded from the running total (no real API call, no real spend).
190
+ - Results are cached at `.pseolint/ai-cache/` for 30 days. Re-running on unchanged audit data is free.
191
+ - Cache key includes the prompt version — bumping it auto-invalidates the cache.
192
+ - **Do not put `apiKey` in a committed config file.** Use the provider's env var (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, etc.). A warning is printed if `ai.apiKey` is set.
193
+ - The cost estimate is best-effort based on a hardcoded pricing table for the most common models. Your provider's billing dashboard is authoritative.
194
+
195
+ ### Privacy
196
+
197
+ Triage sends finding rule IDs, severities, messages, and (optional) page URLs to the configured provider. Messages may contain page titles or short content excerpts (per existing rule outputs). Use the **Ollama** provider to keep all data on your machine.
198
+
199
+ ### Failure modes (fail-open)
200
+
201
+ Any error in the AI step (auth, rate-limit, network, unparseable response, missing SDK) skips triage with a stderr message. The audit completes normally — exit code, JSON output, and findings list are unchanged.
202
+
203
+ ## Telemetry (local-only)
204
+
205
+ Opt-in. Writes a JSONL log of your audit runs to `.pseolint/telemetry.jsonl`. **Nothing is sent anywhere** — no network calls, no phoning home. This is yours to inspect.
206
+
207
+ ### Enable
208
+
209
+ ```bash
210
+ pseolint ./site --telemetry
211
+ ```
212
+
213
+ Or in `pseolint.config.ts`:
214
+ ```ts
215
+ export default {
216
+ telemetry: { enabled: true },
217
+ };
218
+ ```
219
+
220
+ ### What gets recorded
221
+
222
+ Counts only — no URLs, no page content, no API keys:
223
+
224
+ - Audit: `runId`, `timestamp`, `durationMs`, `score`, `pageCount`, `findingCount`, optional `cacheStats`, optional `triage` metadata (model, token counts, cache hit, cost estimate).
225
+ - Feedback: `runId`, `timestamp`, `rating`.
226
+
227
+ ### View
228
+
229
+ ```bash
230
+ pseolint stats # pretty summary
231
+ pseolint stats --json # machine-readable
232
+ ```
233
+
234
+ ### Triage feedback
235
+
236
+ When AI triage runs, you'll see a one-line prompt after the section:
237
+ ```
238
+ Was this triage helpful? [y/n/skip]
239
+ ```
240
+ Skippable. Suppress with `--no-telemetry-prompt` or `telemetry.prompt: false`.
241
+
242
+ In CI (no TTY), the prompt auto-skips. Pass `--triage-feedback helpful|unhelpful` to record a rating non-interactively.
243
+
244
+ ### Share
245
+
246
+ ```bash
247
+ pseolint stats-export /tmp/tel.jsonl
248
+ ```
249
+ Copies your file so you can inspect it before sharing. No automatic upload.
250
+
251
+ ## Documentation
252
+
253
+ See the full documentation at [github.com/ouranos-labs/pseolint](https://github.com/ouranos-labs/pseolint).
254
+
255
+ ## License
256
+
257
+ MIT
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAyCA,wBAAsB,MAAM,CAC1B,IAAI,GAAE,MAAM,EAA0B,GACrC,OAAO,CAAC,MAAM,CAAC,CA6FjB"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAgEA,wBAAsB,MAAM,CAC1B,IAAI,GAAE,MAAM,EAA0B,GACrC,OAAO,CAAC,MAAM,CAAC,CA2FjB"}
package/dist/cli.js CHANGED
@@ -14,11 +14,12 @@ const formatters = {
14
14
  };
15
15
  export async function runCli(args = process.argv.slice(2)) {
16
16
  const program = new Command();
17
+ let exitCode = 0;
17
18
  program
18
19
  .name("pseolint")
19
20
  .description("Programmatic SEO linter — audit sites for SpamBrain risk")
20
21
  .version(version)
21
- .argument("<source>", "Directory path or URL to audit")
22
+ .argument("[source]", "Directory path or URL to audit")
22
23
  .option("-f, --format <type>", "Output format: console, json, markdown, html", "console")
23
24
  .option("-t, --threshold <n>", "SpamBrain Risk Score threshold for CI exit code", "40")
24
25
  .option("-o, --output <file>", "Write report to file instead of stdout")
@@ -29,12 +30,75 @@ export async function runCli(args = process.argv.slice(2)) {
29
30
  .option("--ignore <patterns>", "Comma-separated glob patterns to exclude")
30
31
  .option("--render", "Render pages in a browser before auditing")
31
32
  .option("--browser-ws <url>", "CDP WebSocket endpoint for browser rendering")
32
- .option("--no-crawl", "Disable crawl-based page discovery for URL sources");
33
- program.parse(args, { from: "user" });
34
- const opts = program.opts();
35
- const source = program.args[0];
33
+ .option("--no-crawl", "Disable crawl-based page discovery for URL sources")
34
+ .option("--data-source <file>", "JSON file with source data for content verification")
35
+ .option("--cache [dir]", "Enable HTTP cache (default dir: .pseolint/cache)")
36
+ .option("--cache-ttl <duration>", "Cache TTL for entries without validators, e.g. 7d, 1h, 30m", "7d")
37
+ .option("--strategy <random|stratified>", "Sampling strategy when --sample-size is set", "stratified")
38
+ .option("--max-per-template <n>", "Cap samples per URL template cluster", "0")
39
+ .option("--state [path]", "Enable state persistence (default path: .pseolint/state.json)")
40
+ .option("--since", "Delta mode: audit only URLs changed since prior --state (requires --state)")
41
+ .option("--exit-on-regression", "Exit non-zero when new rule IDs fire vs prior --state")
42
+ .option("--ai", "Enable AI triage of findings")
43
+ .option("--ai-provider <id>", "AI provider: anthropic | openai | google | mistral | groq | xai | cohere | ollama (default: auto-detect)")
44
+ .option("--ai-model <name>", "AI model name (overrides provider default)")
45
+ .option("--ai-endpoint <url>", "AI endpoint (Ollama only; default: http://localhost:11434)")
46
+ .option("--ai-max-tokens <n>", "Input token cap per triage call", (v) => parseInt(v, 10), 60000)
47
+ .option("--ai-max-cost <usd>", "Refuse a triage call whose pre-flight cost estimate exceeds this many USD", (v) => parseFloat(v))
48
+ .option("--ai-daily-budget <usd>", "Refuse triage when today's total estimated spend would exceed this USD (requires --telemetry)", (v) => parseFloat(v))
49
+ .option("--ai-cache-ttl <duration>", "Triage cache TTL (e.g. 30d, 12h, 60s)", "30d")
50
+ .option("--no-ai-cache", "Bypass AI triage cache for this run")
51
+ .option("--no-ai-suggest", "Suppress AI discovery hint")
52
+ .option("--telemetry", "Enable local telemetry write (.pseolint/telemetry.jsonl)")
53
+ .option("--no-telemetry-prompt", "Suppress the y/n/skip triage feedback prompt")
54
+ .option("--telemetry-path <file>", "Override telemetry JSONL path")
55
+ .option("--triage-feedback <rating>", "Non-interactive feedback: helpful|unhelpful|y|n")
56
+ .option("--mcp", "Start as an MCP server (for AI coding assistants)")
57
+ .action(async (source, opts) => {
58
+ exitCode = await runAudit(source, opts);
59
+ });
60
+ program
61
+ .command("stats")
62
+ .description("Show aggregate telemetry stats from .pseolint/telemetry.jsonl")
63
+ .option("--path <file>", "Path to telemetry JSONL", ".pseolint/telemetry.jsonl")
64
+ .option("--json", "Output stats as JSON")
65
+ .action(async (opts) => {
66
+ const { readTelemetryJsonl, aggregateTelemetry } = await import("@pseolint/core");
67
+ const records = await readTelemetryJsonl(opts.path);
68
+ const stats = aggregateTelemetry(records);
69
+ if (opts.json) {
70
+ process.stdout.write(JSON.stringify(stats, null, 2) + "\n");
71
+ return;
72
+ }
73
+ renderStats(stats);
74
+ });
75
+ program
76
+ .command("stats-export <outPath>")
77
+ .description("Copy telemetry JSONL to <outPath> for manual review/sharing")
78
+ .option("--path <file>", "Path to telemetry JSONL", ".pseolint/telemetry.jsonl")
79
+ .action(async (outPath, opts) => {
80
+ const { copyFile } = await import("node:fs/promises");
81
+ try {
82
+ await copyFile(opts.path, outPath);
83
+ process.stderr.write(`Wrote ${outPath}\n`);
84
+ }
85
+ catch (e) {
86
+ process.stderr.write(`Failed to read ${opts.path}: ${e.message}\n`);
87
+ exitCode = 1;
88
+ }
89
+ });
90
+ await program.parseAsync(args, { from: "user" });
91
+ return exitCode;
92
+ }
93
+ async function runAudit(source, opts) {
94
+ if (opts.mcp) {
95
+ const { startMcpServer } = await import("./mcp.js");
96
+ startMcpServer();
97
+ return 0; // never reached, server runs until stdin closes
98
+ }
36
99
  if (!source) {
37
- program.help();
100
+ // Print help via a temporary Command since we're inside the action
101
+ process.stderr.write("Error: source argument is required. Run `pseolint --help` for usage.\n");
38
102
  return 1;
39
103
  }
40
104
  const threshold = Number(opts.threshold);
@@ -56,8 +120,92 @@ export async function runCli(args = process.argv.slice(2)) {
56
120
  ignore: opts.ignore ? opts.ignore.split(",").map((s) => s.trim()) : undefined,
57
121
  render: opts.render ? { browserWsEndpoint: opts.browserWs } : undefined,
58
122
  crawlDiscovery: opts.crawl === false ? false : undefined,
123
+ samplingStrategy: opts.strategy === "random" ? "random" : "stratified",
124
+ maxPerTemplate: opts.maxPerTemplate !== "0" ? Number(opts.maxPerTemplate) : undefined,
59
125
  };
126
+ if (opts.cache) {
127
+ try {
128
+ cliFlags.cache = {
129
+ dir: typeof opts.cache === "string" ? opts.cache : undefined,
130
+ ttlMs: parseDuration(opts.cacheTtl),
131
+ };
132
+ }
133
+ catch (err) {
134
+ const message = err instanceof Error ? err.message : String(err);
135
+ console.error(`Error: ${message}`);
136
+ return 1;
137
+ }
138
+ }
139
+ if ((opts.since || opts.exitOnRegression) && !opts.state) {
140
+ console.error("Error: --since and --exit-on-regression require --state to be set");
141
+ return 1;
142
+ }
143
+ if (opts.state || opts.since || opts.exitOnRegression) {
144
+ cliFlags.state = {
145
+ path: typeof opts.state === "string" ? opts.state : undefined,
146
+ since: Boolean(opts.since),
147
+ exitOnRegression: Boolean(opts.exitOnRegression),
148
+ };
149
+ }
150
+ // AI flags
151
+ let aiCache;
152
+ try {
153
+ aiCache = opts.aiCache === false ? false : { ttlMs: parseDuration(opts.aiCacheTtl) };
154
+ }
155
+ catch (err) {
156
+ const message = err instanceof Error ? err.message : String(err);
157
+ console.error(`Error: ${message}`);
158
+ return 1;
159
+ }
160
+ if (opts.ai) {
161
+ cliFlags.ai = {
162
+ enabled: true,
163
+ provider: opts.aiProvider,
164
+ model: opts.aiModel,
165
+ endpoint: opts.aiEndpoint,
166
+ maxInputTokens: opts.aiMaxTokens,
167
+ maxCostUsd: Number.isFinite(opts.aiMaxCost) ? opts.aiMaxCost : undefined,
168
+ dailyBudgetUsd: Number.isFinite(opts.aiDailyBudget) ? opts.aiDailyBudget : undefined,
169
+ suggest: opts.aiSuggest !== false,
170
+ cache: aiCache,
171
+ };
172
+ }
173
+ else if (opts.aiSuggest === false) {
174
+ // allow suppressing the hint without enabling AI
175
+ cliFlags.ai = { suggest: false };
176
+ }
177
+ const telemetryFeedback = opts.triageFeedback
178
+ ? (opts.triageFeedback === "y" || opts.triageFeedback === "yes" || opts.triageFeedback === "helpful")
179
+ ? "helpful"
180
+ : (opts.triageFeedback === "n" || opts.triageFeedback === "no" || opts.triageFeedback === "unhelpful")
181
+ ? "unhelpful"
182
+ : undefined
183
+ : undefined;
184
+ const telemetry = opts.telemetry || opts.telemetryPath || telemetryFeedback || opts.telemetryPrompt === false
185
+ ? {
186
+ enabled: opts.telemetry === true,
187
+ path: opts.telemetryPath,
188
+ prompt: opts.telemetryPrompt !== false,
189
+ feedback: telemetryFeedback,
190
+ }
191
+ : undefined;
192
+ if (telemetry !== undefined) {
193
+ cliFlags.telemetry = telemetry;
194
+ }
60
195
  const options = mergeOptions(configFile, cliFlags);
196
+ if (opts.dataSource) {
197
+ const { loadDataSource } = await import("@pseolint/core");
198
+ try {
199
+ const records = await loadDataSource(opts.dataSource);
200
+ options.dataSource = { records };
201
+ console.log(`Loaded ${records.length} data source records from ${opts.dataSource}`);
202
+ }
203
+ catch (err) {
204
+ const message = err instanceof Error ? err.message : String(err);
205
+ console.error(`Error loading data source: ${message}`);
206
+ return 1;
207
+ }
208
+ }
61
209
  // Run audit
62
210
  let summary;
63
211
  try {
@@ -68,6 +216,11 @@ export async function runCli(args = process.argv.slice(2)) {
68
216
  console.error(`Error: ${message}`);
69
217
  return 1;
70
218
  }
219
+ if (summary.cacheStats && summary.cacheStats.total > 0) {
220
+ const { hits, total, bytesSavedEstimate } = summary.cacheStats;
221
+ const mb = (bytesSavedEstimate / (1024 * 1024)).toFixed(2);
222
+ console.error(`Cache: ${hits}/${total} hits (${mb} MB saved)`);
223
+ }
71
224
  // Format output
72
225
  const output = format === "console"
73
226
  ? formatConsole(summary, { noColor: !opts.color })
@@ -83,8 +236,76 @@ export async function runCli(args = process.argv.slice(2)) {
83
236
  else {
84
237
  console.log(output);
85
238
  }
86
- // Exit code based on threshold
87
- return summary.score >= threshold ? 1 : 0;
239
+ // Exit code based on threshold + regression
240
+ let exitCode = summary.score >= threshold ? 1 : 0;
241
+ if (summary.hasRegression) {
242
+ console.error("Regression detected: new rule IDs fired vs prior state");
243
+ exitCode = Math.max(exitCode, 1);
244
+ }
245
+ return exitCode;
246
+ }
247
+ function renderStats(stats) {
248
+ const NA = "—";
249
+ const formatDuration = (ms) => {
250
+ if (ms === null)
251
+ return NA;
252
+ return `${(ms / 1000).toFixed(1)}s`;
253
+ };
254
+ const formatRound = (n) => {
255
+ if (n === null)
256
+ return NA;
257
+ return String(Math.round(n));
258
+ };
259
+ const formatPct = (num, denom) => {
260
+ if (denom === 0)
261
+ return NA;
262
+ return `${Math.round((num / denom) * 100)}%`;
263
+ };
264
+ const formatNum = (n) => n.toLocaleString("en-US");
265
+ const formatCost = (n) => {
266
+ if (n === 0)
267
+ return NA;
268
+ return `$${n.toFixed(2)}`;
269
+ };
270
+ const formatDate = (s) => s ?? NA;
271
+ const pad = (label) => label.padEnd(20);
272
+ const lines = [];
273
+ lines.push("Telemetry summary");
274
+ lines.push(` ${pad("Total audits")}: ${stats.totalAudits}`);
275
+ lines.push(` ${pad("Average duration")}: ${formatDuration(stats.avgDurationMs)}`);
276
+ lines.push(` ${pad("Average score")}: ${formatRound(stats.avgScore)}`);
277
+ lines.push(` ${pad("Average findings")}: ${formatRound(stats.avgFindings)}`);
278
+ lines.push(` ${pad("Average page count")}: ${formatRound(stats.avgPages)}`);
279
+ lines.push("");
280
+ lines.push("AI triage");
281
+ lines.push(` ${pad("Attempts")}: ${stats.triageAttempts}`);
282
+ lines.push(` ${pad("Successful")}: ${stats.triageUsed}`);
283
+ lines.push(` ${pad("Success rate")}: ${formatPct(stats.triageUsed, stats.triageAttempts)}`);
284
+ lines.push(` ${pad("Cache hit rate")}: ${formatPct(stats.triageCacheHits, stats.triageUsed)}`);
285
+ for (const [reason, count] of Object.entries(stats.triageSkipReasons)) {
286
+ lines.push(` ${pad(` skip: ${reason}`)}: ${count}`);
287
+ }
288
+ lines.push(` ${pad("Tokens (in/out)")}: ${formatNum(stats.totalTokenInput)} / ${formatNum(stats.totalTokenOutput)}`);
289
+ lines.push(` ${pad("Estimated cost")}: ${formatCost(stats.totalEstimatedCostUsd)}`);
290
+ lines.push("");
291
+ lines.push("Feedback");
292
+ lines.push(` ${pad("Helpful")}: ${stats.feedbackBreakdown.helpful}`);
293
+ lines.push(` ${pad("Unhelpful")}: ${stats.feedbackBreakdown.unhelpful}`);
294
+ lines.push(` ${pad("Skipped")}: ${stats.feedbackBreakdown.skipped}`);
295
+ lines.push("");
296
+ lines.push("Data range");
297
+ lines.push(` ${pad("First run")}: ${formatDate(stats.firstRun)}`);
298
+ lines.push(` ${pad("Last run")}: ${formatDate(stats.lastRun)}`);
299
+ process.stdout.write(lines.join("\n") + "\n");
300
+ }
301
+ function parseDuration(s) {
302
+ const m = s.match(/^(\d+)(ms|s|m|h|d)$/);
303
+ if (!m)
304
+ throw new Error(`invalid duration: ${s}. Use e.g. 1h, 30m, 7d.`);
305
+ const n = Number(m[1]);
306
+ const unit = m[2];
307
+ const mul = { ms: 1, s: 1000, m: 60_000, h: 3_600_000, d: 86_400_000 }[unit] ?? 1;
308
+ return n * mul;
88
309
  }
89
310
  // Direct execution
90
311
  const scriptUrl = `file://${process.argv[1]?.replace(/\\/g, "/")}`;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -9,6 +9,36 @@ export interface CliFlags {
9
9
  browserWsEndpoint?: string;
10
10
  };
11
11
  crawlDiscovery?: boolean;
12
+ cache?: {
13
+ dir?: string;
14
+ ttlMs: number;
15
+ };
16
+ samplingStrategy?: "stratified" | "random";
17
+ maxPerTemplate?: number;
18
+ state?: {
19
+ path?: string;
20
+ since?: boolean;
21
+ exitOnRegression?: boolean;
22
+ };
23
+ ai?: {
24
+ enabled?: boolean;
25
+ provider?: string;
26
+ model?: string;
27
+ endpoint?: string;
28
+ maxInputTokens?: number;
29
+ maxCostUsd?: number;
30
+ dailyBudgetUsd?: number;
31
+ suggest?: boolean;
32
+ cache?: {
33
+ ttlMs?: number;
34
+ } | false;
35
+ };
36
+ telemetry?: {
37
+ enabled?: boolean;
38
+ path?: string;
39
+ prompt?: boolean;
40
+ feedback?: "helpful" | "unhelpful";
41
+ };
12
42
  }
13
43
  export declare function mergeOptions(configFile: AuditOptions, cliFlags: CliFlags): AuditOptions;
14
44
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAyCnD,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,CAUxD;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAC1B,UAAU,EAAE,YAAY,EACxB,QAAQ,EAAE,QAAQ,GACjB,YAAY,CASd"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAkFnD,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,CAUxD;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,gBAAgB,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAC;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACvE,EAAE,CAAC,EAAE;QACH,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,KAAK,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,KAAK,CAAC;KACpC,CAAC;IACF,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;KACpC,CAAC;CACH;AAED,wBAAgB,YAAY,CAC1B,UAAU,EAAE,YAAY,EACxB,QAAQ,EAAE,QAAQ,GACjB,YAAY,CA4Cd"}
package/dist/config.js CHANGED
@@ -36,6 +36,47 @@ const auditOptionsSchema = z.object({
36
36
  }).optional(),
37
37
  crawlDiscovery: z.boolean().optional(),
38
38
  templateGenerated: z.boolean().optional(),
39
+ entityPatterns: z.array(z.object({
40
+ placeholder: z.string(),
41
+ pattern: z.string(),
42
+ flags: z.string().optional(),
43
+ })).optional(),
44
+ cache: z.object({
45
+ dir: z.string().optional(),
46
+ ttlMs: z.number().optional(),
47
+ }).optional(),
48
+ state: z.object({
49
+ path: z.string().optional(),
50
+ since: z.boolean().optional(),
51
+ exitOnRegression: z.boolean().optional(),
52
+ }).optional(),
53
+ samplingStrategy: z.enum(["stratified", "random"]).optional(),
54
+ maxPerTemplate: z.number().optional(),
55
+ ai: z.object({
56
+ enabled: z.boolean().optional(),
57
+ provider: z.string().optional(),
58
+ model: z.string().optional(),
59
+ endpoint: z.string().optional(),
60
+ apiKey: z.string().optional(),
61
+ maxInputTokens: z.number().optional(),
62
+ maxOutputTokens: z.number().optional(),
63
+ maxCostUsd: z.number().optional(),
64
+ dailyBudgetUsd: z.number().optional(),
65
+ suggest: z.boolean().optional(),
66
+ cache: z.union([
67
+ z.object({
68
+ ttlMs: z.number().optional(),
69
+ dir: z.string().optional(),
70
+ }),
71
+ z.literal(false),
72
+ ]).optional(),
73
+ }).optional(),
74
+ telemetry: z.object({
75
+ enabled: z.boolean().optional(),
76
+ path: z.string().optional(),
77
+ prompt: z.boolean().optional(),
78
+ feedback: z.enum(["helpful", "unhelpful"]).optional(),
79
+ }).optional(),
39
80
  });
40
81
  export async function loadConfig() {
41
82
  const explorer = cosmiconfig("pseolint");
@@ -60,6 +101,58 @@ export function mergeOptions(configFile, cliFlags) {
60
101
  result.render = cliFlags.render;
61
102
  if (cliFlags.crawlDiscovery !== undefined)
62
103
  result.crawlDiscovery = cliFlags.crawlDiscovery;
104
+ if (cliFlags.cache !== undefined)
105
+ result.cache = cliFlags.cache;
106
+ if (cliFlags.samplingStrategy !== undefined)
107
+ result.samplingStrategy = cliFlags.samplingStrategy;
108
+ if (cliFlags.maxPerTemplate !== undefined)
109
+ result.maxPerTemplate = cliFlags.maxPerTemplate;
110
+ if (cliFlags.state !== undefined)
111
+ result.state = cliFlags.state;
112
+ if (cliFlags.ai !== undefined) {
113
+ const merged = { ...result.ai };
114
+ if (cliFlags.ai.enabled !== undefined)
115
+ merged.enabled = cliFlags.ai.enabled;
116
+ if (cliFlags.ai.provider !== undefined)
117
+ merged.provider = cliFlags.ai.provider;
118
+ if (cliFlags.ai.model !== undefined)
119
+ merged.model = cliFlags.ai.model;
120
+ if (cliFlags.ai.endpoint !== undefined)
121
+ merged.endpoint = cliFlags.ai.endpoint;
122
+ if (cliFlags.ai.maxInputTokens !== undefined)
123
+ merged.maxInputTokens = cliFlags.ai.maxInputTokens;
124
+ if (cliFlags.ai.maxCostUsd !== undefined)
125
+ merged.maxCostUsd = cliFlags.ai.maxCostUsd;
126
+ if (cliFlags.ai.dailyBudgetUsd !== undefined)
127
+ merged.dailyBudgetUsd = cliFlags.ai.dailyBudgetUsd;
128
+ if (cliFlags.ai.suggest !== undefined)
129
+ merged.suggest = cliFlags.ai.suggest;
130
+ if (cliFlags.ai.cache !== undefined) {
131
+ if (cliFlags.ai.cache === false) {
132
+ merged.cache = false;
133
+ }
134
+ else {
135
+ const prior = typeof result.ai?.cache === "object" ? result.ai.cache : undefined;
136
+ merged.cache = {
137
+ ...(prior ?? {}),
138
+ ...(cliFlags.ai.cache.ttlMs !== undefined && { ttlMs: cliFlags.ai.cache.ttlMs }),
139
+ };
140
+ }
141
+ }
142
+ result.ai = merged;
143
+ }
144
+ if (cliFlags.telemetry !== undefined) {
145
+ const merged = { ...result.telemetry };
146
+ if (cliFlags.telemetry.enabled !== undefined)
147
+ merged.enabled = cliFlags.telemetry.enabled;
148
+ if (cliFlags.telemetry.path !== undefined)
149
+ merged.path = cliFlags.telemetry.path;
150
+ if (cliFlags.telemetry.prompt !== undefined)
151
+ merged.prompt = cliFlags.telemetry.prompt;
152
+ if (cliFlags.telemetry.feedback !== undefined)
153
+ merged.feedback = cliFlags.telemetry.feedback;
154
+ result.telemetry = merged;
155
+ }
63
156
  return result;
64
157
  }
65
158
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,WAAW,GAAG,CAAC;KAClB,MAAM,CAAC;IACN,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACrC,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACpC,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7C,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,4BAA4B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnD,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,+BAA+B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtD,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,wBAAwB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/C,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACzC,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5C,yBAAyB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChD,wBAAwB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChD,CAAC;KACD,QAAQ,EAAE,CAAC;AAEd,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,KAAK,EAAE,WAAW;IAClB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACtC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC;QACxC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjD,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QACrC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;KAC9E,CAAC,CAAC,CAAC,QAAQ,EAAE;IACd,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACzC,CAAC,CAAC,QAAQ,EAAE;IACb,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACtC,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACzC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAC/B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;QACvB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;QACnB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC7B,CAAC,CAAC,CAAC,QAAQ,EAAE;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC7B,CAAC,CAAC,QAAQ,EAAE;IACb,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC7B,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;KACzC,CAAC,CAAC,QAAQ,EAAE;IACb,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC7D,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC;QACX,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC/B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC/B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC/B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC7B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACrC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACtC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACjC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACrC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC/B,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC;YACb,CAAC,CAAC,MAAM,CAAC;gBACP,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;gBAC5B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;aAC3B,CAAC;YACF,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;SACjB,CAAC,CAAC,QAAQ,EAAE;KACd,CAAC,CAAC,QAAQ,EAAE;IACb,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC;QAClB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC/B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC9B,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE;KACtD,CAAC,CAAC,QAAQ,EAAE;CACd,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;IAEvC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvD,OAAO,MAAsB,CAAC;AAChC,CAAC;AAgCD,MAAM,UAAU,YAAY,CAC1B,UAAwB,EACxB,QAAkB;IAElB,MAAM,MAAM,GAAG,EAAE,GAAG,UAAU,EAAE,CAAC;IACjC,IAAI,QAAQ,CAAC,WAAW,KAAK,SAAS;QAAE,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;IAClF,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS;QAAE,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IACtE,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS;QAAE,MAAM,CAAC,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;IAC/E,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS;QAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IACnE,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS;QAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IACnE,IAAI,QAAQ,CAAC,cAAc,KAAK,SAAS;QAAE,MAAM,CAAC,cAAc,GAAG,QAAQ,CAAC,cAAc,CAAC;IAC3F,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS;QAAE,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAChE,IAAI,QAAQ,CAAC,gBAAgB,KAAK,SAAS;QAAE,MAAM,CAAC,gBAAgB,GAAG,QAAQ,CAAC,gBAAgB,CAAC;IACjG,IAAI,QAAQ,CAAC,cAAc,KAAK,SAAS;QAAE,MAAM,CAAC,cAAc,GAAG,QAAQ,CAAC,cAAc,CAAC;IAC3F,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS;QAAE,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAChE,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAoC,EAAE,GAAG,MAAM,CAAC,EAAE,EAAE,CAAC;QACjE,IAAI,QAAQ,CAAC,EAAE,CAAC,OAAO,KAAK,SAAS;YAAE,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC;QAC5E,IAAI,QAAQ,CAAC,EAAE,CAAC,QAAQ,KAAK,SAAS;YAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC;QAC/E,IAAI,QAAQ,CAAC,EAAE,CAAC,KAAK,KAAK,SAAS;YAAE,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC;QACtE,IAAI,QAAQ,CAAC,EAAE,CAAC,QAAQ,KAAK,SAAS;YAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC;QAC/E,IAAI,QAAQ,CAAC,EAAE,CAAC,cAAc,KAAK,SAAS;YAAE,MAAM,CAAC,cAAc,GAAG,QAAQ,CAAC,EAAE,CAAC,cAAc,CAAC;QACjG,IAAI,QAAQ,CAAC,EAAE,CAAC,UAAU,KAAK,SAAS;YAAE,MAAM,CAAC,UAAU,GAAG,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC;QACrF,IAAI,QAAQ,CAAC,EAAE,CAAC,cAAc,KAAK,SAAS;YAAE,MAAM,CAAC,cAAc,GAAG,QAAQ,CAAC,EAAE,CAAC,cAAc,CAAC;QACjG,IAAI,QAAQ,CAAC,EAAE,CAAC,OAAO,KAAK,SAAS;YAAE,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC;QAC5E,IAAI,QAAQ,CAAC,EAAE,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YACpC,IAAI,QAAQ,CAAC,EAAE,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;gBAChC,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,GAAG,OAAO,MAAM,CAAC,EAAE,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;gBACjF,MAAM,CAAC,KAAK,GAAG;oBACb,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;oBAChB,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;iBACjF,CAAC;YACJ,CAAC;QACH,CAAC;QACD,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC;IACrB,CAAC;IACD,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACrC,MAAM,MAAM,GAA2C,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAC/E,IAAI,QAAQ,CAAC,SAAS,CAAC,OAAO,KAAK,SAAS;YAAE,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC;QAC1F,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,SAAS;YAAE,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;QACjF,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,KAAK,SAAS;YAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC;QACvF,IAAI,QAAQ,CAAC,SAAS,CAAC,QAAQ,KAAK,SAAS;YAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC;QAC7F,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  export { runCli } from "./cli.js";
2
+ export { startMcpServer } from "./mcp.js";
2
3
  export * from "@pseolint/core";
4
+ import type { AuditOptions } from "@pseolint/core";
5
+ export declare function defineConfig(config: AuditOptions): AuditOptions;
3
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAE/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAE/D"}
package/dist/index.js CHANGED
@@ -1,3 +1,7 @@
1
1
  export { runCli } from "./cli.js";
2
+ export { startMcpServer } from "./mcp.js";
2
3
  export * from "@pseolint/core";
4
+ export function defineConfig(config) {
5
+ return config;
6
+ }
3
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAI/B,MAAM,UAAU,YAAY,CAAC,MAAoB;IAC/C,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { startMcpServer } from "@pseolint/mcp";
2
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
package/dist/mcp.js ADDED
@@ -0,0 +1,2 @@
1
+ export { startMcpServer } from "@pseolint/mcp";
2
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pseolint",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Programmatic SEO linter CLI — SpamBrain-proof your pSEO before you publish",
5
5
  "license": "MIT",
6
6
  "author": "Ouranos Labs <contact@ouranos-labs.dev>",
@@ -37,6 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@pseolint/core": "workspace:*",
40
+ "@pseolint/mcp": "workspace:*",
40
41
  "commander": "^14.0.3",
41
42
  "cosmiconfig": "^9.0.1",
42
43
  "zod": "^4.3.6"