@syv-ai/rulecast 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,9 +1,45 @@
1
- import { A as Adapter, D as DetectorRuleInput, a as DetectorRun, M as Match, b as Detector, c as AnyDetector, d as AdapterInput, e as Delivery, E as Event } from './types-2oz2AlwA.js';
2
- export { f as AdapterInstall, C as Cache, g as ChangeSet, h as CheckResult, i as CompiledDetector, j as CompiledRule, k as DeliveredReference, l as DetectorCheck, m as DetectorEvent, n as DetectorRegistry, o as DetectorResult, p as DetectorRule, q as DetectorSettings, r as DetectorWarm, s as EventKind, F as Finding, I as InstallScope, L as LLM_PROVIDERS, t as LlmFinding, u as LlmProvider, v as LlmProviderName, w as LlmRequest, x as LlmSettings, y as LlmUnavailableError, O as Omitted, R as ReferenceMode, z as ResolvedReference, S as Severity, T as TouchRule, W as WriteIntent, B as createRegistry, G as defaultDetectorSettings, H as emptyDelivery, J as isDetectorRule } from './types-2oz2AlwA.js';
1
+ import { A as Adapter, D as Delivery, a as DetectorRuleInput, b as DetectorRun, M as Match, c as Detector, d as AnyDetector, e as AdapterInput, E as Event } from './types-C8b7hrnG.js';
2
+ export { f as AdapterInstall, C as Cache, g as ChangeSet, h as CheckResult, i as CompiledDetector, j as CompiledRule, k as DeliveredReference, l as DetectorCheck, m as DetectorEvent, n as DetectorRegistry, o as DetectorResult, p as DetectorRule, q as DetectorSettings, r as DetectorWarm, s as EventKind, F as Finding, I as InstallScope, L as LLM_PROVIDERS, t as LlmFinding, u as LlmProvider, v as LlmProviderName, w as LlmRequest, x as LlmSettings, y as LlmUnavailableError, O as Omitted, R as ReferenceMode, z as ResolvedReference, B as RuleScope, S as Severity, T as TouchRule, W as WriteIntent, G as createRegistry, H as defaultDetectorSettings, J as emptyDelivery, K as isDetectorRule } from './types-C8b7hrnG.js';
3
3
  import 'zod';
4
4
 
5
5
  declare const claudeCodeAdapter: Adapter;
6
6
 
7
+ /**
8
+ * How much of a rule a repository already owes, per rule and per file.
9
+ *
10
+ * Counts, never rates. One codebase went from 61 violations in 80 files to 57 in 194 over eight
11
+ * months: the rate fell from 76% to 29% and the count did not move, because new code complied and
12
+ * the old violations were only diluted. A team watching the rate would have believed it was fixing
13
+ * the problem. So this reports the stock and leaves the division to nobody.
14
+ */
15
+ interface BacklogSummary {
16
+ /** Violations descending, then rule ascending. */
17
+ rules: {
18
+ rule: string;
19
+ violations: number;
20
+ files: number;
21
+ }[];
22
+ /** Violations descending, then file ascending. */
23
+ files: {
24
+ file: string;
25
+ violations: number;
26
+ }[];
27
+ totalViolations: number;
28
+ /** Distinct files with at least one violation — not the sum of the per-rule file counts. */
29
+ totalFiles: number;
30
+ }
31
+ /**
32
+ * Both halves of a delivery count.
33
+ *
34
+ * `--all-files` has no baseline, so every violation arrives as a finding. `--from-ref` classifies
35
+ * against the merge base, and there most of the backlog is in `preexistingSummary` — which is
36
+ * exactly the set this exists to give a number to.
37
+ */
38
+ declare function summarise(delivery: Delivery): BacklogSummary;
39
+ declare function renderBacklog(summary: BacklogSummary, options: {
40
+ topFiles: number;
41
+ }): string;
42
+
7
43
  /** Every agent adapter rulecast ships. */
8
44
  declare const ADAPTERS: readonly Adapter[];
9
45
  declare function adapterByName(name: string): Adapter | undefined;
@@ -12,7 +48,7 @@ declare function adapterByName(name: string): Adapter | undefined;
12
48
  declare function perRule<Config>(detect: (rule: DetectorRuleInput<Config>, input: DetectorRun<Config>) => Promise<Match[]>): Detector<Config>["run"];
13
49
 
14
50
  /** The running rulecast version. test/core/version.test.ts keeps it equal to package.json. */
15
- declare const VERSION = "0.2.0";
51
+ declare const VERSION = "0.3.0";
16
52
 
17
53
  declare const builtinDetectors: readonly AnyDetector[];
18
54
 
@@ -71,4 +107,4 @@ interface DetectorFixture {
71
107
  */
72
108
  declare function detectorContract(detector: AnyDetector, fixture: DetectorFixture): ContractCase[];
73
109
 
74
- export { ADAPTERS, Adapter, type AdapterFixture, AdapterInput, AnyDetector, type ContractCase, Delivery, Detector, type DetectorFixture, DetectorRuleInput, DetectorRun, Event, Match, VERSION, adapterByName, adapterContract, builtinDetectors, claudeCodeAdapter, detectorContract, perRule };
110
+ export { ADAPTERS, Adapter, type AdapterFixture, AdapterInput, AnyDetector, type BacklogSummary, type ContractCase, Delivery, Detector, type DetectorFixture, DetectorRuleInput, DetectorRun, Event, Match, VERSION, adapterByName, adapterContract, builtinDetectors, claudeCodeAdapter, detectorContract, perRule, renderBacklog, summarise };
package/dist/index.js CHANGED
@@ -3,8 +3,10 @@ import {
3
3
  adapterByName,
4
4
  builtinDetectors,
5
5
  claudeCodeAdapter,
6
- createRegistry
7
- } from "./chunk-C6C5EER7.js";
6
+ createRegistry,
7
+ renderBacklog,
8
+ summarise
9
+ } from "./chunk-KOUHBT7F.js";
8
10
  import {
9
11
  LlmUnavailableError,
10
12
  VERSION,
@@ -14,7 +16,7 @@ import {
14
16
  memoryCache,
15
17
  perRule,
16
18
  readSourceFile
17
- } from "./chunk-ZEFEQKG5.js";
19
+ } from "./chunk-HZUATJ53.js";
18
20
 
19
21
  // src/testing/adapter-contract.ts
20
22
  import assert from "assert/strict";
@@ -297,5 +299,7 @@ export {
297
299
  detectorContract,
298
300
  emptyDelivery,
299
301
  isDetectorRule,
300
- perRule
302
+ perRule,
303
+ renderBacklog,
304
+ summarise
301
305
  };
@@ -1,5 +1,5 @@
1
- import { n as DetectorRegistry, K as Config, j as CompiledRule, e as Delivery, h as CheckResult, q as DetectorSettings, E as Event, v as LlmProviderName, u as LlmProvider } from './types-2oz2AlwA.js';
2
- export { N as RuleEntry, P as Stage } from './types-2oz2AlwA.js';
1
+ import { n as DetectorRegistry, N as Config, j as CompiledRule, D as Delivery, h as CheckResult, q as DetectorSettings, E as Event, v as LlmProviderName, u as LlmProvider } from './types-C8b7hrnG.js';
2
+ export { P as RuleEntry, Q as Stage } from './types-C8b7hrnG.js';
3
3
  import 'zod';
4
4
 
5
5
  type Checkout = {
package/dist/internal.js CHANGED
@@ -11,13 +11,13 @@ import {
11
11
  fixedRepo,
12
12
  projectStateDir,
13
13
  runPipeline
14
- } from "./chunk-RODZRI7B.js";
14
+ } from "./chunk-7KUPYT35.js";
15
15
  import {
16
16
  MODEL_ALIASES,
17
17
  providerByName,
18
18
  renderAgentText,
19
19
  resolveModel
20
- } from "./chunk-ZEFEQKG5.js";
20
+ } from "./chunk-HZUATJ53.js";
21
21
  export {
22
22
  CONFIG_FILE,
23
23
  MANIFEST_FILE,
@@ -264,6 +264,30 @@ declare function emptyDelivery(): Delivery;
264
264
 
265
265
  declare const STAGES: readonly ["touch", "edit", "verify"];
266
266
  type Stage = (typeof STAGES)[number];
267
+ declare const RULE_SCOPES: readonly ["instance", "container"];
268
+ type RuleScope = (typeof RULE_SCOPES)[number];
269
+ /**
270
+ * One inline example: a file the rule would see, and what is in it.
271
+ *
272
+ * `path` is required and has no useful default — `files`, `exclude`, the type tags and `ast-grep`'s
273
+ * language selection are all functions of it, so an example without one would be testing a
274
+ * different rule than the one that will run.
275
+ */
276
+ declare const exampleSchema: z.ZodObject<{
277
+ path: z.ZodString;
278
+ code: z.ZodString;
279
+ }, "strict", z.ZodTypeAny, {
280
+ code: string;
281
+ path: string;
282
+ }, {
283
+ code: string;
284
+ path: string;
285
+ }>;
286
+ type RuleExample = z.infer<typeof exampleSchema>;
287
+ type RuleExamples = {
288
+ good: RuleExample[];
289
+ bad: RuleExample[];
290
+ };
267
291
  /** A config entry selecting a rule from a rule repo; every key but id overrides the manifest rule's. */
268
292
  declare const overrideSchema: z.ZodObject<{
269
293
  alias: z.ZodOptional<z.ZodString>;
@@ -277,6 +301,12 @@ declare const overrideSchema: z.ZodObject<{
277
301
  stages: z.ZodOptional<z.ZodArray<z.ZodEnum<["touch", "edit", "verify"]>, "atleastone">>;
278
302
  minimum_rulecast_version: z.ZodOptional<z.ZodString>;
279
303
  severity: z.ZodOptional<z.ZodEnum<["error", "warning"]>>;
304
+ /**
305
+ * What the convention belongs to (§8). `instance`: the token the detector matched, classified by
306
+ * whether the agent's edit touched it. `container`: the node the match spans, classified by
307
+ * whether that node already violated the rule at the baseline.
308
+ */
309
+ scope: z.ZodOptional<z.ZodEnum<["instance", "container"]>>;
280
310
  refuse_write: z.ZodOptional<z.ZodBoolean>;
281
311
  detect: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodUnknown>, Record<string, unknown>, Record<string, unknown>>>;
282
312
  message: z.ZodOptional<z.ZodString>;
@@ -290,6 +320,47 @@ declare const overrideSchema: z.ZodObject<{
290
320
  path: string;
291
321
  mode?: "inject" | "read" | undefined;
292
322
  }>]>, "many">>;
323
+ /** Code the rule must flag (`bad`) and must not (`good`), run by `rulecast test`. */
324
+ examples: z.ZodOptional<z.ZodObject<{
325
+ good: z.ZodDefault<z.ZodArray<z.ZodObject<{
326
+ path: z.ZodString;
327
+ code: z.ZodString;
328
+ }, "strict", z.ZodTypeAny, {
329
+ code: string;
330
+ path: string;
331
+ }, {
332
+ code: string;
333
+ path: string;
334
+ }>, "many">>;
335
+ bad: z.ZodDefault<z.ZodArray<z.ZodObject<{
336
+ path: z.ZodString;
337
+ code: z.ZodString;
338
+ }, "strict", z.ZodTypeAny, {
339
+ code: string;
340
+ path: string;
341
+ }, {
342
+ code: string;
343
+ path: string;
344
+ }>, "many">>;
345
+ }, "strict", z.ZodTypeAny, {
346
+ good: {
347
+ code: string;
348
+ path: string;
349
+ }[];
350
+ bad: {
351
+ code: string;
352
+ path: string;
353
+ }[];
354
+ }, {
355
+ good?: {
356
+ code: string;
357
+ path: string;
358
+ }[] | undefined;
359
+ bad?: {
360
+ code: string;
361
+ path: string;
362
+ }[] | undefined;
363
+ }>>;
293
364
  id: z.ZodString;
294
365
  }, "strict", z.ZodTypeAny, {
295
366
  id: string;
@@ -305,12 +376,23 @@ declare const overrideSchema: z.ZodObject<{
305
376
  stages?: ["touch" | "edit" | "verify", ...("touch" | "edit" | "verify")[]] | undefined;
306
377
  minimum_rulecast_version?: string | undefined;
307
378
  severity?: "error" | "warning" | undefined;
379
+ scope?: "instance" | "container" | undefined;
308
380
  refuse_write?: boolean | undefined;
309
381
  detect?: Record<string, unknown> | undefined;
310
382
  context?: (string | {
311
383
  path: string;
312
384
  mode?: "inject" | "read" | undefined;
313
385
  })[] | undefined;
386
+ examples?: {
387
+ good: {
388
+ code: string;
389
+ path: string;
390
+ }[];
391
+ bad: {
392
+ code: string;
393
+ path: string;
394
+ }[];
395
+ } | undefined;
314
396
  }, {
315
397
  id: string;
316
398
  name?: string | undefined;
@@ -325,12 +407,23 @@ declare const overrideSchema: z.ZodObject<{
325
407
  stages?: ["touch" | "edit" | "verify", ...("touch" | "edit" | "verify")[]] | undefined;
326
408
  minimum_rulecast_version?: string | undefined;
327
409
  severity?: "error" | "warning" | undefined;
410
+ scope?: "instance" | "container" | undefined;
328
411
  refuse_write?: boolean | undefined;
329
412
  detect?: Record<string, unknown> | undefined;
330
413
  context?: (string | {
331
414
  path: string;
332
415
  mode?: "inject" | "read" | undefined;
333
416
  })[] | undefined;
417
+ examples?: {
418
+ good?: {
419
+ code: string;
420
+ path: string;
421
+ }[] | undefined;
422
+ bad?: {
423
+ code: string;
424
+ path: string;
425
+ }[] | undefined;
426
+ } | undefined;
334
427
  }>;
335
428
  type RuleEntry = z.infer<typeof overrideSchema>;
336
429
  declare const configSchema: z.ZodEffects<z.ZodObject<{
@@ -570,6 +663,12 @@ interface CompiledRule {
570
663
  /** "local", or the rule repo label ("syv-ai/rulecast@v0.2.0"). */
571
664
  source: string;
572
665
  severity: Severity;
666
+ /**
667
+ * How a finding of this rule is classified against the baseline (spec §8). `instance` — the
668
+ * default, and every rule before 0.2 — is new when the match touches a changed line. `container`
669
+ * is new when the node the match spans was not already violating the rule at the baseline.
670
+ */
671
+ scope: RuleScope;
573
672
  /** Refuse the agent's write when this rule fires on what it is writing (spec §9, Guard). */
574
673
  refuseWrite: boolean;
575
674
  stages: Stage[];
@@ -577,6 +676,11 @@ interface CompiledRule {
577
676
  detector: CompiledDetector | null;
578
677
  message: string | null;
579
678
  context: ReferenceSpec[];
679
+ /**
680
+ * Inline good/bad examples, run by `rulecast test`. `null` when the rule declared none, which
681
+ * `validate` and `test` report differently from a rule that declared an empty set.
682
+ */
683
+ examples: RuleExamples | null;
580
684
  }
581
685
  /**
582
686
  * A rule that runs a detector. compileRule enforces the split — a rule with `detect` must also
@@ -669,4 +773,4 @@ interface LlmProvider {
669
773
  }): Promise<LlmAvailability>;
670
774
  }
671
775
 
672
- export { type Adapter as A, createRegistry as B, type Cache as C, type DetectorRuleInput as D, type Event as E, type Finding as F, defaultDetectorSettings as G, emptyDelivery as H, type InstallScope as I, isDetectorRule as J, type Config as K, LLM_PROVIDERS as L, type Match as M, type RuleEntry as N, type Omitted as O, type Stage as P, type ReferenceMode as R, type Severity as S, type TouchRule as T, type WriteIntent as W, type DetectorRun as a, type Detector as b, type AnyDetector as c, type AdapterInput as d, type Delivery as e, type AdapterInstall as f, type ChangeSet as g, type CheckResult as h, type CompiledDetector as i, type CompiledRule as j, type DeliveredReference as k, type DetectorCheck as l, type DetectorEvent as m, type DetectorRegistry as n, type DetectorResult as o, type DetectorRule as p, type DetectorSettings as q, type DetectorWarm as r, type EventKind as s, type LlmFinding as t, type LlmProvider as u, type LlmProviderName as v, type LlmRequest as w, type LlmSettings as x, LlmUnavailableError as y, type ResolvedReference as z };
776
+ export { type Adapter as A, type RuleScope as B, type Cache as C, type Delivery as D, type Event as E, type Finding as F, createRegistry as G, defaultDetectorSettings as H, type InstallScope as I, emptyDelivery as J, isDetectorRule as K, LLM_PROVIDERS as L, type Match as M, type Config as N, type Omitted as O, type RuleEntry as P, type Stage as Q, type ReferenceMode as R, type Severity as S, type TouchRule as T, type WriteIntent as W, type DetectorRuleInput as a, type DetectorRun as b, type Detector as c, type AnyDetector as d, type AdapterInput as e, type AdapterInstall as f, type ChangeSet as g, type CheckResult as h, type CompiledDetector as i, type CompiledRule as j, type DeliveredReference as k, type DetectorCheck as l, type DetectorEvent as m, type DetectorRegistry as n, type DetectorResult as o, type DetectorRule as p, type DetectorSettings as q, type DetectorWarm as r, type EventKind as s, type LlmFinding as t, type LlmProvider as u, type LlmProviderName as v, type LlmRequest as w, type LlmSettings as x, LlmUnavailableError as y, type ResolvedReference as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syv-ai/rulecast",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Deliver project conventions to coding agents at the moment they matter.",
5
5
  "keywords": [
6
6
  "claude-code",