From 1a712a0f6bc936bd8111138141cf18fdd05c52f8 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Thu, 2 Jul 2026 04:52:05 -0700 Subject: [PATCH] docs(config): document 4 real gate knobs missing from .gittensory.yml.example gate.size.mode, gate.dryRun, gate.selfAuthoredLinkedIssue, and gate.aiReview.closeConfidence are all fully parsed by parseGateConfig and applied by resolveEffectiveSettings -- real, working, enforced knobs -- but none appeared in .gittensory.yml.example's documented gate: block. Three of the four (size.mode, dryRun, aiReview.closeConfidence) are config-as-code only, with no DB column or dashboard equivalent; selfAuthoredLinkedIssue has a real DB column (self_authored_linked_issue_gate_mode) the yml value overrides. Added all 4 to the example file with the exact doc-comment convention already used for every other gate sub-field, noting config-as-code-only scope where applicable. Added a regression test that parses the actual .gittensory.yml.example file through the real parser and asserts zero warnings plus round-trips the 4 new knobs, so documentation can never silently drift from parser behavior again. --- .gittensory.yml.example | 26 ++++++++++++++++++++++++++ test/unit/focus-manifest.test.ts | 13 +++++++++++++ 2 files changed, 39 insertions(+) diff --git a/.gittensory.yml.example b/.gittensory.yml.example index 00396ff35c..da2c2b01b3 100644 --- a/.gittensory.yml.example +++ b/.gittensory.yml.example @@ -135,6 +135,14 @@ gate: # the gate. Bool. Default: false. aiAdvisory: false + # Oversized-PR gate. A PR at/above BOTH the file-count and line-count thresholds + # (engine defaults, not configurable here) gets a manual-review HOLD finding — + # never a hard blocker, so it's dry-run/advisory friendly regardless of mode. + # off | advisory | block. Default: off. Config-as-code only — no DB column or + # dashboard toggle; this can only be set here. + size: + mode: off + # Composite merge-readiness gate (no min score). # off | advisory | block. Default: off. mergeReadiness: off @@ -145,6 +153,19 @@ gate: # off | advisory | block. Default: off. manifestPolicy: off + # Self-authored-linked-issue gate — blocks (or advises on) a PR whose only + # linked issue was opened by the PR's own author, which the readiness/quality + # signals can't otherwise catch. off | advisory | block. Default: advisory. + # DB-backed (dashboard-settable too); this overrides the stored value. + selfAuthoredLinkedIssue: advisory + + # Gate-wide dry-run. When true, the gate evaluates and posts its verdict as + # normal but never actually blocks/merges/closes based on it — useful for + # trialing a stricter pack or mode change against real traffic before + # enforcing it. Bool. Default: false. Config-as-code only — no DB column or + # dashboard toggle; this can only be set here. + dryRun: false + # First-time-contributor grace. RESERVED / currently INERT: this value is # parsed and stored, but the gate does not read it — a first-time # contributor with a real blocker is one-shot closed the same as a @@ -188,6 +209,11 @@ gate: # String or null. Default: null (the key record's model, else a conservative # per-provider default). model: null + # Minimum calibrated AI-reviewer confidence (0-1) for a consensus defect to + # become a blocker; below this it stays advisory-only. Number 0–1, or null. + # Default: null (engine uses 0.93). Config-as-code only — no DB column or + # dashboard toggle; this can only be set here. + closeConfidence: null # ---------------------------------------------------------------------------- diff --git a/test/unit/focus-manifest.test.ts b/test/unit/focus-manifest.test.ts index 61d81bbd50..c0f5e35e5f 100644 --- a/test/unit/focus-manifest.test.ts +++ b/test/unit/focus-manifest.test.ts @@ -1,3 +1,4 @@ +import { readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; import { buildFocusManifestGuidance, @@ -168,6 +169,18 @@ describe("parseFocusManifestContent", () => { expect(manifest.present).toBe(false); expect(manifest.warnings.join(" ")).toMatch(/not valid YAML/i); }); + + it("parses .gittensory.yml.example with zero warnings (#2554: doc must match parser exactly)", () => { + const content = readFileSync(".gittensory.yml.example", "utf8"); + const manifest = parseFocusManifestContent(content, "repo_file"); + expect(manifest.warnings).toEqual([]); + expect(manifest.present).toBe(true); + // Spot-check the 4 knobs #2554 added docs for actually round-trip through the real parser. + expect(manifest.gate.sizeMode).toBe("off"); + expect(manifest.gate.dryRun).toBe(false); + expect(manifest.gate.selfAuthoredLinkedIssue).toBe("advisory"); + expect(manifest.gate.aiReviewCloseConfidence).toBeNull(); + }); }); describe("matchesManifestPath", () => {