patdown 0.3.1 → 0.5.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.
Files changed (46) hide show
  1. package/README.md +50 -8
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +51 -26
  4. package/dist/index.d.ts +5 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +4 -1
  7. package/dist/patdown-console-rule-blocks.d.ts +13 -0
  8. package/dist/patdown-console-rule-blocks.d.ts.map +1 -0
  9. package/dist/patdown-console-rule-blocks.js +80 -0
  10. package/dist/patdown-evidence-regions.d.ts +44 -0
  11. package/dist/patdown-evidence-regions.d.ts.map +1 -0
  12. package/dist/patdown-evidence-regions.js +124 -0
  13. package/dist/patdown-github-actions-env.d.ts +6 -0
  14. package/dist/patdown-github-actions-env.d.ts.map +1 -0
  15. package/dist/patdown-github-actions-env.js +17 -0
  16. package/dist/patdown-github-actions-output.d.ts +8 -0
  17. package/dist/patdown-github-actions-output.d.ts.map +1 -0
  18. package/dist/patdown-github-actions-output.js +52 -0
  19. package/dist/patdown-github-actions-summary.d.ts +19 -0
  20. package/dist/patdown-github-actions-summary.d.ts.map +1 -0
  21. package/dist/patdown-github-actions-summary.js +171 -0
  22. package/dist/patdown-glob.d.ts +9 -0
  23. package/dist/patdown-glob.d.ts.map +1 -0
  24. package/dist/patdown-glob.js +21 -0
  25. package/dist/patdown-judge.d.ts +31 -1
  26. package/dist/patdown-judge.d.ts.map +1 -1
  27. package/dist/patdown-judge.js +31 -2
  28. package/dist/patdown-lint-files.d.ts +14 -0
  29. package/dist/patdown-lint-files.d.ts.map +1 -0
  30. package/dist/patdown-lint-files.js +75 -0
  31. package/dist/patdown-lint.d.ts +5 -1
  32. package/dist/patdown-lint.d.ts.map +1 -1
  33. package/dist/patdown-lint.js +67 -25
  34. package/dist/patdown-output.d.ts +26 -7
  35. package/dist/patdown-output.d.ts.map +1 -1
  36. package/dist/patdown-output.js +92 -19
  37. package/dist/patdown-probability-bar.d.ts +3 -0
  38. package/dist/patdown-probability-bar.d.ts.map +1 -0
  39. package/dist/patdown-probability-bar.js +29 -0
  40. package/dist/run-patdown-cli.d.ts +3 -1
  41. package/dist/run-patdown-cli.d.ts.map +1 -1
  42. package/dist/run-patdown-cli.js +16 -3
  43. package/dist/typesafe-judge.d.ts +1 -0
  44. package/dist/typesafe-judge.d.ts.map +1 -1
  45. package/dist/typesafe-judge.js +15 -1
  46. package/package.json +3 -3
@@ -2,26 +2,45 @@ import type { PatdownRulesDocument } from '@patdown/rules';
2
2
  import { type PatdownYesThreshold } from '@patdown/rules';
3
3
  import { Context, Effect, Layer } from 'effect';
4
4
  import { type PatdownJudgment } from '#src/patdown-judge';
5
+ /** Optional 1-based span from a FAIL-only evidence Choice. */
6
+ export type PatdownLintEvidenceSpan = {
7
+ readonly startLine: number;
8
+ readonly endLine: number;
9
+ readonly confidence: number;
10
+ };
5
11
  /** One file/rule result; probability estimates a violation, not correctness of the verdict. */
6
12
  export type PatdownLintResult = {
7
13
  readonly violated: boolean;
8
14
  readonly ruleTitle: string;
15
+ readonly ruleBody: string;
16
+ readonly ruleGlobs: ReadonlyArray<string>;
9
17
  readonly filePath: string;
10
18
  readonly violationProbability: number;
11
19
  readonly yesThreshold: PatdownYesThreshold;
20
+ readonly elapsedMs: number;
21
+ readonly evidence?: PatdownLintEvidenceSpan;
12
22
  };
13
- declare const PatdownOutput_base: Context.ServiceClass<PatdownOutput, "@patdown/cli/PatdownOutput", {
14
- readonly writeLintFailed: Effect.Effect<void>;
15
- readonly writeLintOk: Effect.Effect<void>;
23
+ /** Writers used by the PatdownOutput service. */
24
+ export type PatdownOutputWriters = {
25
+ readonly writeLintFailed: (elapsedMs?: number) => Effect.Effect<void>;
26
+ readonly writeLintOk: (elapsedMs?: number) => Effect.Effect<void>;
16
27
  readonly writeLintResult: (result: PatdownLintResult, verbose: boolean) => Effect.Effect<void>;
17
28
  readonly writeNoFilesMatched: (ruleTitle: string) => Effect.Effect<void>;
18
- readonly writeAnswer: (judgment: PatdownJudgment, verbose: boolean, yesThreshold?: PatdownYesThreshold) => Effect.Effect<void>;
29
+ readonly writeAnswer: (judgment: PatdownJudgment, verbose: boolean, yesThreshold?: PatdownYesThreshold, elapsedMs?: number) => Effect.Effect<void>;
19
30
  readonly writeRulesDocument: (document: PatdownRulesDocument) => Effect.Effect<void>;
20
- }>;
31
+ };
32
+ declare const PatdownOutput_base: Context.ServiceClass<PatdownOutput, "@patdown/cli/PatdownOutput", PatdownOutputWriters>;
21
33
  /** Swappable output service. Probability details are opt-in. */
22
34
  export declare class PatdownOutput extends PatdownOutput_base {
23
35
  }
24
- /** Default human-readable output, without provider-specific vocabulary. */
25
- export declare const PatdownOutputLive: Layer.Layer<PatdownOutput, never, never>;
36
+ /** One-line writers shared with GitHub Actions job logs. */
37
+ export declare const patdownStreamingHumanOutput: PatdownOutputWriters;
38
+ /**
39
+ * Local human output. Quiet mode streams one PASS/FAIL line per judgment. Verbose mode groups
40
+ * judgments into per-rule console blocks.
41
+ */
42
+ export declare const PatdownOutputLive: Layer.Layer<PatdownOutput>;
43
+ /** @deprecated Use patdownStreamingHumanOutput for one-line logs. */
44
+ export declare const patdownHumanOutput: PatdownOutputWriters;
26
45
  export {};
27
46
  //# sourceMappingURL=patdown-output.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"patdown-output.d.ts","sourceRoot":"","sources":["../src/patdown-output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAA8B,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AACrF,OAAO,EAAW,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAExD,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAE/E,+FAA+F;AAC/F,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAA;IACrC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAA;CAC1C,CAAA;;8BAmD2B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;0BACvB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;8BACf,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;kCAChE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;0BAClD,CACrB,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,OAAO,EAChB,YAAY,CAAC,EAAE,mBAAmB,KAC9B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;iCACK,CAAC,QAAQ,EAAE,oBAAoB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;;AAbtF,gEAAgE;AAChE,qBAAa,aAAc,SAAQ,kBAcF;CAAG;AAEpC,2EAA2E;AAC3E,eAAO,MAAM,iBAAiB,0CAQ5B,CAAA"}
1
+ {"version":3,"file":"patdown-output.d.ts","sourceRoot":"","sources":["../src/patdown-output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAA8B,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AACrF,OAAO,EAAW,OAAO,EAAE,MAAM,EAAE,KAAK,EAAO,MAAM,QAAQ,CAAA;AAM7D,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAG/E,8DAA8D;AAC9D,MAAM,MAAM,uBAAuB,GAAG;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED,+FAA+F;AAC/F,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAA;IACrC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAA;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAA;CAC3C,CAAA;AAoDD,iDAAiD;AACjD,MAAM,MAAM,oBAAoB,GAAG;IAClC,QAAQ,CAAC,eAAe,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACrE,QAAQ,CAAC,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACjE,QAAQ,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC9F,QAAQ,CAAC,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACxE,QAAQ,CAAC,WAAW,EAAE,CACrB,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,OAAO,EAChB,YAAY,CAAC,EAAE,mBAAmB,EAClC,SAAS,CAAC,EAAE,MAAM,KACd,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACxB,QAAQ,CAAC,kBAAkB,EAAE,CAAC,QAAQ,EAAE,oBAAoB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;CACpF,CAAA;;AAED,gEAAgE;AAChE,qBAAa,aAAc,SAAQ,kBAElC;CAAG;AAQJ,4DAA4D;AAC5D,eAAO,MAAM,2BAA2B,EAAE,oBA8BzC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,CA8ExD,CAAA;AAED,qEAAqE;AACrE,eAAO,MAAM,kBAAkB,sBAA8B,CAAA"}
@@ -1,22 +1,20 @@
1
1
  import { defaultPatdownYesThreshold } from '@patdown/rules';
2
- import { Console, Context, Effect, Layer } from 'effect';
2
+ import { Console, Context, Effect, Layer, Ref } from 'effect';
3
+ import { formatPatdownLintResultLine, formatPatdownRuleBlock, } from '#src/patdown-console-rule-blocks';
3
4
  import { patdownJudgmentIsYes } from '#src/patdown-judge';
4
- function formatPatdownProbability(probability, yesThreshold) {
5
- return `estimated P(yes): ${String(probability)}; cutoff: >${String(yesThreshold)}`;
5
+ import { formatPatdownProbabilityBar } from '#src/patdown-probability-bar';
6
+ function formatPatdownElapsedMs(elapsedMs) {
7
+ return `${String(elapsedMs)}ms`;
6
8
  }
7
- function formatPatdownAnswer(judgment, verbose, yesThreshold) {
9
+ function formatPatdownProbability(probability, yesThreshold, elapsedMs) {
10
+ return `${formatPatdownProbabilityBar(probability)} estimated P(yes): ${String(probability)}; cutoff: >${String(yesThreshold)}; elapsed: ${formatPatdownElapsedMs(elapsedMs)}`;
11
+ }
12
+ function formatPatdownAnswer(judgment, verbose, yesThreshold, elapsedMs) {
8
13
  const answer = patdownJudgmentIsYes(judgment, yesThreshold) ? 'yes' : 'no';
9
14
  return verbose
10
- ? `${answer} (${formatPatdownProbability(judgment.yesProbability, yesThreshold)})`
15
+ ? `${answer} (${formatPatdownProbability(judgment.yesProbability, yesThreshold, elapsedMs)})`
11
16
  : answer;
12
17
  }
13
- function formatPatdownLintResult(result, verbose) {
14
- const verdict = result.violated ? 'FAIL' : 'PASS';
15
- const line = `${verdict} ${result.filePath}: ${result.ruleTitle}`;
16
- return verbose
17
- ? `${line} (${formatPatdownProbability(result.violationProbability, result.yesThreshold)})`
18
- : line;
19
- }
20
18
  function formatPatdownRulesDocument(document) {
21
19
  const lines = [
22
20
  `patdown: ${String(document.patdownRules.length)} rules from ${document.patdownRulesFilePath}`,
@@ -34,12 +32,87 @@ function formatPatdownRulesDocument(document) {
34
32
  /** Swappable output service. Probability details are opt-in. */
35
33
  export class PatdownOutput extends Context.Service()('@patdown/cli/PatdownOutput') {
36
34
  }
37
- /** Default human-readable output, without provider-specific vocabulary. */
38
- export const PatdownOutputLive = Layer.succeed(PatdownOutput, {
39
- writeLintFailed: Console.log('patdown: failed'),
40
- writeLintOk: Console.log('patdown: ok'),
41
- writeLintResult: (result, verbose) => Console.log(formatPatdownLintResult(result, verbose)),
35
+ function flushPatdownConsoleRuleBlock(buffer) {
36
+ if (buffer.ruleTitle === null)
37
+ return Effect.void;
38
+ return Console.log(formatPatdownRuleBlock(buffer.ruleTitle, buffer.results));
39
+ }
40
+ /** One-line writers shared with GitHub Actions job logs. */
41
+ export const patdownStreamingHumanOutput = {
42
+ writeLintFailed: (elapsedMs) => Console.log(elapsedMs === undefined
43
+ ? 'patdown: failed'
44
+ : `patdown: failed (elapsed: ${formatPatdownElapsedMs(elapsedMs)})`),
45
+ writeLintOk: (elapsedMs) => Console.log(elapsedMs === undefined
46
+ ? 'patdown: passed'
47
+ : `patdown: passed (elapsed: ${formatPatdownElapsedMs(elapsedMs)})`),
48
+ writeLintResult: (result, verbose) => Console.log(verbose
49
+ ? `${formatPatdownLintResultLine(result)} (${formatPatdownProbability(result.violationProbability, result.yesThreshold, result.elapsedMs)})`
50
+ : formatPatdownLintResultLine(result)),
42
51
  writeNoFilesMatched: (title) => Console.log(`patdown: no files matched ${title}`),
43
- writeAnswer: (judgment, verbose, yesThreshold = defaultPatdownYesThreshold) => Console.log(formatPatdownAnswer(judgment, verbose, yesThreshold)),
52
+ writeAnswer: (judgment, verbose, yesThreshold = defaultPatdownYesThreshold, elapsedMs = 0) => Console.log(formatPatdownAnswer(judgment, verbose, yesThreshold, elapsedMs)),
44
53
  writeRulesDocument: (document) => Console.log(formatPatdownRulesDocument(document)),
45
- });
54
+ };
55
+ /**
56
+ * Local human output. Quiet mode streams one PASS/FAIL line per judgment. Verbose mode groups
57
+ * judgments into per-rule console blocks.
58
+ */
59
+ export const PatdownOutputLive = Layer.effect(PatdownOutput, Effect.gen(function* () {
60
+ const buffer = yield* Ref.make({
61
+ ruleTitle: null,
62
+ results: [],
63
+ });
64
+ const flush = () => Effect.gen(function* () {
65
+ const current = yield* Ref.get(buffer);
66
+ yield* flushPatdownConsoleRuleBlock(current);
67
+ yield* Ref.set(buffer, { ruleTitle: null, results: [] });
68
+ });
69
+ const writers = {
70
+ writeAnswer: patdownStreamingHumanOutput.writeAnswer,
71
+ writeRulesDocument: patdownStreamingHumanOutput.writeRulesDocument,
72
+ writeLintResult: (result, verbose) => {
73
+ if (!verbose) {
74
+ return patdownStreamingHumanOutput.writeLintResult(result, false);
75
+ }
76
+ return Effect.gen(function* () {
77
+ const current = yield* Ref.get(buffer);
78
+ if (current.ruleTitle !== null && current.ruleTitle !== result.ruleTitle) {
79
+ yield* flushPatdownConsoleRuleBlock(current);
80
+ yield* Ref.set(buffer, {
81
+ ruleTitle: result.ruleTitle,
82
+ results: [result],
83
+ });
84
+ return;
85
+ }
86
+ yield* Ref.set(buffer, {
87
+ ruleTitle: result.ruleTitle,
88
+ results: [...current.results, result],
89
+ });
90
+ });
91
+ },
92
+ writeNoFilesMatched: (title) => Effect.gen(function* () {
93
+ yield* flush();
94
+ yield* Console.log(formatPatdownRuleBlock(title, []));
95
+ }),
96
+ writeLintOk: (elapsedMs) => Effect.gen(function* () {
97
+ const current = yield* Ref.get(buffer);
98
+ const hadVerboseBlock = current.ruleTitle !== null;
99
+ yield* flush();
100
+ if (hadVerboseBlock) {
101
+ yield* Console.log('');
102
+ }
103
+ yield* patdownStreamingHumanOutput.writeLintOk(elapsedMs);
104
+ }),
105
+ writeLintFailed: (elapsedMs) => Effect.gen(function* () {
106
+ const current = yield* Ref.get(buffer);
107
+ const hadVerboseBlock = current.ruleTitle !== null;
108
+ yield* flush();
109
+ if (hadVerboseBlock) {
110
+ yield* Console.log('');
111
+ }
112
+ yield* patdownStreamingHumanOutput.writeLintFailed(elapsedMs);
113
+ }),
114
+ };
115
+ return writers;
116
+ }));
117
+ /** @deprecated Use patdownStreamingHumanOutput for one-line logs. */
118
+ export const patdownHumanOutput = patdownStreamingHumanOutput;
@@ -0,0 +1,3 @@
1
+ /** Ten-cell shade bar for estimated P(yes). Search for ▓ ▒ ░ to find the glyphs. */
2
+ export declare function formatPatdownProbabilityBar(probability: number): string;
3
+ //# sourceMappingURL=patdown-probability-bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patdown-probability-bar.d.ts","sourceRoot":"","sources":["../src/patdown-probability-bar.ts"],"names":[],"mappings":"AAgBA,oFAAoF;AACpF,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAqBvE"}
@@ -0,0 +1,29 @@
1
+ const patdownProbabilityBarFilled = '▓';
2
+ const patdownProbabilityBarPartial = '▒';
3
+ const patdownProbabilityBarEmpty = '░';
4
+ const patdownProbabilityBarWidth = 10;
5
+ function clampPatdownProbability(probability) {
6
+ if (probability <= 0)
7
+ return 0;
8
+ if (probability >= 1)
9
+ return 1;
10
+ return probability;
11
+ }
12
+ /** Ten-cell shade bar for estimated P(yes). Search for ▓ ▒ ░ to find the glyphs. */
13
+ export function formatPatdownProbabilityBar(probability) {
14
+ const filledCells = clampPatdownProbability(probability) * patdownProbabilityBarWidth;
15
+ const cells = [];
16
+ for (let index = 0; index < patdownProbabilityBarWidth; index += 1) {
17
+ const cellFill = filledCells - index;
18
+ if (cellFill >= 1) {
19
+ cells.push(patdownProbabilityBarFilled);
20
+ continue;
21
+ }
22
+ if (cellFill >= 0.5) {
23
+ cells.push(patdownProbabilityBarPartial);
24
+ continue;
25
+ }
26
+ cells.push(patdownProbabilityBarEmpty);
27
+ }
28
+ return cells.join('');
29
+ }
@@ -6,7 +6,9 @@ import { type PatdownOutput } from '#src/patdown-output';
6
6
  import type { PatdownRuleSourceLayer } from '#src/patdown-rule-source-adapter';
7
7
  /**
8
8
  * Returns a runnable CLI Effect. A supplied rule source disables discovery; argv excludes node and
9
- * script. The third and fourth arguments replace the judge and output layers independently.
9
+ * script. The third and fourth arguments replace the judge and output layers independently. Without
10
+ * an output layer, GitHub Actions summary/annotations turn on when GITHUB_ACTIONS and
11
+ * GITHUB_STEP_SUMMARY are set, unless argv includes --no-github.
10
12
  */
11
13
  export declare function runPatdownCli(ruleSourceLayer?: PatdownRuleSourceLayer, argv?: readonly string[], judgeLayer?: Layer.Layer<PatdownJudge, PatdownJudgeFailed>, outputLayer?: Layer.Layer<PatdownOutput>): Effect.Effect<void, PatdownRulesLoadFailed | PatdownJudgeFailed | CliError>;
12
14
  //# sourceMappingURL=run-patdown-cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-patdown-cli.d.ts","sourceRoot":"","sources":["../src/run-patdown-cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAiC,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAC3F,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAEtC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AAI5D,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC1E,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAC3E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AAG9E;;;GAGG;AACH,wBAAgB,aAAa,CAC5B,eAAe,CAAC,EAAE,sBAAsB,EACxC,IAAI,GAAE,SAAS,MAAM,EAA0B,EAC/C,UAAU,GAAE,KAAK,CAAC,KAAK,CAAC,YAAY,EAAE,kBAAkB,CAAqB,EAC7E,WAAW,GAAE,KAAK,CAAC,KAAK,CAAC,aAAa,CAAqB,GACzD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,sBAAsB,GAAG,kBAAkB,GAAG,QAAQ,CAAC,CAS7E"}
1
+ {"version":3,"file":"run-patdown-cli.d.ts","sourceRoot":"","sources":["../src/run-patdown-cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAiC,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAC3F,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAEtC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AAM5D,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC1E,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAC3E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AAO9E;;;;;GAKG;AACH,wBAAgB,aAAa,CAC5B,eAAe,CAAC,EAAE,sBAAsB,EACxC,IAAI,GAAE,SAAS,MAAM,EAA0B,EAC/C,UAAU,GAAE,KAAK,CAAC,KAAK,CAAC,YAAY,EAAE,kBAAkB,CAAqB,EAC7E,WAAW,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,GACtC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,sBAAsB,GAAG,kBAAkB,GAAG,QAAQ,CAAC,CAmB7E"}
@@ -4,14 +4,27 @@ import { Effect, Layer } from 'effect';
4
4
  import { Command } from 'effect/unstable/cli';
5
5
  import { makePatdownCommand } from '#src/cli';
6
6
  import { patdownCliVersion } from '#src/patdown-cli-version';
7
+ import { patdownGitHubActionsIsEnabled } from '#src/patdown-github-actions-env';
8
+ import { PatdownGitHubActionsOutputLive } from '#src/patdown-github-actions-output';
7
9
  import { PatdownOutputLive } from '#src/patdown-output';
8
10
  import { TypeSafeJudgeLive } from '#src/typesafe-judge';
11
+ function argvDisablesPatdownGitHubActions(argv) {
12
+ return argv.includes('--no-github');
13
+ }
9
14
  /**
10
15
  * Returns a runnable CLI Effect. A supplied rule source disables discovery; argv excludes node and
11
- * script. The third and fourth arguments replace the judge and output layers independently.
16
+ * script. The third and fourth arguments replace the judge and output layers independently. Without
17
+ * an output layer, GitHub Actions summary/annotations turn on when GITHUB_ACTIONS and
18
+ * GITHUB_STEP_SUMMARY are set, unless argv includes --no-github.
12
19
  */
13
- export function runPatdownCli(ruleSourceLayer, argv = process.argv.slice(2), judgeLayer = TypeSafeJudgeLive, outputLayer = PatdownOutputLive) {
20
+ export function runPatdownCli(ruleSourceLayer, argv = process.argv.slice(2), judgeLayer = TypeSafeJudgeLive, outputLayer) {
14
21
  const command = makePatdownCommand(ruleSourceLayer === undefined);
15
22
  const source = ruleSourceLayer ?? MarkdownPatdownRuleSourceLive;
16
- return Command.runWith(command, { version: patdownCliVersion })(argv).pipe(Effect.provide(Layer.mergeAll(source, judgeLayer, outputLayer).pipe(Layer.provideMerge(NodeServices.layer))));
23
+ return Effect.gen(function* () {
24
+ const selectedOutput = outputLayer ??
25
+ (argvDisablesPatdownGitHubActions(argv) || !(yield* patdownGitHubActionsIsEnabled)
26
+ ? PatdownOutputLive
27
+ : PatdownGitHubActionsOutputLive);
28
+ yield* Command.runWith(command, { version: patdownCliVersion })(argv).pipe(Effect.provide(Layer.mergeAll(source, judgeLayer, selectedOutput).pipe(Layer.provideMerge(NodeServices.layer))));
29
+ });
17
30
  }
@@ -1,5 +1,6 @@
1
1
  import { Layer } from 'effect';
2
2
  import { PatdownJudge } from '#src/patdown-judge';
3
+ export { patdownEvidenceMinConfidence } from '#src/patdown-evidence-regions';
3
4
  /**
4
5
  * Temporary TypeSafe backend. Replace this layer with Effect Decision/DecisionModel when available;
5
6
  * see issue #1.
@@ -1 +1 @@
1
- {"version":3,"file":"typesafe-judge.d.ts","sourceRoot":"","sources":["../src/typesafe-judge.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAA;AAGtC,OAAO,EAAE,YAAY,EAA4C,MAAM,oBAAoB,CAAA;AAE3F;;;GAGG;AACH,eAAO,MAAM,iBAAiB,yCAcS,CAAA"}
1
+ {"version":3,"file":"typesafe-judge.d.ts","sourceRoot":"","sources":["../src/typesafe-judge.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAA;AAOtC,OAAO,EACN,YAAY,EAIZ,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAA;AAE5E;;;GAGG;AACH,eAAO,MAAM,iBAAiB,yCAmCS,CAAA"}
@@ -1,7 +1,9 @@
1
1
  import { JevSystemOne, JevSystemOneLive } from '@patdown/jev';
2
2
  import { Effect, Layer } from 'effect';
3
3
  import { FetchHttpClient } from 'effect/unstable/http';
4
- import { PatdownJudge, PatdownJudgeFailed } from '#src/patdown-judge';
4
+ import { patdownEvidenceMinConfidence, patdownEvidenceNoMatchChoice, } from '#src/patdown-evidence-regions';
5
+ import { PatdownJudge, PatdownJudgeFailed, } from '#src/patdown-judge';
6
+ export { patdownEvidenceMinConfidence } from '#src/patdown-evidence-regions';
5
7
  /**
6
8
  * Temporary TypeSafe backend. Replace this layer with Effect Decision/DecisionModel when available;
7
9
  * see issue #1.
@@ -10,5 +12,17 @@ export const TypeSafeJudgeLive = Layer.effect(PatdownJudge, Effect.gen(function*
10
12
  const client = yield* JevSystemOne;
11
13
  return {
12
14
  ask: (question, inputText) => client.askNoul(question, inputText).pipe(Effect.map((answer) => ({ yesProbability: answer.noul })), Effect.mapError((error) => new PatdownJudgeFailed({ message: error.message })), Effect.provide(FetchHttpClient.layer)),
15
+ locateEvidence: (question, inputText, criteria) => client.askChoice(question, inputText, criteria).pipe(Effect.map((answer) => {
16
+ if (answer.choice === patdownEvidenceNoMatchChoice())
17
+ return null;
18
+ if (answer.confidence < patdownEvidenceMinConfidence)
19
+ return null;
20
+ if (!(answer.choice in criteria))
21
+ return null;
22
+ return {
23
+ regionId: answer.choice,
24
+ confidence: answer.confidence,
25
+ };
26
+ }), Effect.mapError((error) => new PatdownJudgeFailed({ message: error.message })), Effect.provide(FetchHttpClient.layer)),
13
27
  };
14
28
  })).pipe(Layer.provide(JevSystemOneLive));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patdown",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "Standalone CLI that lints a tree against fuzzy markdown rules",
5
5
  "homepage": "https://github.com/tyler-dot-earth/patdown",
6
6
  "bugs": {
@@ -48,8 +48,8 @@
48
48
  "@effect/platform-node": "4.0.0-rc.112",
49
49
  "effect": "4.0.0-rc.112",
50
50
  "import-meta-resolve": "4.2.0",
51
- "@patdown/jev": "0.3.1",
52
- "@patdown/rules": "0.3.1"
51
+ "@patdown/jev": "0.5.0",
52
+ "@patdown/rules": "0.5.0"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@effect/language-service": "0.87.2",