Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 5 additions & 13 deletions packages/gittensory-engine/src/focus-manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ export type FocusManifestIssueDiscoveryPolicy = "encouraged" | "neutral" | "disc
* field is `null` when the maintainer did not set it, so the resolver can layer the manifest OVER the
* DB-backed RepositorySettings (manifest > DB > safe defaults) without clobbering unset values. All
* of these flow through the SAME confirmed-contributor-gated `evaluateGateCheck` path — the manifest
* only chooses which deterministic blockers are active, never who can be blocked. Turning the gate
* itself on/off stays a repository setting (`gateCheckMode`); `.gittensory.yml gate:` refines the
* blocker policy of an already-enabled gate. `checkMode` (#2852) is a separate, more expressive axis:
* whether/how the "Gittensory Orb Review Agent" check-RUN publishes, independent of gate evaluation
* itself (which always runs regardless of `checkMode`/`enabled`) — see {@link ReviewCheckMode}.
* only chooses which deterministic blockers are active, never who can be blocked. There is no single
* gate master switch: each per-dimension mode (`linkedIssue`, `duplicates`, `readinessMode`, etc.)
* independently controls whether that dimension evaluates. `checkMode`/`enabled` (#2852) is a separate
* axis entirely: whether/how the "Gittensory Orb Review Agent" check-RUN publishes, independent of gate
* evaluation itself (which always runs regardless of `checkMode`/`enabled`) — see {@link ReviewCheckMode}.
*/
export type FocusManifestGateConfig = {
present: boolean;
Expand Down Expand Up @@ -373,7 +373,6 @@ export type FocusManifestSettings = Partial<
| "publicSignalLevel"
| "checkRunMode"
| "checkRunDetailLevel"
| "gateCheckMode"
| "regateSweepOrderMode"
| "reviewCheckMode"
| "autoProjectMilestoneMatch"
Expand Down Expand Up @@ -1815,19 +1814,12 @@ function parseSettingsOverride(value: JsonValue | undefined, warnings: string[],
if (checkRunMode !== null) out.checkRunMode = checkRunMode;
const checkRunDetailLevel = normalizeOptionalEnum(r.checkRunDetailLevel, "settings.checkRunDetailLevel", ["minimal", "standard"] as const, warnings);
if (checkRunDetailLevel !== null) out.checkRunDetailLevel = checkRunDetailLevel;
// #4618: gateCheckMode is deprecated (a computed read-back value everywhere else) but this yml key still
// parses for back-compat with existing `.gittensory.yml` files. A manifest setting ONLY gateCheckMode
// (never the more expressive reviewCheckMode) must keep its historical effect on the actual publish
// authority -- derive reviewCheckMode from it below when reviewCheckMode itself is unset.
const gateCheckMode = normalizeOptionalEnum(r.gateCheckMode, "settings.gateCheckMode", ["off", "enabled"] as const, warnings);
if (gateCheckMode !== null) out.gateCheckMode = gateCheckMode;
const regateSweepOrderMode = normalizeOptionalEnum(r.regateSweepOrderMode, "settings.regateSweepOrderMode", ["staleness", "oldest-first"] as const, warnings);
if (regateSweepOrderMode !== null) out.regateSweepOrderMode = regateSweepOrderMode;
// Same tri-state field as gate.checkMode above (the friendly gate alias overlays onto it in
// resolveEffectiveSettings, and wins when both are set).
const reviewCheckMode = normalizeOptionalEnum(r.reviewCheckMode, "settings.reviewCheckMode", ["required", "visible", "disabled"] as const, warnings);
if (reviewCheckMode !== null) out.reviewCheckMode = reviewCheckMode;
else if (gateCheckMode !== null) out.reviewCheckMode = gateCheckMode === "enabled" ? "required" : "disabled";
const autoProjectMilestoneMatch = normalizeOptionalEnum(r.autoProjectMilestoneMatch, "settings.autoProjectMilestoneMatch", ["off", "suggest", "auto"] as const, warnings);
if (autoProjectMilestoneMatch !== null) out.autoProjectMilestoneMatch = autoProjectMilestoneMatch;
const autoProjectMilestoneMatchBackend = normalizeOptionalEnum(r.autoProjectMilestoneMatchBackend, "settings.autoProjectMilestoneMatchBackend", ["github", "linear"] as const, warnings);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,6 @@ export type RepositorySettings = {
publicSignalLevel: "minimal" | "standard";
checkRunMode: "off" | "enabled";
checkRunDetailLevel: "minimal" | "standard";
/** @deprecated (#4618, being removed per #5373) computed read-back of {@link reviewCheckMode} below,
* kept only for API/dashboard back-compat display -- read `reviewCheckMode` instead. Optional (widened
* ahead of full removal) so callers building a partial RepositorySettings no longer need to supply it. */
gateCheckMode?: "off" | "enabled" | undefined;
/** Scheduled re-gate sweep candidate ordering (#3815). `staleness` (default) picks whichever open PR the
* sweep has gone longest WITHOUT re-gating (see selectRegateCandidates), which is what gives the sweep its
* documented full-coverage-in-ceil(open/max)-ticks convergence guarantee even under dry-run/pause (when
Expand All @@ -168,8 +164,7 @@ export type RepositorySettings = {
* any time regardless of the chosen order. */
regateSweepOrderMode: "staleness" | "oldest-first";
/** The actual runtime authority for whether the "Gittensory Orb Review Agent" check-run publishes (#2852).
* See {@link ReviewCheckMode}. `gateCheckMode` above stays wired for API/back-compat display but no longer
* drives the publish decision on its own. */
* See {@link ReviewCheckMode}. */
reviewCheckMode: ReviewCheckMode;
/** Auto-project/milestone matching (#3183). See {@link ProjectMilestoneMatchMode}. Always populated by the DB
* layer (default `"off"`); optional so existing settings fixtures/callers need not be touched. */
Expand Down
1 change: 0 additions & 1 deletion scripts/check-docs-drift.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ const NOT_YML_CONFIGURABLE_SETTINGS_FIELDS = new Set([
* alias per row is enough. Any `*GateMode` field is deliberately absent from this manifest even though its own
* yml key is ALSO renamed the same way -- GATE_MODE_MANIFEST above already owns that exhaustive cross-check. */
export const SETTINGS_ALIAS_MANIFEST = [
{ field: "gateCheckMode", aliases: ["checkMode"] },
{ field: "reviewCheckMode", aliases: ["checkMode"] },
{ field: "gatePack", aliases: ["pack:"] },
{ field: "qualityGateMinScore", aliases: ["minScore"] },
Expand Down
28 changes: 15 additions & 13 deletions test/unit/focus-manifest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ describe(".gittensory.yml.example field-exhaustiveness (#1670)", () => {
// Settings fields that are raw aliases of an already-documented `gate:` field (see the describe-block
// comment above) -- intentionally NOT in SETTINGS_FIELD_TOKENS, so they must be listed here instead of
// silently vanishing from the exhaustiveness check.
const SETTINGS_GATE_ALIASED_FIELDS = ["gateCheckMode", "linkedIssueGateMode", "duplicatePrGateMode", "selfAuthoredLinkedIssueGateMode", "qualityGateMode", "qualityGateMinScore", "aiReviewMode", "aiReviewByok", "aiReviewProvider", "aiReviewModel", "aiReviewAllAuthors"] as const;
const SETTINGS_GATE_ALIASED_FIELDS = ["linkedIssueGateMode", "duplicatePrGateMode", "selfAuthoredLinkedIssueGateMode", "qualityGateMode", "qualityGateMinScore", "aiReviewMode", "aiReviewByok", "aiReviewProvider", "aiReviewModel", "aiReviewAllAuthors"] as const;

// Settings fields that are DELIBERATELY absent from `.gittensory.yml.example` (unlike the gate-aliased fields
// above, these are never documented anywhere in the public template): agentGlobalFreezeOverride is an
Expand Down Expand Up @@ -1997,7 +1997,7 @@ describe("parseFocusManifest settings override + resolveEffectiveSettings", () =
publicSignalLevel: "minimal",
checkRunMode: "enabled",
checkRunDetailLevel: "standard",
gateCheckMode: "enabled",
reviewCheckMode: "required",
linkedIssueGateMode: "block",
duplicatePrGateMode: "off",
qualityGateMode: "advisory",
Expand All @@ -2019,9 +2019,6 @@ describe("parseFocusManifest settings override + resolveEffectiveSettings", () =
publicSignalLevel: "minimal",
checkRunMode: "enabled",
checkRunDetailLevel: "standard",
gateCheckMode: "enabled",
// #4618: gateCheckMode is deprecated -- setting it alone (no explicit reviewCheckMode) still derives
// reviewCheckMode, so its historical effect on the actual publish authority is preserved.
reviewCheckMode: "required",
linkedIssueGateMode: "block",
duplicatePrGateMode: "off",
Expand Down Expand Up @@ -2519,18 +2516,23 @@ describe("parseFocusManifest settings override + resolveEffectiveSettings", () =
});

// #4618/#5373: the RepositorySettings.gateCheckMode field (a computed read-back of reviewCheckMode) was
// removed entirely in #5373 -- resolveEffectiveSettings no longer derives or exposes it. The yml
// settings.gateCheckMode key still parses at the gittensory-engine layer (back-compat, tracked separately
// for removal), always resolving to reviewCheckMode rather than being trusted as its own source of truth.
describe("settings.gateCheckMode back-compat parsing (#4618)", () => {
it("settings.gateCheckMode alone (no reviewCheckMode) derives reviewCheckMode, keeping its historical effect", () => {
// removed entirely in #5373, including the gittensory-engine yml-parsing layer's settings.gateCheckMode
// back-compat key (#5373 stage 2.10) -- it is now a fully unrecognized settings key, parsed into nothing
// and deriving nothing. resolveEffectiveSettings no longer derives or exposes the field either.
describe("settings.gateCheckMode is a fully removed, inert key (#4618/#5373)", () => {
it("settings.gateCheckMode alone no longer derives reviewCheckMode (back-compat removed)", () => {
const enabled = parseFocusManifest({ settings: { gateCheckMode: "enabled" } });
expect(enabled.settings.reviewCheckMode).toBe("required");
expect(enabled.settings.reviewCheckMode).toBeUndefined();
const off = parseFocusManifest({ settings: { gateCheckMode: "off" } });
expect(off.settings.reviewCheckMode).toBe("disabled");
expect(off.settings.reviewCheckMode).toBeUndefined();
});

it("an explicit settings.reviewCheckMode wins over settings.gateCheckMode when both are set", () => {
it("settings.gateCheckMode is not parsed into the output settings object at all", () => {
const m = parseFocusManifest({ settings: { gateCheckMode: "enabled" } });
expect(m.settings).not.toHaveProperty("gateCheckMode");
});

it("an explicit settings.reviewCheckMode is honored regardless of a settings.gateCheckMode also present", () => {
const m = parseFocusManifest({ settings: { gateCheckMode: "off", reviewCheckMode: "visible" } });
expect(m.settings.reviewCheckMode).toBe("visible");
});
Expand Down
4 changes: 2 additions & 2 deletions test/unit/gate-check-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ describe(".gittensory.yml settings override (resolveEffectiveSettings)", () => {
it("overlays the generic settings: block over DB, and gate: wins for gate fields", () => {
const eff = resolveEffectiveSettings(
settings({ commentMode: "off", publicSurface: "off", reviewCheckMode: "disabled", linkedIssueGateMode: "off" }),
parseFocusManifest({ settings: { commentMode: "all_prs", publicSurface: "comment_only", gateCheckMode: "enabled", linkedIssueGateMode: "advisory" }, gate: { linkedIssue: "block" } }),
parseFocusManifest({ settings: { commentMode: "all_prs", publicSurface: "comment_only", reviewCheckMode: "required", linkedIssueGateMode: "advisory" }, gate: { linkedIssue: "block" } }),
);
expect(eff.commentMode).toBe("all_prs"); // settings: override
expect(eff.publicSurface).toBe("comment_only"); // settings: override
expect(eff.reviewCheckMode).toBe("required"); // settings.gateCheckMode: enabled -> reviewCheckMode: required (engine-level back-compat parse, #5373 stage 2.10)
expect(eff.reviewCheckMode).toBe("required"); // settings: override
expect(eff.linkedIssueGateMode).toBe("block"); // gate: wins over settings:
});

Expand Down