@rigour-labs/core 6.8.1 → 6.9.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/goal/goal.d.ts +34 -0
  2. package/dist/goal/goal.js +188 -0
  3. package/dist/goal/hook.d.ts +7 -0
  4. package/dist/goal/hook.js +100 -0
  5. package/dist/hooks/stop-review.js +4 -1
  6. package/dist/index.d.ts +5 -0
  7. package/dist/index.js +4 -0
  8. package/dist/outcomes/outcome.d.ts +80 -0
  9. package/dist/outcomes/outcome.js +161 -0
  10. package/dist/outcomes/run.d.ts +26 -0
  11. package/dist/outcomes/run.js +63 -0
  12. package/dist/review/backtest-init.d.ts +9 -4
  13. package/dist/review/backtest-init.js +2 -2
  14. package/dist/review/quiet.js +2 -1
  15. package/dist/review/review.d.ts +5 -0
  16. package/dist/review/review.js +23 -2
  17. package/dist/review/reviewer/context.d.ts +11 -0
  18. package/dist/review/reviewer/context.js +10 -4
  19. package/dist/review/reviewer/prompt.d.ts +8 -1
  20. package/dist/review/reviewer/prompt.js +21 -2
  21. package/dist/review/reviewer/verdict.d.ts +12 -1
  22. package/dist/review/reviewer/verdict.js +8 -1
  23. package/dist/review/reviewer.d.ts +4 -0
  24. package/dist/review/reviewer.js +14 -6
  25. package/dist/review-learning/lessons.d.ts +11 -3
  26. package/dist/review-learning/lessons.js +3 -0
  27. package/dist/review-learning/outcome-evidence.d.ts +41 -0
  28. package/dist/review-learning/outcome-evidence.js +72 -0
  29. package/dist/review-learning/outcomes.d.ts +8 -0
  30. package/dist/review-learning/outcomes.js +11 -5
  31. package/dist/settings.d.ts +2 -0
  32. package/dist/switches.d.ts +640 -0
  33. package/dist/switches.js +36 -0
  34. package/dist/task/thread.d.ts +9 -1
  35. package/dist/task/thread.js +33 -1
  36. package/dist/templates/universal-config.js +4 -0
  37. package/dist/types/fix-packet.d.ts +1 -1
  38. package/dist/types/index.d.ts +56 -0
  39. package/dist/types/index.js +18 -0
  40. package/package.json +6 -6
@@ -1,6 +1,6 @@
1
1
  /** Under the repository's git folder (the common one, shared by every worktree). */
2
2
  export declare const THREADS_DIR = "rigour/threads";
3
- export type TaskEventKind = 'edit-check' | 'stop-review' | 'push' | 'review' | 'brief';
3
+ export type TaskEventKind = 'edit-check' | 'stop-review' | 'push' | 'review' | 'brief' | 'goal' | 'merge' | 'outcome';
4
4
  export interface TaskEvent {
5
5
  kind: TaskEventKind;
6
6
  /** The agent session it happened in, when a hook knows it. */
@@ -29,6 +29,14 @@ export declare function taskOf(cwd: string): {
29
29
  } | undefined;
30
30
  /** Appends one event to the checkout's task thread. Best effort: a thread never breaks the hook or command it runs in. */
31
31
  export declare function appendTaskEvent(cwd: string, event: TaskEvent): ThreadEvent | undefined;
32
+ /** Every thread's events of one kind, oldest first: what the outcome loop reads across tasks (the reviews that found a lesson repeated). */
33
+ export declare function eventsOfKind(cwd: string, kind: TaskEventKind): ThreadEvent[];
34
+ /**
35
+ * Appends one event to a named branch's thread, under the task its own events carry: what happened to a pull request
36
+ * after it merged, recorded from wherever the outcome was read. Only a thread that already exists is written: a branch
37
+ * this machine never worked on gets none. Best effort, like appendTaskEvent.
38
+ */
39
+ export declare function appendBranchEvent(cwd: string, branch: string, event: TaskEvent): ThreadEvent | undefined;
32
40
  /**
33
41
  * The thread for a key, oldest first: a ticket (`PROJ-123`, every branch whose events carry it, from their first
34
42
  * event), a branch name, a pull request (`#42` or `42`: the branches a review of it ran on), or nothing for the
@@ -99,6 +99,35 @@ export function appendTaskEvent(cwd, event) {
99
99
  return undefined;
100
100
  }
101
101
  }
102
+ /** Every thread's events of one kind, oldest first: what the outcome loop reads across tasks (the reviews that found a lesson repeated). */
103
+ export function eventsOfKind(cwd, kind) {
104
+ const dir = threadsDir(cwd);
105
+ if (!dir)
106
+ return [];
107
+ return listThreads(dir).flatMap(file => readEvents(path.join(dir, file))).filter(e => e.kind === kind).sort(byTime);
108
+ }
109
+ /**
110
+ * Appends one event to a named branch's thread, under the task its own events carry: what happened to a pull request
111
+ * after it merged, recorded from wherever the outcome was read. Only a thread that already exists is written: a branch
112
+ * this machine never worked on gets none. Best effort, like appendTaskEvent.
113
+ */
114
+ export function appendBranchEvent(cwd, branch, event) {
115
+ try {
116
+ const dir = threadsDir(cwd);
117
+ if (!dir || !branch)
118
+ return undefined;
119
+ const file = path.join(dir, branchFile(branch));
120
+ const last = readEvents(file).at(-1);
121
+ if (!last)
122
+ return undefined;
123
+ const line = { at: new Date().toISOString(), task: last.task, branch, ...event };
124
+ fs.appendFileSync(file, JSON.stringify(line) + '\n');
125
+ return line;
126
+ }
127
+ catch {
128
+ return undefined;
129
+ }
130
+ }
102
131
  /**
103
132
  * The thread for a key, oldest first: a ticket (`PROJ-123`, every branch whose events carry it, from their first
104
133
  * event), a branch name, a pull request (`#42` or `42`: the branches a review of it ran on), or nothing for the
@@ -184,7 +213,10 @@ function describe(e) {
184
213
  : e.kind === 'stop-review' ? (e.blocked ? `blocked: ${num(e.blocking)} to fix` : 'passed')
185
214
  : e.kind === 'push' ? (e.passed === false ? `blocked: ${num(e.failed)} check(s) failed` : 'passed')
186
215
  : e.kind === 'review' ? `${String(e.outcome)}, ${num(e.blocking)} blocking, ${num(e.should_fix)} should-fix${e.pr ? ` on #${e.pr}` : ''}`
187
- : e.kind === 'brief' ? `${num(e.items)} item(s) briefed` : '';
216
+ : e.kind === 'brief' ? `${num(e.items)} item(s) briefed`
217
+ : e.kind === 'goal' ? `at ${String(e.moment)}: ${e.declared ? `${num(e.blocks)} goal block(s)` : 'the description declares no goal'}`
218
+ : e.kind === 'merge' ? `#${num(e.pr)} merged as ${String(e.merge_sha).slice(0, 9)}`
219
+ : e.kind === 'outcome' ? `#${num(e.pr)} settled: CI ${String(e.ci)}, ${num(e.fixes)} fix(es) in ${num(e.follow_ups)} later commit(s)${e.reverted ? ', reverted' : ''}` : '';
188
220
  return [what, who ? `(${who})` : '', e.head ? `@${String(e.head).slice(0, 9)}` : ''].filter(Boolean).join(' ');
189
221
  }
190
222
  function readEvents(file) {
@@ -279,9 +279,13 @@ export const UNIVERSAL_CONFIG = {
279
279
  enabled: true,
280
280
  max_items: 10,
281
281
  },
282
+ learning: {
283
+ outcomes: { mode: 'off', window_days: 30, demote_after: 2 },
284
+ },
282
285
  review: {
283
286
  include_heuristics: false,
284
287
  show_preexisting: false,
288
+ goal: 'off',
285
289
  reviewer: {
286
290
  enabled: false,
287
291
  on_push: 'background',
@@ -194,8 +194,8 @@ export declare const FixPacketV2Schema: z.ZodObject<{
194
194
  allowed_dependencies?: string[] | undefined;
195
195
  }>>>;
196
196
  }, "strip", z.ZodTypeAny, {
197
- version: 3;
198
197
  goal: string;
198
+ version: 3;
199
199
  failed_gates: string[];
200
200
  violations: {
201
201
  id: string;
@@ -2412,12 +2412,50 @@ export declare const ConfigSchema: z.ZodObject<{
2412
2412
  enabled?: boolean | undefined;
2413
2413
  max_items?: number | undefined;
2414
2414
  }>>>;
2415
+ /** What Rigour learns from, beyond the reviews themselves. */
2416
+ learning: z.ZodDefault<z.ZodOptional<z.ZodObject<{
2417
+ /** What happened after each pull request merged (outcomes/outcome.ts): CI on the merge commit, later commits on its files, a revert. */
2418
+ outcomes: z.ZodDefault<z.ZodOptional<z.ZodObject<{
2419
+ /** off, on, or required (no person, environment variable or flag may turn it off). */
2420
+ mode: z.ZodDefault<z.ZodOptional<z.ZodEnum<["off", "on", "required"]>>>;
2421
+ /** How long after a merge later commits count, in days. */
2422
+ window_days: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
2423
+ /** How many later pull requests, independent and settled clean after a review found them repeating a lesson, demote it (review-learning/outcome-evidence.ts). */
2424
+ demote_after: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
2425
+ }, "strip", z.ZodTypeAny, {
2426
+ mode: "off" | "on" | "required";
2427
+ window_days: number;
2428
+ demote_after: number;
2429
+ }, {
2430
+ mode?: "off" | "on" | "required" | undefined;
2431
+ window_days?: number | undefined;
2432
+ demote_after?: number | undefined;
2433
+ }>>>;
2434
+ }, "strip", z.ZodTypeAny, {
2435
+ outcomes: {
2436
+ mode: "off" | "on" | "required";
2437
+ window_days: number;
2438
+ demote_after: number;
2439
+ };
2440
+ }, {
2441
+ outcomes?: {
2442
+ mode?: "off" | "on" | "required" | undefined;
2443
+ window_days?: number | undefined;
2444
+ demote_after?: number | undefined;
2445
+ } | undefined;
2446
+ }>>>;
2415
2447
  /** rigour review / rigour_review / the PR bot / the stop hook. */
2416
2448
  review: z.ZodDefault<z.ZodOptional<z.ZodObject<{
2417
2449
  /** Let heuristic gates decide the verdict too; by default only findings that prove a defect do (quiet.ts). */
2418
2450
  include_heuristics: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
2419
2451
  /** Also report findings the base already had; by default only what the change introduced is (baseline.ts). */
2420
2452
  show_preexisting: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
2453
+ /**
2454
+ * Check the change against the goal its pull request's description declares (goal/goal.ts): a changed file
2455
+ * outside the declared Scope or inside Out of scope, a "Done when" item naming a file or symbol the change never
2456
+ * touches. Deterministic; a finding blocks. `required` stops a person, the environment or a flag turning it off.
2457
+ */
2458
+ goal: z.ZodDefault<z.ZodOptional<z.ZodEnum<["off", "on", "required"]>>>;
2421
2459
  /** The GitHub account whose token fetches the pull request's previous review (`gh auth token --user`). */
2422
2460
  github_account: z.ZodOptional<z.ZodString>;
2423
2461
  /** The reviewer (review/reviewer.ts): the person's own coding-agent CLIs, headless and read-only. `enabled` runs it at push; `rigour review --reviewer` runs it on request. */
@@ -2567,6 +2605,7 @@ export declare const ConfigSchema: z.ZodObject<{
2567
2605
  }, "strip", z.ZodTypeAny, {
2568
2606
  include_heuristics: boolean;
2569
2607
  show_preexisting: boolean;
2608
+ goal: "off" | "on" | "required";
2570
2609
  reviewer: {
2571
2610
  enabled: boolean;
2572
2611
  mode: "single" | "cross" | "full";
@@ -2600,6 +2639,7 @@ export declare const ConfigSchema: z.ZodObject<{
2600
2639
  }, {
2601
2640
  include_heuristics?: boolean | undefined;
2602
2641
  show_preexisting?: boolean | undefined;
2642
+ goal?: "off" | "on" | "required" | undefined;
2603
2643
  github_account?: string | undefined;
2604
2644
  reviewer?: {
2605
2645
  enabled?: boolean | undefined;
@@ -2890,9 +2930,17 @@ export declare const ConfigSchema: z.ZodObject<{
2890
2930
  enabled: boolean;
2891
2931
  max_items: number;
2892
2932
  };
2933
+ learning: {
2934
+ outcomes: {
2935
+ mode: "off" | "on" | "required";
2936
+ window_days: number;
2937
+ demote_after: number;
2938
+ };
2939
+ };
2893
2940
  review: {
2894
2941
  include_heuristics: boolean;
2895
2942
  show_preexisting: boolean;
2943
+ goal: "off" | "on" | "required";
2896
2944
  reviewer: {
2897
2945
  enabled: boolean;
2898
2946
  mode: "single" | "cross" | "full";
@@ -3186,9 +3234,17 @@ export declare const ConfigSchema: z.ZodObject<{
3186
3234
  enabled?: boolean | undefined;
3187
3235
  max_items?: number | undefined;
3188
3236
  } | undefined;
3237
+ learning?: {
3238
+ outcomes?: {
3239
+ mode?: "off" | "on" | "required" | undefined;
3240
+ window_days?: number | undefined;
3241
+ demote_after?: number | undefined;
3242
+ } | undefined;
3243
+ } | undefined;
3189
3244
  review?: {
3190
3245
  include_heuristics?: boolean | undefined;
3191
3246
  show_preexisting?: boolean | undefined;
3247
+ goal?: "off" | "on" | "required" | undefined;
3192
3248
  github_account?: string | undefined;
3193
3249
  reviewer?: {
3194
3250
  enabled?: boolean | undefined;
@@ -372,12 +372,30 @@ export const ConfigSchema = z.object({
372
372
  /** At most this many items, never more than 10. */
373
373
  max_items: z.number().int().min(1).max(10).optional().default(10),
374
374
  }).optional().default({}),
375
+ /** What Rigour learns from, beyond the reviews themselves. */
376
+ learning: z.object({
377
+ /** What happened after each pull request merged (outcomes/outcome.ts): CI on the merge commit, later commits on its files, a revert. */
378
+ outcomes: z.object({
379
+ /** off, on, or required (no person, environment variable or flag may turn it off). */
380
+ mode: z.enum(['off', 'on', 'required']).optional().default('off'),
381
+ /** How long after a merge later commits count, in days. */
382
+ window_days: z.number().int().min(7).max(90).optional().default(30),
383
+ /** How many later pull requests, independent and settled clean after a review found them repeating a lesson, demote it (review-learning/outcome-evidence.ts). */
384
+ demote_after: z.number().int().min(2).optional().default(2),
385
+ }).optional().default({}),
386
+ }).optional().default({}),
375
387
  /** rigour review / rigour_review / the PR bot / the stop hook. */
376
388
  review: z.object({
377
389
  /** Let heuristic gates decide the verdict too; by default only findings that prove a defect do (quiet.ts). */
378
390
  include_heuristics: z.boolean().optional().default(false),
379
391
  /** Also report findings the base already had; by default only what the change introduced is (baseline.ts). */
380
392
  show_preexisting: z.boolean().optional().default(false),
393
+ /**
394
+ * Check the change against the goal its pull request's description declares (goal/goal.ts): a changed file
395
+ * outside the declared Scope or inside Out of scope, a "Done when" item naming a file or symbol the change never
396
+ * touches. Deterministic; a finding blocks. `required` stops a person, the environment or a flag turning it off.
397
+ */
398
+ goal: z.enum(['off', 'on', 'required']).optional().default('off'),
381
399
  /** The GitHub account whose token fetches the pull request's previous review (`gh auth token --user`). */
382
400
  github_account: z.string().optional(),
383
401
  /** The reviewer (review/reviewer.ts): the person's own coding-agent CLIs, headless and read-only. `enabled` runs it at push; `rigour review --reviewer` runs it on request. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigour-labs/core",
3
- "version": "6.8.1",
3
+ "version": "6.9.0-rc.2",
4
4
  "description": "Rigour's review engine: deterministic gates on changed lines, rules and lessons learned from your team's fixes, and per-check precision from what you fix versus dismiss, across TypeScript, JavaScript, Python, Go, Ruby and C#.",
5
5
  "engines": {
6
6
  "node": ">=22.13"
@@ -75,11 +75,11 @@
75
75
  "@anthropic-ai/sdk": "^0.132.1",
76
76
  "pg": "^8.16.3",
77
77
  "openai": "^5.23.2",
78
- "@rigour-labs/brain-darwin-arm64": "6.8.1",
79
- "@rigour-labs/brain-linux-arm64": "6.8.1",
80
- "@rigour-labs/brain-darwin-x64": "6.8.1",
81
- "@rigour-labs/brain-linux-x64": "6.8.1",
82
- "@rigour-labs/brain-win-x64": "6.8.1"
78
+ "@rigour-labs/brain-darwin-arm64": "6.9.0-rc.2",
79
+ "@rigour-labs/brain-darwin-x64": "6.9.0-rc.2",
80
+ "@rigour-labs/brain-linux-arm64": "6.9.0-rc.2",
81
+ "@rigour-labs/brain-linux-x64": "6.9.0-rc.2",
82
+ "@rigour-labs/brain-win-x64": "6.9.0-rc.2"
83
83
  },
84
84
  "devDependencies": {
85
85
  "@types/fs-extra": "^11.0.4",