@loopover/engine 1.0.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 (272) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/LICENSE +661 -0
  3. package/README.md +676 -0
  4. package/dist/advisory/gate-advisory.d.ts +151 -0
  5. package/dist/advisory/gate-advisory.js +512 -0
  6. package/dist/ai-policy-map.d.ts +97 -0
  7. package/dist/ai-policy-map.js +377 -0
  8. package/dist/ams-policy-spec.d.ts +56 -0
  9. package/dist/ams-policy-spec.js +165 -0
  10. package/dist/calibration-dashboard.d.ts +23 -0
  11. package/dist/calibration-dashboard.js +65 -0
  12. package/dist/calibration-trend.d.ts +40 -0
  13. package/dist/calibration-trend.js +60 -0
  14. package/dist/contributor-fit.d.ts +24 -0
  15. package/dist/contributor-fit.js +50 -0
  16. package/dist/discovery-index-contract.d.ts +74 -0
  17. package/dist/discovery-index-contract.js +184 -0
  18. package/dist/discovery-soft-claim.d.ts +35 -0
  19. package/dist/discovery-soft-claim.js +50 -0
  20. package/dist/duplicate-winner.d.ts +57 -0
  21. package/dist/duplicate-winner.js +98 -0
  22. package/dist/feasibility.d.ts +27 -0
  23. package/dist/feasibility.js +86 -0
  24. package/dist/finding-severity-calibration.d.ts +116 -0
  25. package/dist/finding-severity-calibration.js +457 -0
  26. package/dist/fleet-run-manifest.d.ts +41 -0
  27. package/dist/fleet-run-manifest.js +151 -0
  28. package/dist/focus-manifest/guidance.d.ts +21 -0
  29. package/dist/focus-manifest/guidance.js +222 -0
  30. package/dist/focus-manifest.d.ts +826 -0
  31. package/dist/focus-manifest.js +2730 -0
  32. package/dist/gate-verdict-calibration.d.ts +111 -0
  33. package/dist/gate-verdict-calibration.js +411 -0
  34. package/dist/github/constants.d.ts +1 -0
  35. package/dist/github/constants.js +1 -0
  36. package/dist/github/sanitize-public-comment.d.ts +1 -0
  37. package/dist/github/sanitize-public-comment.js +26 -0
  38. package/dist/goal-model.d.ts +7 -0
  39. package/dist/goal-model.js +87 -0
  40. package/dist/governor/action-mode.d.ts +55 -0
  41. package/dist/governor/action-mode.js +74 -0
  42. package/dist/governor/budget-cap.d.ts +49 -0
  43. package/dist/governor/budget-cap.js +34 -0
  44. package/dist/governor/chokepoint.d.ts +58 -0
  45. package/dist/governor/chokepoint.js +269 -0
  46. package/dist/governor/kill-switch.d.ts +38 -0
  47. package/dist/governor/kill-switch.js +62 -0
  48. package/dist/governor/rate-limit.d.ts +40 -0
  49. package/dist/governor/rate-limit.js +63 -0
  50. package/dist/governor/reputation-throttle.d.ts +50 -0
  51. package/dist/governor/reputation-throttle.js +94 -0
  52. package/dist/governor/run-halt.d.ts +39 -0
  53. package/dist/governor/run-halt.js +83 -0
  54. package/dist/governor/self-plagiarism.d.ts +47 -0
  55. package/dist/governor/self-plagiarism.js +200 -0
  56. package/dist/governor/write-rate-limit.d.ts +52 -0
  57. package/dist/governor/write-rate-limit.js +132 -0
  58. package/dist/governor-ledger.d.ts +25 -0
  59. package/dist/governor-ledger.js +91 -0
  60. package/dist/index.d.ts +99 -0
  61. package/dist/index.js +120 -0
  62. package/dist/issue-plan-decomposition.d.ts +18 -0
  63. package/dist/issue-plan-decomposition.js +56 -0
  64. package/dist/issue-rag-query.d.ts +12 -0
  65. package/dist/issue-rag-query.js +35 -0
  66. package/dist/local-scorer.d.ts +34 -0
  67. package/dist/local-scorer.js +36 -0
  68. package/dist/metadata-best-min-score.d.ts +9 -0
  69. package/dist/metadata-best-min-score.js +9 -0
  70. package/dist/metadata-best-pick.d.ts +9 -0
  71. package/dist/metadata-best-pick.js +9 -0
  72. package/dist/metadata-min-score.d.ts +9 -0
  73. package/dist/metadata-min-score.js +13 -0
  74. package/dist/metadata-top-min-score.d.ts +9 -0
  75. package/dist/metadata-top-min-score.js +13 -0
  76. package/dist/metadata-top-pick.d.ts +9 -0
  77. package/dist/metadata-top-pick.js +13 -0
  78. package/dist/miner/acceptance-criteria.d.ts +43 -0
  79. package/dist/miner/acceptance-criteria.js +77 -0
  80. package/dist/miner/agent-sdk-driver.d.ts +39 -0
  81. package/dist/miner/agent-sdk-driver.js +162 -0
  82. package/dist/miner/attempt-log.d.ts +29 -0
  83. package/dist/miner/attempt-log.js +100 -0
  84. package/dist/miner/attempt-metering.d.ts +39 -0
  85. package/dist/miner/attempt-metering.js +67 -0
  86. package/dist/miner/cli-subprocess-driver.d.ts +68 -0
  87. package/dist/miner/cli-subprocess-driver.js +272 -0
  88. package/dist/miner/coding-agent-driver.d.ts +33 -0
  89. package/dist/miner/coding-agent-driver.js +36 -0
  90. package/dist/miner/coding-agent-invoke.d.ts +11 -0
  91. package/dist/miner/coding-agent-invoke.js +80 -0
  92. package/dist/miner/coding-agent-mode.d.ts +25 -0
  93. package/dist/miner/coding-agent-mode.js +43 -0
  94. package/dist/miner/driver-factory.d.ts +82 -0
  95. package/dist/miner/driver-factory.js +169 -0
  96. package/dist/miner/harness-submission-trigger.d.ts +37 -0
  97. package/dist/miner/harness-submission-trigger.js +46 -0
  98. package/dist/miner/iterate-loop.d.ts +97 -0
  99. package/dist/miner/iterate-loop.js +278 -0
  100. package/dist/miner/iterate-policy.d.ts +98 -0
  101. package/dist/miner/iterate-policy.js +98 -0
  102. package/dist/miner/lint-guard.d.ts +50 -0
  103. package/dist/miner/lint-guard.js +68 -0
  104. package/dist/miner/local-write-tools.d.ts +81 -0
  105. package/dist/miner/local-write-tools.js +113 -0
  106. package/dist/miner/loop-reentry-policy.d.ts +36 -0
  107. package/dist/miner/loop-reentry-policy.js +53 -0
  108. package/dist/miner/repo-map.d.ts +51 -0
  109. package/dist/miner/repo-map.js +268 -0
  110. package/dist/miner/self-review-adapter.d.ts +106 -0
  111. package/dist/miner/self-review-adapter.js +83 -0
  112. package/dist/miner/submission-gate.d.ts +40 -0
  113. package/dist/miner/submission-gate.js +89 -0
  114. package/dist/miner/worktree-allocator.d.ts +59 -0
  115. package/dist/miner/worktree-allocator.js +60 -0
  116. package/dist/miner/worktree-pool.d.ts +55 -0
  117. package/dist/miner/worktree-pool.js +65 -0
  118. package/dist/miner-goal-lane-fit.d.ts +18 -0
  119. package/dist/miner-goal-lane-fit.js +76 -0
  120. package/dist/miner-goal-spec.d.ts +139 -0
  121. package/dist/miner-goal-spec.js +281 -0
  122. package/dist/miner-prediction-metrics.d.ts +16 -0
  123. package/dist/miner-prediction-metrics.js +61 -0
  124. package/dist/miner-telemetry.d.ts +32 -0
  125. package/dist/miner-telemetry.js +87 -0
  126. package/dist/objective-anchor.d.ts +125 -0
  127. package/dist/objective-anchor.js +401 -0
  128. package/dist/opportunity-competition.d.ts +6 -0
  129. package/dist/opportunity-competition.js +29 -0
  130. package/dist/opportunity-freshness.d.ts +18 -0
  131. package/dist/opportunity-freshness.js +55 -0
  132. package/dist/opportunity-metadata.d.ts +53 -0
  133. package/dist/opportunity-metadata.js +204 -0
  134. package/dist/opportunity-ranker.d.ts +46 -0
  135. package/dist/opportunity-ranker.js +74 -0
  136. package/dist/pairwise-calibration.d.ts +49 -0
  137. package/dist/pairwise-calibration.js +106 -0
  138. package/dist/phase7-calibration-loop.d.ts +136 -0
  139. package/dist/phase7-calibration-loop.js +437 -0
  140. package/dist/plan-blocked.d.ts +6 -0
  141. package/dist/plan-blocked.js +24 -0
  142. package/dist/plan-completed.d.ts +5 -0
  143. package/dist/plan-completed.js +6 -0
  144. package/dist/plan-completion.d.ts +6 -0
  145. package/dist/plan-completion.js +7 -0
  146. package/dist/plan-empty.d.ts +5 -0
  147. package/dist/plan-empty.js +6 -0
  148. package/dist/plan-export.d.ts +27 -0
  149. package/dist/plan-export.js +86 -0
  150. package/dist/plan-failure.d.ts +5 -0
  151. package/dist/plan-failure.js +6 -0
  152. package/dist/plan-overall-status.d.ts +6 -0
  153. package/dist/plan-overall-status.js +25 -0
  154. package/dist/plan-pending.d.ts +5 -0
  155. package/dist/plan-pending.js +6 -0
  156. package/dist/plan-progress-complete.d.ts +7 -0
  157. package/dist/plan-progress-complete.js +10 -0
  158. package/dist/plan-ready.d.ts +6 -0
  159. package/dist/plan-ready.js +12 -0
  160. package/dist/plan-running.d.ts +5 -0
  161. package/dist/plan-running.js +6 -0
  162. package/dist/plan-skipped.d.ts +5 -0
  163. package/dist/plan-skipped.js +6 -0
  164. package/dist/plan-step-count.d.ts +5 -0
  165. package/dist/plan-step-count.js +6 -0
  166. package/dist/plan-step-stats.d.ts +5 -0
  167. package/dist/plan-step-stats.js +6 -0
  168. package/dist/plan-templates.d.ts +25 -0
  169. package/dist/plan-templates.js +107 -0
  170. package/dist/plan-terminated.d.ts +6 -0
  171. package/dist/plan-terminated.js +9 -0
  172. package/dist/portfolio/non-convergence.d.ts +37 -0
  173. package/dist/portfolio/non-convergence.js +57 -0
  174. package/dist/portfolio/queue.d.ts +30 -0
  175. package/dist/portfolio/queue.js +150 -0
  176. package/dist/predicted-gate.d.ts +103 -0
  177. package/dist/predicted-gate.js +218 -0
  178. package/dist/prompt-packet.d.ts +11 -0
  179. package/dist/prompt-packet.js +34 -0
  180. package/dist/ranked-opportunity-best-min-score.d.ts +8 -0
  181. package/dist/ranked-opportunity-best-min-score.js +9 -0
  182. package/dist/ranked-opportunity-best-pick.d.ts +8 -0
  183. package/dist/ranked-opportunity-best-pick.js +9 -0
  184. package/dist/ranked-opportunity-min-score.d.ts +8 -0
  185. package/dist/ranked-opportunity-min-score.js +13 -0
  186. package/dist/ranked-opportunity-top-min-score.d.ts +8 -0
  187. package/dist/ranked-opportunity-top-min-score.js +13 -0
  188. package/dist/review/advisory-ai-routing-config.d.ts +8 -0
  189. package/dist/review/advisory-ai-routing-config.js +40 -0
  190. package/dist/review/check-names.d.ts +1 -0
  191. package/dist/review/check-names.js +1 -0
  192. package/dist/review/cla-check.d.ts +49 -0
  193. package/dist/review/cla-check.js +71 -0
  194. package/dist/review/diff-file-priority.d.ts +1 -0
  195. package/dist/review/diff-file-priority.js +12 -0
  196. package/dist/review/enrichment-analyzer-names.d.ts +3 -0
  197. package/dist/review/enrichment-analyzer-names.js +63 -0
  198. package/dist/review/guardrail-config.d.ts +10 -0
  199. package/dist/review/guardrail-config.js +62 -0
  200. package/dist/review/linked-issue-hard-rules-config.d.ts +4 -0
  201. package/dist/review/linked-issue-hard-rules-config.js +79 -0
  202. package/dist/review/linked-issue-label-propagation.d.ts +9 -0
  203. package/dist/review/linked-issue-label-propagation.js +114 -0
  204. package/dist/review/pre-merge-checks.d.ts +28 -0
  205. package/dist/review/pre-merge-checks.js +66 -0
  206. package/dist/review/review-thread-findings.d.ts +1 -0
  207. package/dist/review/review-thread-findings.js +1 -0
  208. package/dist/review/safe-url.d.ts +5 -0
  209. package/dist/review/safe-url.js +137 -0
  210. package/dist/review/screenshot-table-gate.d.ts +87 -0
  211. package/dist/review/screenshot-table-gate.js +340 -0
  212. package/dist/review/unlinked-issue-guardrail-config.d.ts +9 -0
  213. package/dist/review/unlinked-issue-guardrail-config.js +44 -0
  214. package/dist/reviewer-consensus-calibration.d.ts +113 -0
  215. package/dist/reviewer-consensus-calibration.js +493 -0
  216. package/dist/reward-risk.d.ts +223 -0
  217. package/dist/reward-risk.js +618 -0
  218. package/dist/scoring/label-match.d.ts +4 -0
  219. package/dist/scoring/label-match.js +145 -0
  220. package/dist/scoring/model.d.ts +31 -0
  221. package/dist/scoring/model.js +157 -0
  222. package/dist/scoring/pending-pr-scenarios.d.ts +44 -0
  223. package/dist/scoring/pending-pr-scenarios.js +145 -0
  224. package/dist/scoring/preview.d.ts +246 -0
  225. package/dist/scoring/preview.js +1108 -0
  226. package/dist/scoring/types.d.ts +131 -0
  227. package/dist/scoring/types.js +7 -0
  228. package/dist/settings/auto-close-exempt.d.ts +10 -0
  229. package/dist/settings/auto-close-exempt.js +58 -0
  230. package/dist/settings/autonomy.d.ts +33 -0
  231. package/dist/settings/autonomy.js +80 -0
  232. package/dist/settings/command-authorization.d.ts +49 -0
  233. package/dist/settings/command-authorization.js +222 -0
  234. package/dist/settings/contributor-blacklist.d.ts +17 -0
  235. package/dist/settings/contributor-blacklist.js +86 -0
  236. package/dist/settings/moderation-rules.d.ts +51 -0
  237. package/dist/settings/moderation-rules.js +104 -0
  238. package/dist/settings/pr-type-label.d.ts +70 -0
  239. package/dist/settings/pr-type-label.js +149 -0
  240. package/dist/signals/change-guardrail.d.ts +49 -0
  241. package/dist/signals/change-guardrail.js +164 -0
  242. package/dist/signals/check-summary.d.ts +9 -0
  243. package/dist/signals/check-summary.js +12 -0
  244. package/dist/signals/contributor-calibration.d.ts +23 -0
  245. package/dist/signals/contributor-calibration.js +47 -0
  246. package/dist/signals/duplicate-winner.d.ts +9 -0
  247. package/dist/signals/duplicate-winner.js +9 -0
  248. package/dist/signals/path-matchers.d.ts +36 -0
  249. package/dist/signals/path-matchers.js +371 -0
  250. package/dist/signals/predicted-gate-engine.d.ts +62 -0
  251. package/dist/signals/predicted-gate-engine.js +895 -0
  252. package/dist/signals/preflight-limits.d.ts +14 -0
  253. package/dist/signals/preflight-limits.js +14 -0
  254. package/dist/signals/slop.d.ts +56 -0
  255. package/dist/signals/slop.js +324 -0
  256. package/dist/signals/test-evidence.d.ts +25 -0
  257. package/dist/signals/test-evidence.js +108 -0
  258. package/dist/subprocess-env.d.ts +23 -0
  259. package/dist/subprocess-env.js +74 -0
  260. package/dist/track-record-summary.d.ts +92 -0
  261. package/dist/track-record-summary.js +301 -0
  262. package/dist/types/manifest-deps-types.d.ts +514 -0
  263. package/dist/types/manifest-deps-types.js +4 -0
  264. package/dist/types/predicted-gate-types.d.ts +338 -0
  265. package/dist/types/predicted-gate-types.js +3 -0
  266. package/dist/types/reward-risk-types.d.ts +319 -0
  267. package/dist/types/reward-risk-types.js +11 -0
  268. package/dist/utils/json.d.ts +1 -0
  269. package/dist/utils/json.js +3 -0
  270. package/dist/version.d.ts +2 -0
  271. package/dist/version.js +3 -0
  272. package/package.json +80 -0
@@ -0,0 +1,514 @@
1
+ export type { JsonValue } from "../scoring/types.js";
2
+ export type GateRuleMode = "off" | "advisory" | "block";
3
+ export type ReviewCheckMode = "required" | "visible" | "disabled";
4
+ export type ProjectMilestoneMatchMode = "off" | "suggest" | "auto";
5
+ export type ProjectMilestoneMatchBackend = "github" | "linear";
6
+ export type GatePolicyPack = "gittensor" | "oss-anti-slop";
7
+ export type CombineStrategy = "single" | "consensus" | "synthesis";
8
+ export type OnMerge = "either" | "both";
9
+ export type AiReviewLowConfidenceDisposition = "one_shot" | "hold_for_review" | "advisory_only";
10
+ export type ScreenshotTableGateAction = "close" | "advisory";
11
+ export type ScreenshotTableGateConfig = {
12
+ enabled: boolean;
13
+ whenLabels: string[];
14
+ whenPaths: string[];
15
+ action: ScreenshotTableGateAction;
16
+ message?: string | undefined;
17
+ requireViewports: string[];
18
+ requireThemes: string[];
19
+ skillFileUrl?: string | undefined;
20
+ };
21
+ export type CommandAuthorizationRole = "maintainer" | "collaborator" | "pr_author" | "confirmed_miner";
22
+ export type RepositoryCommandAuthorizationPolicy = {
23
+ default: CommandAuthorizationRole[];
24
+ commands: Record<string, CommandAuthorizationRole[]>;
25
+ };
26
+ export type PrTypeLabelSet = Record<string, string>;
27
+ export type LinkedIssueLabelPropagationMapping = {
28
+ issueLabel: string;
29
+ prLabel: string;
30
+ removeOtherTypeLabels: boolean;
31
+ /** Allow this mapping to fire off a linked issue authored by the repo's owner/admin/write-collaborator
32
+ * even when the PR author neither opened nor is assigned to that issue (#priority-linked-issue-gate-
33
+ * ownership). Defaults to `false`/unset (strict author-or-assignee-only behavior) -- a maintainer-reward
34
+ * mapping like `gittensor:priority` should never set this. Mirrors `src/types.ts`'s copy of this type;
35
+ * see `review/linked-issue-label-propagation-fetch.ts`'s `isRepoMaintainerLogin` (app-side only, not
36
+ * duplicated into this engine package since it needs GitHub/fetch/Env access). */
37
+ trustMaintainerAuthoredIssue?: boolean | undefined;
38
+ /** Like `trustMaintainerAuthoredIssue`, but for a mapping that DOES carry real reward weight
39
+ * (#priority-reward-maintainer-trust) -- e.g. `gittensor:priority`. Mirrors `src/types.ts`'s copy of
40
+ * this type; see that copy's doc comment for the full rationale. */
41
+ trustMaintainerAuthoredIssueForReward?: boolean | undefined;
42
+ };
43
+ export type LinkedIssueLabelPropagationMode = "exclusive_type_label";
44
+ export type LinkedIssueLabelPropagationConfig = {
45
+ enabled: boolean;
46
+ mode: LinkedIssueLabelPropagationMode;
47
+ mappings: LinkedIssueLabelPropagationMapping[];
48
+ };
49
+ export type LinkedIssueHardRulesMode = "block" | "off";
50
+ export type LinkedIssueHardRulesConfig = {
51
+ ownerAssignedClose: LinkedIssueHardRulesMode;
52
+ /** Close when an open linked issue is assigned to someone other than the PR author. */
53
+ assignedIssueClose: LinkedIssueHardRulesMode;
54
+ missingPointLabelClose: LinkedIssueHardRulesMode;
55
+ maintainerOnlyLabelClose: LinkedIssueHardRulesMode;
56
+ pointBearingLabels: string[];
57
+ maintainerOnlyLabels: string[];
58
+ defaultLabelRepo: boolean;
59
+ verifyBeforeClose: boolean;
60
+ closeDelaySeconds: number;
61
+ };
62
+ export type UnlinkedIssueGuardrailMode = "hold" | "off";
63
+ export type UnlinkedIssueGuardrailConfig = {
64
+ mode: UnlinkedIssueGuardrailMode;
65
+ minConfidence: number;
66
+ };
67
+ /** Per-capability opt-in to the local-inference AI_ADVISORY binding (#4364): each of these four ADVISORY-ONLY
68
+ * (never gate-blocking) capabilities independently decides whether it routes through env.AI_ADVISORY (when
69
+ * configured) instead of the shared frontier env.AI chain. Config-as-code only -- no DB column, resolved
70
+ * purely from `.gittensory.yml` `settings.advisoryAiRouting` (global default in the shared/root manifest,
71
+ * per-repo override), the same "config-as-code only" shape as unlinkedIssueGuardrail above. Every field
72
+ * defaults to false: an operator must deliberately opt EACH capability in, and even then a repo only
73
+ * actually routes through AI_ADVISORY when the binding itself is configured (env.AI_ADVISORY unset ⇒ every
74
+ * capability stays on env.AI regardless of this config, byte-identical to before this existed). */
75
+ export type AdvisoryAiRoutingConfig = {
76
+ slop: boolean;
77
+ e2eTestGen: boolean;
78
+ planner: boolean;
79
+ summaries: boolean;
80
+ /** Grounded `@gittensory chat <question>` LLM Q&A (#4595). Ollama-first: declines when off or when
81
+ * env.AI_ADVISORY is unconfigured and {@link chatQaFrontierFallback} is not also enabled. Default false. */
82
+ chatQa: boolean;
83
+ /** Opt-in ONLY (#4595 follow-up): when true, chat falls back to the shared frontier env.AI chain if
84
+ * env.AI_ADVISORY is unconfigured, instead of declining. Meaningless unless {@link chatQa} is also true.
85
+ * Default false. */
86
+ chatQaFrontierFallback: boolean;
87
+ /** Closed-set intent-classification router for unrecognized `@gittensory` mentions (#4596). Ollama-only,
88
+ * same as chatQa. Default false. */
89
+ intentRouting: boolean;
90
+ };
91
+ export type ContributorBlacklistEntry = {
92
+ login: string;
93
+ /** Why the account is blocked. Free-text maintainer metadata; not published in automated close comments. */
94
+ reason?: string | undefined;
95
+ /** PR/issue URLs (or other maintainer refs) evidencing the block. */
96
+ evidence?: string[] | undefined;
97
+ /** ISO-8601 date the entry was added. */
98
+ addedAt?: string | undefined;
99
+ };
100
+ export type AutonomyLevel = "observe" | "auto_with_approval" | "auto";
101
+ export type AgentActionClass = "review" | "request_changes" | "approve" | "merge" | "close" | "label" | "review_state_label" | "update_branch" | "assign";
102
+ export type AutonomyPolicy = Partial<Record<AgentActionClass, AutonomyLevel>>;
103
+ export type AutoMergeMethod = "merge" | "squash" | "rebase";
104
+ export type AutoMaintainPolicy = {
105
+ requireApprovals: number;
106
+ mergeMethod: AutoMergeMethod;
107
+ };
108
+ export type RepositorySettings = {
109
+ repoFullName: string;
110
+ commentMode: "off" | "detected_contributors_only" | "all_prs";
111
+ publicAudienceMode: "oss_maintainer" | "gittensor_only";
112
+ publicSignalLevel: "minimal" | "standard";
113
+ checkRunMode: "off" | "enabled";
114
+ checkRunDetailLevel: "minimal" | "standard";
115
+ /** Scheduled re-gate sweep candidate ordering (#3815). `staleness` (default) picks whichever open PR the
116
+ * sweep has gone longest WITHOUT re-gating (see selectRegateCandidates), which is what gives the sweep its
117
+ * documented full-coverage-in-ceil(open/max)-ticks convergence guarantee even under dry-run/pause (when
118
+ * GitHub's own `updatedAt` writes are suppressed). `oldest-first` instead always picks the oldest-created
119
+ * open PRs first, for an operator who wants deterministic creation-order draining over that guarantee.
120
+ * Selection-time only — real-time webhook-driven review is not gated by this and can process any PR at
121
+ * any time regardless of the chosen order. */
122
+ regateSweepOrderMode: "staleness" | "oldest-first";
123
+ /** The actual runtime authority for whether the "LoopOver Orb Review Agent" check-run publishes (#2852).
124
+ * See {@link ReviewCheckMode}. */
125
+ reviewCheckMode: ReviewCheckMode;
126
+ /** Auto-project/milestone matching (#3183). See {@link ProjectMilestoneMatchMode}. Always populated by the DB
127
+ * layer (default `"off"`); optional so existing settings fixtures/callers need not be touched. */
128
+ autoProjectMilestoneMatch?: ProjectMilestoneMatchMode | undefined;
129
+ /** Which backend {@link ProjectMilestoneMatchMode} matches against (#3186). See {@link ProjectMilestoneMatchBackend}.
130
+ * Always populated by the DB layer (default `"github"`); optional so existing settings fixtures/callers need
131
+ * not be touched. */
132
+ autoProjectMilestoneMatchBackend?: ProjectMilestoneMatchBackend | undefined;
133
+ /** Policy pack the gate evaluates under (#692). Default `gittensor` (registry-aware; threads confirmed
134
+ * status for scoring only). `oss-anti-slop` runs the deterministic rules against any author on any repo. */
135
+ gatePack: GatePolicyPack;
136
+ linkedIssueGateMode: GateRuleMode;
137
+ duplicatePrGateMode: GateRuleMode;
138
+ qualityGateMode: GateRuleMode;
139
+ qualityGateMinScore?: number | null | undefined;
140
+ /** Deterministic anti-slop signal (#530/#532). `off` = no slop score; `advisory` = surface the slop
141
+ * score + warnings in context; `block` = ALSO hard-block when slopRisk >= slopGateMinScore (deterministic
142
+ * only, applies to every author like every blocker). Default `off` — opt-in via .gittensory.yml. */
143
+ slopGateMode: GateRuleMode;
144
+ /** PR-size manual-review HOLD (#gate-size). `off` (default/absent) = no size hold; `advisory`/`block` = a PR with
145
+ * >= 10 changed files OR >= 1000 changed (added+deleted) lines that would otherwise pass is HELD for manual review
146
+ * (neutral gate → "manual" verdict), never auto-merged and never a hard failure. Opt-in via `gate.size.mode`. */
147
+ sizeGateMode?: GateRuleMode | undefined;
148
+ /** Lockfile-tamper-risk gate (#2563). `off` (default/absent) = no scan; `advisory`/`block` = a changed
149
+ * `package-lock.json` whose diff changes a `resolved`/`integrity` value WITHOUT the same package's version
150
+ * changing in a changed `package.json`, or whose `resolved` URL points outside `registry.npmjs.org`, produces
151
+ * a `lockfile_tamper_risk` finding (`block` additionally hard-blocks). Distinct from the OSV.dev CVE analyzer
152
+ * in review-enrichment — this is a tamper/integrity-substitution check, not a known-CVE check. Config-as-code
153
+ * only — no DB column or dashboard toggle; set via `.gittensory.yml gate.lockfileIntegrity`. */
154
+ lockfileIntegrityGateMode?: GateRuleMode | undefined;
155
+ /** CLA / license-compatibility gate (#2564). `off` (default/absent) = no CLA check at all; `advisory`/`block` =
156
+ * evaluate the configured detection method(s) (`claConsentPhrase` and/or `claCheckRunName` + `claCheckRunAppSlug`) and raise a
157
+ * `cla_consent_missing` finding when neither confirms consent — `block` also hard-blocks the gate. Config-as-code
158
+ * only (no DB column, mirrors sizeGateMode) — set via `.gittensory.yml gate.claMode`. */
159
+ claGateMode?: GateRuleMode | undefined;
160
+ /** `gate.cla.consentPhrase`: a public-safe-filtered phrase a maintainer requires somewhere in the PR body (e.g.
161
+ * "I have read and agree to the CLA"), matched case-insensitively. `null`/absent ⇒ phrase-match detection is not
162
+ * configured. Config-as-code only, alongside {@link claGateMode}. */
163
+ claConsentPhrase?: string | null | undefined;
164
+ /** `gate.cla.checkRunName`: the name of a separate CLA-bot check-run this repo also runs (e.g. "CLA Assistant
165
+ * Lite"). A `success`/`neutral` conclusion for a check-run with this exact name (case-insensitive), produced
166
+ * by `claCheckRunAppSlug`, also satisfies consent. `null`/absent ⇒ check-run detection is not configured.
167
+ * Config-as-code only, alongside {@link claGateMode}. */
168
+ claCheckRunName?: string | null | undefined;
169
+ /** `gate.cla.checkRunAppSlug`: the trusted GitHub App slug that must have produced `claCheckRunName`. Required
170
+ * for check-run detection so contributor-controlled same-name runs cannot satisfy a blocking CLA gate. */
171
+ claCheckRunAppSlug?: string | null | undefined;
172
+ /** Copycat/plagiarism detection (#1969). `off` (default/absent) = no check; `warn`/`label`/`block` are
173
+ * escalating tiers a future containment/similarity engine would act on. Config-as-code only — no DB column
174
+ * or dashboard toggle; set via `.gittensory.yml gate.copycat.mode`. CURRENTLY INERT: parsed and threaded
175
+ * end-to-end, but no detection engine reads it yet. */
176
+ copycatGateMode?: "off" | "warn" | "label" | "block" | undefined;
177
+ /** `gate.copycat.minScore`: containment/similarity score (0-100) at/above which `copycatGateMode` would act,
178
+ * once the detection engine exists. Config-as-code only, alongside {@link copycatGateMode}. */
179
+ copycatGateMinScore?: number | null | undefined;
180
+ /** `gate.expectedCiContexts` (#selfhost-ci-verification): maintainer-declared CI check/status context names to
181
+ * treat as required when GitHub branch protection returns no readable required-status-checks (unconfigured,
182
+ * or a 403 from a token lacking `administration:read` — common for GitHub App installations). Merged with any
183
+ * branch-protection required contexts when both exist; used ALONE when branch protection is null/empty; a
184
+ * repo with neither configured keeps the existing fold-all fail-closed behavior. A context missing from the
185
+ * commit ⇒ pending; a completed red check for a listed context ⇒ failed; every listed context settled clean
186
+ * ⇒ verified passed (no `ciCompletenessWarning`). Config-as-code only — no DB column; set via
187
+ * `.gittensory.yml gate.expectedCiContexts`. */
188
+ expectedCiContexts?: ReadonlyArray<string> | null | undefined;
189
+ /** Dry-run disposition (#gate-dryrun). When true, the gate renders the would-be merge/close/manual verdict (every
190
+ * advisory sub-gate promoted to block) WITHOUT enforcing — the posted check stays non-blocking. Lets advisory mode
191
+ * preview exactly what it would do before the maintainer flips to real enforcement. Default off. */
192
+ gateDryRun?: boolean | undefined;
193
+ /** Live premerge migrations/** collision recheck (#2550). When true, an agent-driven merge of a PR that
194
+ * touches migrations/** is preceded by a fresh GitHub Trees-API read of the base branch's CURRENT migration
195
+ * filenames — unioned with this PR's own new migration filenames — checked for a live numeric collision.
196
+ * A collision suppresses the merge and holds the PR with a rebase-needed label + comment instead of merging
197
+ * blind. Config-as-code only (no DB column, mirrors gateDryRun) — set via `.gittensory.yml`
198
+ * `gate.premergeContentRecheck`. Default off/undefined — opt-in, since it costs one extra, uncached
199
+ * GitHub API call for any PR that touches migrations/**. */
200
+ premergeContentRecheck?: boolean | undefined;
201
+ /** Merge-readiness gate (#merge-readiness). `off`/`advisory`/`block`. No min-score. Default `off`. */
202
+ mergeReadinessGateMode: GateRuleMode;
203
+ /** Focus-manifest policy gate (#555). When `block`, the focus manifest's declared policy (required-linked
204
+ * issue and test expectations) becomes an enforceable review-agent blocker. Path-based manual-review holds
205
+ * are configured separately through `settings.hardGuardrailGlobs`. An
206
+ * INDEPENDENT dimension, deliberately not folded into the merge-readiness composite. Default `off` — opt-in. */
207
+ manifestPolicyGateMode: GateRuleMode;
208
+ /** Self-authored linked-issue gate. When `block`, the gate closes a PR where the contributor also
209
+ * opened the linked issue (`pr.authorLogin === issue.authorLogin`). Defaults to `advisory` — the finding
210
+ * is surfaced in the review panel but never blocks unless the maintainer opts in. */
211
+ selfAuthoredLinkedIssueGateMode: GateRuleMode;
212
+ /** First-time-contributor grace (#552). RESERVED / currently INERT (#2266): parsed, clamped, and threaded
213
+ * end-to-end, but the gate evaluator never reads it — a genuine newcomer with a real blocker is still
214
+ * one-shot closed exactly like a repeat contributor (blocker findings must remain closure outcomes).
215
+ * Setting this true has no runtime effect today; kept for potential future use. Default false. */
216
+ firstTimeContributorGrace: boolean;
217
+ /** Slop-risk threshold (0-100) at/above which `slopGateMode: block` blocks. Default 60 (the `high` band). */
218
+ slopGateMinScore?: number | null | undefined;
219
+ /** AI-assisted slop advisory (the `slopAiAdvisory` capability). When true AND `slopGateMode != off`, a
220
+ * free/default-reviewer pass (the configured self-host provider, or the legacy Workers-AI pair when
221
+ * none is configured) adds an ADVISORY-only `ai_slop_advisory` finding for semantic slop the
222
+ * deterministic detector cannot quantify. It NEVER feeds slopRisk or the gate (only the deterministic
223
+ * core blocks). Default false — opt-in via `.gittensory.yml gate.slop.aiAdvisory`. */
224
+ slopAiAdvisory: boolean;
225
+ /** AI maintainer review. `off` = no AI; `advisory` = post AI review notes only; `block` = ALSO let a
226
+ * dual-model high-confidence consensus defect become a gate blocker (confirmed-contributors only,
227
+ * like every other blocker). Default `off` — AI is opt-in. */
228
+ aiReviewMode: GateRuleMode;
229
+ /** Bring-your-own-key: when true and a provider key is configured for the repo, the advisory AI review
230
+ * is generated by the maintainer's frontier model (Anthropic/OpenAI) instead of the free/default
231
+ * reviewer. The consensus blocker always uses the free/default reviewer pair regardless (the configured
232
+ * self-host provider, or the legacy Workers-AI pair when none is configured), so BYOK never changes who
233
+ * can be blocked. Default false. */
234
+ aiReviewByok: boolean;
235
+ /** Config-as-code BYOK provider for the advisory write-up. `null` = use the configured key's own
236
+ * provider. When set, it must match the stored key's provider or BYOK is skipped (falls back to the
237
+ * free/default reviewer). The secret key itself is never here — only via the encrypted key store. */
238
+ aiReviewProvider?: "anthropic" | "openai" | null | undefined;
239
+ /** Config-as-code model override for the BYOK advisory write-up (e.g. "claude-3-5-sonnet-latest").
240
+ * `null` = use the key record's model, else a conservative per-provider default. */
241
+ aiReviewModel?: string | null | undefined;
242
+ /** Review EVERY PR's author, not only confirmed Gittensor contributors. The AI maintainer review is
243
+ * confirmed-contributor-gated by default (an AI-spend guard). When true the review runs for any author —
244
+ * intended for a self-host operator who wants real reviews on all PRs (incl. their own) and pays for the
245
+ * AI themselves. Default false — opt-in via `.gittensory.yml gate.aiReview.allAuthors`. Independent of
246
+ * `aiReviewMode`: `off` still means no AI; this only widens WHO an enabled review covers. */
247
+ aiReviewAllAuthors: boolean;
248
+ /** Configured AI-reviewer confidence floor (0-1) for close calibration (#7). Under `aiReviewMode: block`, AI
249
+ * defect findings remain blockers even when their confidence is below this floor; the floor is retained as
250
+ * configurable context, not a manual-review downgrade. Config-as-code only — set via `.gittensory.yml
251
+ * gate.aiReview.closeConfidence` (no dashboard/DB column); unset ⇒ the gate uses the 0.93 default. Clamped to
252
+ * [0,1] at parse time. */
253
+ aiReviewCloseConfidence?: number | null | undefined;
254
+ /** Per-repo dual-AI combine-strategy override (#2567). Config-as-code only — set via `.gittensory.yml
255
+ * gate.aiReview.combine` (no dashboard/DB column); unset ⇒ the self-host operator's `AI_REVIEW_PLAN.combine`
256
+ * boot config (or `consensus` if the operator set nothing). A REFINEMENT of the operator's plan, not a
257
+ * bypass — `runGittensoryAiReview` clamps the resolved `onMerge` to the operator's floor (see
258
+ * {@link aiReviewOnMerge}); `combine` itself carries no floor semantics (single/consensus/synthesis are not
259
+ * ordered by strictness). */
260
+ aiReviewCombine?: CombineStrategy | null | undefined;
261
+ /** Per-repo `synthesis` merge-rule override (#2567): `either` blocks on ANY one reviewer's blocker (the
262
+ * STRICTER rule); `both` blocks only when every reviewer agrees (the more PERMISSIVE rule). Config-as-code
263
+ * only — set via `.gittensory.yml gate.aiReview.onMerge` (no dashboard/DB column). A repo override can only
264
+ * TIGHTEN the operator's `AI_REVIEW_PLAN.onMerge` floor (e.g. `either` → `either` is a no-op; `both` → an
265
+ * attempted loosening is clamped back to `either`). When the operator has not set an `onMerge` floor, any
266
+ * per-repo value is honored unclamped. See `resolveEffectiveAiReviewOnMerge` in `services/ai-review.ts`. */
267
+ aiReviewOnMerge?: OnMerge | null | undefined;
268
+ /** Per-repo reviewer-pair override (#2567): named self-host providers (e.g. `{ model: "claude-code" }`,
269
+ * `{ model: "codex" }`) to run instead of the operator's `AI_REVIEW_PLAN.reviewers` (or the free Workers-AI
270
+ * pair when the operator configured none). Config-as-code only — set via `.gittensory.yml
271
+ * gate.aiReview.reviewers` (no dashboard/DB column). Unlike {@link aiReviewOnMerge}, WHICH reviewers run
272
+ * carries no operator floor to violate (the floor is what triggers a hold/block, not who evaluates it), so a
273
+ * repo override always wins unclamped when set. */
274
+ aiReviewReviewers?: ReadonlyArray<{
275
+ model: string;
276
+ fallback?: string | null | undefined;
277
+ }> | null | undefined;
278
+ /** When TRUE, the repo OWNER's (and maintainer's) own PRs are eligible for auto-CLOSE like a contributor's
279
+ * (still subject to the `close` autonomy class + the same adverse-signal conditions). Default FALSE — owner
280
+ * PRs are exempt from auto-close (merge or manual-hold only). Per-repo configurable so maintainers choose
281
+ * rather than inheriting a hardwired opinion. */
282
+ closeOwnerAuthors: boolean;
283
+ autoLabelEnabled: boolean;
284
+ gittensorLabel: string;
285
+ createMissingLabel: boolean;
286
+ /** #label-decoupling: independently gates the per-PR TYPE/taxonomy label (bug/feature by the PR
287
+ * title, or priority via linked-issue label propagation — see `resolvePrTypeLabel` in
288
+ * `settings/pr-type-label.ts`). Distinct from {@link autoLabelEnabled} (which governs only the
289
+ * base {@link gittensorLabel} context label) and from `decidePublicSurface`'s public-surface gate
290
+ * (miner detection / `publicAudienceMode` / `includeMaintainerAuthors` / bot-author exclusion) —
291
+ * type labels are internal triage metadata applied unconditionally to every PR, not a
292
+ * contributor-facing signal, so neither of those public-surface conditions should suppress them.
293
+ * Default TRUE (matches the prior de-facto behavior before this field existed, when type labels
294
+ * were gated by `autoLabelEnabled` nested inside the public-surface check). Always populated by
295
+ * the DB layer; optional so existing settings fixtures/callers need not be touched. */
296
+ typeLabelsEnabled?: boolean | undefined;
297
+ /** Per-repo override of the TYPE/taxonomy label NAMES, keyed by category (#priority-linked-issue-gate,
298
+ * #label-modularity). Defaults to `DEFAULT_TYPE_LABELS` (`gittensor:bug`/`gittensor:feature`/
299
+ * `gittensor:priority`) in `settings/pr-type-label.ts` — a repo can override just one name (e.g. only
300
+ * `priority`) and keep the others default, AND/OR add arbitrary additional categories beyond the
301
+ * built-in three (e.g. `security: "area:security"`) for its own taxonomy. Always populated by the DB
302
+ * layer; optional so existing settings fixtures/callers need not be touched. */
303
+ typeLabels?: PrTypeLabelSet | undefined;
304
+ /** Linked-issue label propagation (#priority-linked-issue-gate): the ONLY mechanism that can ever
305
+ * select the configured priority label (or any other configured mapping's PR label) — never
306
+ * inferred from a PR's title, changed files, AI output, or existing PR labels. Default disabled
307
+ * (`enabled: false`, no mappings) — a self-hoster opts in per repo. Always populated by the DB
308
+ * layer; optional so existing settings fixtures/callers need not be touched. */
309
+ linkedIssueLabelPropagation?: LinkedIssueLabelPropagationConfig | undefined;
310
+ /** Deterministic linked-issue hard rules. Config-as-code only; set with
311
+ * `.gittensory.yml settings.linkedIssueHardRules` in private/global or per-repo config. These rules close
312
+ * contributor PRs that link ineligible issues before spending AI review budget: owner/other-assigned,
313
+ * maintainer-only, or missing point-label issues. Defaults all-off so self-hosters opt into their own policy. */
314
+ linkedIssueHardRules?: LinkedIssueHardRulesConfig | undefined;
315
+ /** Same-account issue-avoidance guardrail (#unlinked-issue-guardrail). Config-as-code only; set with
316
+ * `.gittensory.yml settings.unlinkedIssueGuardrail` in private/global or per-repo config. Defaults
317
+ * all-off so a self-hoster opts into their own credibility-gate-farming defense. */
318
+ unlinkedIssueGuardrail?: UnlinkedIssueGuardrailConfig | undefined;
319
+ /** Per-capability local-inference routing (#4364). Config-as-code only; set with `.gittensory.yml
320
+ * settings.advisoryAiRouting` in shared/global or per-repo config (global default + per-repo override,
321
+ * the same deep-merge precedence every other settings field uses). Defaults all-false so every advisory
322
+ * capability stays on the shared frontier env.AI chain until an operator opts each one in. */
323
+ advisoryAiRouting?: AdvisoryAiRoutingConfig | undefined;
324
+ publicSurface: "off" | "comment_and_label" | "comment_only" | "label_only";
325
+ includeMaintainerAuthors: boolean;
326
+ requireLinkedIssue: boolean;
327
+ backfillEnabled: boolean;
328
+ /** Opt-in for the public, unauthenticated README status badge (#541). Always populated by the DB layer
329
+ * (default false); optional so existing settings fixtures/callers need not be touched. */
330
+ badgeEnabled?: boolean | undefined;
331
+ /** Opt-in for the public per-repo review-quality page (#2568). Always populated by the DB layer
332
+ * (default false); optional so existing settings fixtures/callers need not be touched. */
333
+ publicQualityMetrics?: boolean | undefined;
334
+ commandAuthorization?: RepositoryCommandAuthorizationPolicy | undefined;
335
+ /** Per-repo contributor blacklist (#1425, anti-abuse): banned GitHub logins whose PRs/issues the engine
336
+ * deterministically closes ahead of merit review. Layered the same as other settings (`.gittensory.yml` >
337
+ * DB) and unioned with the shared/global list at the point of use. Always populated by the DB layer
338
+ * (default `[]`); optional so existing settings fixtures/callers need not be touched. */
339
+ contributorBlacklist?: ContributorBlacklistEntry[] | undefined;
340
+ /** The label applied to a blacklisted contributor's PR (#1425). Configurable per-repo (dashboard/DB +
341
+ * `.gittensory.yml` `settings.blacklistLabel`); defaults to `"slop"` so the disposition works regardless of
342
+ * the label a repo sets. Explicit `null` closes WITHOUT applying any label (the same load-bearing-null idiom
343
+ * as {@link contributorOpenPrCap}) -- distinct from omitted/undefined, which uses the default. Always
344
+ * populated by the DB layer (default `"slop"`); optional so existing settings fixtures/callers need not be
345
+ * touched (mirrors the sibling `contributorBlacklist`). */
346
+ blacklistLabel?: string | null | undefined;
347
+ /** Per-contributor open-PR cap (#2270, anti-abuse): the max PRs a single non-owner/admin/bot contributor may
348
+ * have open on this repo at once. `null`/absent (default) = no cap, byte-identical to today. Layered like
349
+ * every other settings field (`.gittensory.yml` `settings.contributorOpenPrCap` > DB > `null`). Enforcement
350
+ * (closing the newest PR(s) over the cap) is a separate follow-up; this field only carries the threshold. */
351
+ contributorOpenPrCap?: number | null | undefined;
352
+ /** Per-contributor open-issue cap (#2270, anti-abuse): same shape and precedence as {@link contributorOpenPrCap},
353
+ * applied to open issues instead of open PRs. `null`/absent (default) = no cap. */
354
+ contributorOpenIssueCap?: number | null | undefined;
355
+ /** The label applied to a PR/issue closed for exceeding a per-contributor open-item cap (#2270). Same
356
+ * configurable-with-fallback shape as {@link blacklistLabel} (including the explicit-`null`-closes-without-a-
357
+ * label idiom); defaults to `"over-contributor-limit"` so the disposition works regardless of the label a
358
+ * repo sets. Always populated by the DB layer; optional so existing settings fixtures/callers need not be
359
+ * touched. */
360
+ contributorCapLabel?: string | null | undefined;
361
+ /** Cancel in-flight CI runs on a contributor_cap close (#2462, anti-abuse): when true, after a PR is
362
+ * auto-closed for exceeding {@link contributorOpenPrCap}, gittensory lists and cancels that PR's
363
+ * in-progress/queued Actions runs at its head SHA. Requires the App installation to have granted
364
+ * `actions: write` -- degrades gracefully (skipped + logged, never blocks the close) when it hasn't.
365
+ * `null`/undefined (the DB-layer default) means "unset" and falls back to the
366
+ * `CONTRIBUTOR_CAP_CANCEL_CI_DEFAULT` env var -- unlike most boolean toggles, this one is nullable so an
367
+ * explicit `false` (opt back out) is distinguishable from "not configured" for that fallback. */
368
+ contributorCapCancelCi?: boolean | null | undefined;
369
+ /** Review-request nagging cooldown (#2463, anti-abuse): throttle a contributor repeatedly pinging
370
+ * `@gittensory` (any command) on this repo. `"off"` (default) is a no-op; `"hold"` posts a deterministic
371
+ * cooldown reply and takes no further action; `"close"` additionally closes the thread (PR threads only in
372
+ * v1 — a plain issue thread degrades to `"hold"` behavior until #2493's `closeIssue` primitive lands).
373
+ * Always populated by the DB layer (default `"off"`); optional so existing settings fixtures/callers need
374
+ * not be touched. */
375
+ reviewNagPolicy?: "off" | "hold" | "close" | undefined;
376
+ /** Review-nag cooldown (#2463): how many `@gittensory` pings a contributor may make on this repo within
377
+ * {@link reviewNagCooldownDays} before the (N+1)th is throttled. Always populated by the DB layer (default
378
+ * `3`); optional so existing settings fixtures/callers need not be touched. Only meaningful when
379
+ * {@link reviewNagPolicy} is not `"off"`. */
380
+ reviewNagMaxPings?: number | undefined;
381
+ /** Review-nag cooldown (#2463): the rolling window (in days) {@link reviewNagMaxPings} counts against. Always
382
+ * populated by the DB layer (default `5`); optional so existing settings fixtures/callers need not be
383
+ * touched. */
384
+ reviewNagCooldownDays?: number | undefined;
385
+ /** The label applied to a thread closed for review-nag cooldown (#2463), mirroring {@link blacklistLabel}'s
386
+ * configurable-with-fallback shape (including the explicit-`null`-closes-without-a-label idiom). Always
387
+ * populated by the DB layer (default `"review-nag-cooldown"`); optional so existing settings
388
+ * fixtures/callers need not be touched. */
389
+ reviewNagLabel?: string | null | undefined;
390
+ /** Maintainer-mention nag moderation: GitHub logins to ALSO throttle under the review-nag cooldown when the
391
+ * thread author repeatedly @-mentions them (on top of the bot's own `@gittensory` handle) -- e.g. a
392
+ * maintainer login instead of the bot, for a contributor who keeps tagging a specific person for review.
393
+ * Counted independently per mentioned login and independently of the `@gittensory` counter, but reuses the
394
+ * SAME {@link reviewNagPolicy}/{@link reviewNagMaxPings}/{@link reviewNagCooldownDays}/{@link reviewNagLabel}
395
+ * thresholds/action/label -- one cooldown policy, multiple watched mention targets. `[]`/undefined (default)
396
+ * = no logins watched, zero behavior change. Never fires for the repo owner, admin logins, automation bots,
397
+ * or a login on {@link autoCloseExemptLogins}. */
398
+ reviewNagMonitoredMentions?: string[] | undefined;
399
+ /** Shared repo-scoped exemption list (#2463, anti-abuse): GitHub logins that are NEVER throttled or closed by
400
+ * gittensory's deterministic anti-abuse mechanisms (review-nag and the per-contributor open-item cap above),
401
+ * on top of the standing owner/admin/automation-bot exemption. Always populated by the DB layer (default
402
+ * `[]`); optional so existing settings fixtures/callers need not be touched. */
403
+ autoCloseExemptLogins?: string[] | undefined;
404
+ /** Hard manual-review guardrail globs. Config-as-code only: set in private/global or per-repo
405
+ * `.gittensory.yml` under `settings.hardGuardrailGlobs`. Absent means no path guardrails. Arrays are
406
+ * replacement overlays, so a repo can clear a global default with `[]`. */
407
+ hardGuardrailGlobs?: string[] | null | undefined;
408
+ /** Label applied when an otherwise-ready PR is held for manual review by a guardrail. Config-as-code only;
409
+ * `null` disables the label while keeping the hold. Distinct from `review_state_label`, so operators can
410
+ * apply one manual-review label without enabling ready/changes-requested disposition labels. */
411
+ manualReviewLabel?: string | null | undefined;
412
+ /** Optional review-state label names. Config-as-code only; each `null` disables that specific label. These are
413
+ * deliberately generic defaults rather than `gittensory:*` names so self-hosters can opt into their own
414
+ * taxonomy without inheriting project-specific labels. */
415
+ readyToMergeLabel?: string | null | undefined;
416
+ changesRequestedLabel?: string | null | undefined;
417
+ migrationCollisionLabel?: string | null | undefined;
418
+ pendingClosureLabel?: string | null | undefined;
419
+ /** Force-rebase-before-merge window in minutes (#2552, anti-race). When a base branch has advanced within
420
+ * this many minutes of the actual merge-decision moment, an agent-driven merge forces an `update_branch` +
421
+ * fresh CI recheck cycle first, rather than trusting a `mergeableState: clean` read that may already be
422
+ * stale relative to a sibling commit that just landed on the base. `null`/undefined (default) = never
423
+ * force -- a `mergeable_state: clean` read is trusted exactly as it is today. Layered like every other
424
+ * settings field (`.gittensory.yml` `gate.requireFreshRebaseWindow` > DB > `null`). */
425
+ requireFreshRebaseWindowMinutes?: number | null | undefined;
426
+ /** Account-age throttle (#2561, anti-abuse): an account younger than this many days gets the
427
+ * {@link newAccountLabel} and a tighter effective contributor cap — friction/visibility, NEVER an
428
+ * automatic close on account age alone. `null`/undefined (default) = off. Never fires for the repo
429
+ * owner, admin logins, or automation bots. Applies on both PR and issue contributor-cap paths. */
430
+ accountAgeThresholdDays?: number | null | undefined;
431
+ /** The label applied to a below-threshold-age account's PR (#2561), mirroring {@link blacklistLabel}'s
432
+ * configurable-with-fallback shape. Always populated by the DB layer (default `"new-account"`); optional so
433
+ * existing settings fixtures/callers need not be touched. */
434
+ newAccountLabel?: string | undefined;
435
+ /** Per-command @gittensory rate limit (#2560, anti-abuse): generalizes the review-nag cooldown's counting
436
+ * pattern (the audit-events ledger) to EVERY `@gittensory` command, keyed by `(actor, command, targetKey)` --
437
+ * independent of, and complementary to, review-nag's own narrower thread-author-only scope. `"off"` (default)
438
+ * is a no-op; `"hold"` posts a deterministic cooldown reply and skips the command's own dispatch. Always
439
+ * populated by the DB layer (default `"off"`); optional so existing settings fixtures/callers need not be
440
+ * touched. */
441
+ commandRateLimitPolicy?: "off" | "hold" | undefined;
442
+ /** Per-command rate limit (#2560): how many invocations of a single command an actor may make within
443
+ * {@link commandRateLimitWindowHours} before the (N+1)th is throttled -- for a CHEAP command (cache-only,
444
+ * no AI orchestrator call). Always populated by the DB layer (default `20`); optional so existing settings
445
+ * fixtures/callers need not be touched. Only meaningful when {@link commandRateLimitPolicy} is not `"off"`. */
446
+ commandRateLimitMaxPerWindow?: number | undefined;
447
+ /** Per-command rate limit (#2560): the same threshold as {@link commandRateLimitMaxPerWindow}, but for an
448
+ * AI-cost-bearing command (dispatches to a real orchestrator call: `ask`, `blockers`, `preflight`,
449
+ * `reviewability`, `packet`, `duplicate-check`, `next-action`, `repo-fit`). Deliberately tighter than the
450
+ * cheap-command default. Always populated by the DB layer (default `5`); optional so existing settings
451
+ * fixtures/callers need not be touched. */
452
+ commandRateLimitAiMaxPerWindow?: number | undefined;
453
+ /** Per-command rate limit (#2560): the rolling window (in hours) both {@link commandRateLimitMaxPerWindow}
454
+ * and {@link commandRateLimitAiMaxPerWindow} count against. Always populated by the DB layer (default `24`);
455
+ * optional so existing settings fixtures/callers need not be touched. */
456
+ commandRateLimitWindowHours?: number | undefined;
457
+ /** Agent-layer autonomy dial (#773): per-action-class level. Always populated by the DB layer (default
458
+ * `{}` = deny-by-default = "observe" for every class); optional so existing settings fixtures/callers
459
+ * need not be touched. The single source the action layer (#778) reads via `resolveAutonomy`. */
460
+ autonomy?: AutonomyPolicy | undefined;
461
+ /** Auto-maintain policy (#774): merge method + approval count. Always populated by the DB layer with
462
+ * defaults (squash / 1 approval); optional so existing settings fixtures/callers need not be touched. */
463
+ autoMaintain?: AutoMaintainPolicy | undefined;
464
+ /** Per-repo agent kill-switch (#776): when true, the action layer takes NO action on this repo (the
465
+ * global env switch overrides this too). Default false. */
466
+ agentPaused?: boolean | undefined;
467
+ /** Per-repo dry-run/shadow mode (#776): when true, the action layer records what it WOULD do without
468
+ * performing any GitHub mutation. Default false. */
469
+ agentDryRun?: boolean | undefined;
470
+ /** Per-repo override of the global DB-backed agent freeze (#4372): when true, this repo's actions execute
471
+ * even while `global_agent_controls.frozen` is set, so an operator can re-activate one repo at a time
472
+ * without lifting the fleet-wide brake. Never overrides the `AGENT_ACTIONS_PAUSED` env var, and
473
+ * {@link agentPaused} on this same repo still wins over it. Default false. */
474
+ agentGlobalFreezeOverride?: boolean | undefined;
475
+ /** Moderation-rules engine (#selfhost-mod-engine): whether the whole layer runs on THIS repo. `"inherit"`
476
+ * (the DB default) defers to `global_moderation_config.enabled`; `"off"`/`"enabled"` force this repo
477
+ * regardless of the global default. Always populated by the DB layer; optional so existing settings
478
+ * fixtures/callers need not be touched. */
479
+ moderationGateMode?: "inherit" | "off" | "enabled" | undefined;
480
+ /** Moderation-rules engine: a per-repo override of WHICH of the anti-abuse mechanisms (contributor cap,
481
+ * blacklist, review-nag, review-evasion) feed a contributor's shared, cross-repo violation tally.
482
+ * `undefined`/absent ⇒ inherit the global rule set (`resolveEffectiveModerationRules`'s default shape). */
483
+ moderationRules?: ("contributor_cap" | "blacklist" | "review_nag" | "review_evasion")[] | undefined;
484
+ /** Moderation-rules engine: per-repo override of the label applied at >=1 lifetime violation. `undefined` ⇒
485
+ * the global config's `warningLabel` (itself defaulting to `"mod:warning"`). */
486
+ moderationWarningLabel?: string | undefined;
487
+ /** Moderation-rules engine: per-repo override of the label applied at >= the ban threshold. `undefined` ⇒
488
+ * the global config's `bannedLabel` (itself defaulting to `"mod:banned"`). */
489
+ moderationBannedLabel?: string | undefined;
490
+ /** Review-evasion protection (#review-evasion-protection): a contributor closing or converting their OWN
491
+ * PR to draft while gittensory has an ACTIVE review pass running against it is dodging the one-shot
492
+ * review process. `"off"` (the default) disables detection entirely; `"close"` reopens (if needed) and
493
+ * re-closes as the App -- a close the contributor cannot themselves reopen (#one-shot-reopen) -- applies
494
+ * the configured label/comment, and records a `review_evasion` moderation strike. */
495
+ reviewEvasionProtection?: "off" | "close" | undefined;
496
+ /** Review-evasion protection: label applied alongside the enforcement close, gated on `close` autonomy
497
+ * like every other anti-abuse label (#label-scoping), mirroring {@link blacklistLabel}'s shape. `undefined`
498
+ * ⇒ the `"review-evasion"` default; explicit `null` ⇒ close without any label. */
499
+ reviewEvasionLabel?: string | null | undefined;
500
+ /** Review-evasion protection: whether to post the public explanation comment before the enforcement close.
501
+ * Default true. */
502
+ reviewEvasionComment?: boolean | undefined;
503
+ /** Merge-train FIFO gate (#selfhost-merge-train): `"off"` keeps current behavior, `"audit"` logs would-hold
504
+ * decisions, and `"enforce"` defers a merge behind a still-viable older sibling. */
505
+ mergeTrainMode?: "off" | "audit" | "enforce" | undefined;
506
+ /** Config-driven before/after screenshot-table gate (#2006): a DETERMINISTIC check (no AI, zero hallucination
507
+ * risk) that a contributor visual/frontend PR's body contains a markdown table with before/after image
508
+ * markup, scoped to the repo's configured labels/paths (`whenLabels`/`whenPaths`, OR-matched). Off by
509
+ * default (`enabled: false`) -- opt in per repo, mirroring every other anti-abuse mechanism's shape. See
510
+ * `review/screenshot-table-gate.ts` for the normalizer and the pure evaluator. */
511
+ screenshotTableGate?: ScreenshotTableGateConfig | undefined;
512
+ createdAt?: string | null | undefined;
513
+ updatedAt?: string | null | undefined;
514
+ };
@@ -0,0 +1,4 @@
1
+ // Type mirrors from `src/types.ts` needed by focus-manifest parse/compile core and its
2
+ // engine-local settings normalizers. The engine package cannot import across into `src/` — keep in sync
3
+ // by hand. `JsonValue` is sourced from `scoring/types.ts`.
4
+ export {};