From 1c29a6bef6b3738bb71bca7a3bf2250b8dd82181 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Wed, 8 Jul 2026 04:26:50 -0700 Subject: [PATCH] feat(review): register e2eTests as the sixth converged-feature key Extends the existing rag/reputation/unifiedComment/safety/grounding converged-feature registry with a new e2eTests key (env kill-switch -> per-repo features override -> allowlist default), gating the upcoming AI-generated E2E test coverage feature (#4189). Plain symmetric override, no force-on/force-off asymmetry needed. Wires the new GITTENSORY_REVIEW_E2E_TESTS flag through wrangler.jsonc, env.d.ts, and the regenerated worker-configuration.d.ts, and documents it in the public/self-host config examples and the docs site's feature-flag pages. Closes #4190, #4192 (the originally separate resolver-gate issue collapses into this one: every other converged feature is resolved directly via resolveConvergedFeature/ convergedFeatureActive at call sites, with no per-feature wrapper, so e2eTests follows that same established shape). --- .gittensory.yml.example | 9 ++++++--- .../src/routes/docs.privacy-security.tsx | 1 + apps/gittensory-ui/src/routes/docs.tuning.tsx | 6 ++++++ config/examples/gittensory.full.yml | 9 ++++++--- config/examples/global.gittensory.yml | 8 ++++++++ config/examples/repo-override.gittensory.yml | 7 +++++++ .../gittensory-engine/src/focus-manifest.ts | 8 ++++++-- src/env.d.ts | 4 ++++ src/review/e2e-test-gen-wire.ts | 16 +++++++++++++++ src/review/feature-activation.ts | 2 ++ test/unit/e2e-test-gen-wiring.test.ts | 20 +++++++++++++++++++ test/unit/feature-activation.test.ts | 11 +++++++++- test/unit/focus-manifest.test.ts | 3 ++- worker-configuration.d.ts | 4 +++- wrangler.jsonc | 4 ++++ 15 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 src/review/e2e-test-gen-wire.ts create mode 100644 test/unit/e2e-test-gen-wiring.test.ts diff --git a/.gittensory.yml.example b/.gittensory.yml.example index adc818c6b2..0a21e37b64 100644 --- a/.gittensory.yml.example +++ b/.gittensory.yml.example @@ -1046,18 +1046,21 @@ settings: # auto_pause_after_reviewed_commits: 3 # Per-repo activation overrides for the converged review features that ship behind a deployment-wide -# GITTENSORY_REVIEW_* env kill-switch (rag/reputation/unifiedComment/safety/grounding). Each key is `true` -# (force on for this repo, subject to the env flag still being enabled), `false` (force off), or omitted +# GITTENSORY_REVIEW_* env kill-switch (rag/reputation/unifiedComment/safety/grounding/e2eTests). Each key is +# `true` (force on for this repo, subject to the env flag still being enabled), `false` (force off), or omitted # (falls back to the GITTENSORY_REVIEW_REPOS allowlist default -- an operator who sets nothing keeps today's # behavior). Exception: `safety` is force-on-only -- an untrusted repo-controlled `false` is treated as "no # opinion" rather than an active force-off (#2269), since a lower-trust actor must never be able to silently -# defeat the operator's own security-hardening enablement. +# defeat the operator's own security-hardening enablement. `e2eTests` (#4190) is a plain symmetric override +# like rag/reputation/unifiedComment -- generating AI test content carries no security-hardening rationale to +# protect from a repo-controlled override, so there's no force-on/force-off asymmetry here. # features: # rag: true # reputation: false # unifiedComment: true # safety: true # grounding: true +# e2eTests: false # Registry-review lane (#2435): lets a self-hosted maintainer point gittensory at their OWN structured # registry (e.g. a subnet/plugin/package catalog) without a gittensory code change -- reviewing additions diff --git a/apps/gittensory-ui/src/routes/docs.privacy-security.tsx b/apps/gittensory-ui/src/routes/docs.privacy-security.tsx index 6eb7ee1251..780fa86183 100644 --- a/apps/gittensory-ui/src/routes/docs.privacy-security.tsx +++ b/apps/gittensory-ui/src/routes/docs.privacy-security.tsx @@ -95,6 +95,7 @@ GITTENSORY_REVIEW_INLINE_COMMENTS="true" # diff-anchored inline PR revie GITTENSORY_REVIEW_FIX_HANDOFF="true" # machine-readable fix-handoff block (contributor-run) GITTENSORY_REVIEW_PLANNER="true" # @gittensory plan on-demand implementation plan GITTENSORY_REVIEW_SCREENSHOTS="true" # before/after visual capture for UI changes +GITTENSORY_REVIEW_E2E_TESTS="true" # AI-generated E2E test coverage (needs features.e2eTests too) # Global (cron / endpoint) flags, not scoped by GITTENSORY_REVIEW_REPOS. GITTENSORY_REVIEW_OPS="true" # read-only anomaly scan + outcome stats endpoint diff --git a/apps/gittensory-ui/src/routes/docs.tuning.tsx b/apps/gittensory-ui/src/routes/docs.tuning.tsx index 7a3df1a71c..f24df09925 100644 --- a/apps/gittensory-ui/src/routes/docs.tuning.tsx +++ b/apps/gittensory-ui/src/routes/docs.tuning.tsx @@ -132,6 +132,12 @@ function Tuning() { files, so the model verifies claims against reality instead of predicting CI or flagging symbols defined just outside the diff hunk. Per-PR. +
  • + GITTENSORY_REVIEW_E2E_TESTS — master kill-switch for the opt-in, + maintainer-triggered AI-generated E2E test coverage feature. Off by default; a repo also + needs its own features.e2eTests: true override in{" "} + .gittensory.yml before the feature is active for it. Per-PR. +
  • GITTENSORY_REVIEW_RAG — retrieval-augmented context: queries the codebase vector index for related code and docs (callers, related modules, existing conventions) diff --git a/config/examples/gittensory.full.yml b/config/examples/gittensory.full.yml index 101edfa043..09ebb04588 100644 --- a/config/examples/gittensory.full.yml +++ b/config/examples/gittensory.full.yml @@ -1059,18 +1059,21 @@ settings: # auto_pause_after_reviewed_commits: 3 # Per-repo activation overrides for the converged review features that ship behind a deployment-wide -# GITTENSORY_REVIEW_* env kill-switch (rag/reputation/unifiedComment/safety/grounding). Each key is `true` -# (force on for this repo, subject to the env flag still being enabled), `false` (force off), or omitted +# GITTENSORY_REVIEW_* env kill-switch (rag/reputation/unifiedComment/safety/grounding/e2eTests). Each key is +# `true` (force on for this repo, subject to the env flag still being enabled), `false` (force off), or omitted # (falls back to the GITTENSORY_REVIEW_REPOS allowlist default -- an operator who sets nothing keeps today's # behavior). Exception: `safety` is force-on-only -- an untrusted repo-controlled `false` is treated as "no # opinion" rather than an active force-off (#2269), since a lower-trust actor must never be able to silently -# defeat the operator's own security-hardening enablement. +# defeat the operator's own security-hardening enablement. `e2eTests` (#4190) is a plain symmetric override +# like rag/reputation/unifiedComment -- generating AI test content carries no security-hardening rationale to +# protect from a repo-controlled override, so there's no force-on/force-off asymmetry here. # features: # rag: true # reputation: false # unifiedComment: true # safety: true # grounding: true +# e2eTests: false # Registry-review lane (#2435): lets a self-hosted maintainer point gittensory at their OWN structured # registry (e.g. a subnet/plugin/package catalog) without a gittensory code change -- reviewing additions diff --git a/config/examples/global.gittensory.yml b/config/examples/global.gittensory.yml index b177de2284..0e686cf0e8 100644 --- a/config/examples/global.gittensory.yml +++ b/config/examples/global.gittensory.yml @@ -68,3 +68,11 @@ settings: reviewNagCooldownDays: 5 reviewNagMonitoredMentions: - your-maintainer-login + +# Converged-feature activation shared by every repo unless a per-repo file overrides a key (#4190). Each key +# still needs its own deployment-wide GITTENSORY_REVIEW_* env flag ON before this block has any effect at all +# — this section only controls the PER-REPO default once the operator has already turned a feature on +# fleet-wide. `e2eTests` gates the opt-in AI-generated E2E test coverage feature (epic #4189); leaving it +# false/omitted here keeps every repo dark by default until a per-repo file opts in. +features: + e2eTests: false diff --git a/config/examples/repo-override.gittensory.yml b/config/examples/repo-override.gittensory.yml index 5ed8058139..f264fbae87 100644 --- a/config/examples/repo-override.gittensory.yml +++ b/config/examples/repo-override.gittensory.yml @@ -43,3 +43,10 @@ settings: # `autonomy.close: auto`) but applies no label when doing so, e.g. because this repo's own # `gittensor:*` label taxonomy already covers it. Omit to inherit the global/default label name. contributorCapLabel: null + +# Unlike wantedPaths above, `features:` is a nested MAPPING, not an array — it deep-merges KEY BY KEY over the +# global default, so overriding e2eTests here doesn't disturb any other converged-feature key the global file +# sets. This repo opts into AI-generated E2E test coverage (#4190/#4189); still requires the operator's +# GITTENSORY_REVIEW_E2E_TESTS env flag to be on fleet-wide, or this override has no effect (master kill-switch). +features: + e2eTests: true diff --git a/packages/gittensory-engine/src/focus-manifest.ts b/packages/gittensory-engine/src/focus-manifest.ts index 7cbbb5e461..f8f5a420e6 100644 --- a/packages/gittensory-engine/src/focus-manifest.ts +++ b/packages/gittensory-engine/src/focus-manifest.ts @@ -207,8 +207,11 @@ export type CopycatGateMode = "off" | "warn" | "label" | "block"; // outside this block, as its own top-level `review.selftune` field below — it has no `GITTENSORY_REVIEW_REPOS` // allowlist to fall back to (its own repo scoping is `isAgentConfigured`, a different consent boundary), so it // doesn't fit this resolver's env-kill-switch → override → allowlist-default shape; see `selfTuneRepos` in -// `review/selftune-wire.ts`. -export const CONVERGED_FEATURE_KEYS = ["rag", "reputation", "unifiedComment", "safety", "grounding"] as const; +// `review/selftune-wire.ts`. `e2eTests` (#4190, part of the #4189 E2E-test-generation epic) fits this shape +// exactly as a plain symmetric override — unlike `safety`/`grounding` it has no force-on-only or force-off-only +// floor/ceiling, since AI-generated test content carries no security-hardening or full-file-fetch rationale to +// protect from a repo-controlled override. +export const CONVERGED_FEATURE_KEYS = ["rag", "reputation", "unifiedComment", "safety", "grounding", "e2eTests"] as const; export type ConvergedFeatureKey = (typeof CONVERGED_FEATURE_KEYS)[number]; /** Per-repo activation overrides for the converged review features (`features:` block). `true`/`false` force the @@ -885,6 +888,7 @@ const EMPTY_FEATURES_CONFIG: FocusManifestFeaturesConfig = { unifiedComment: null, safety: null, grounding: null, + e2eTests: null, }; const EMPTY_CONTENT_LANE_CONFIG: FocusManifestContentLaneConfig = { diff --git a/src/env.d.ts b/src/env.d.ts index 38c67fbfed..2781a810cc 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -219,6 +219,10 @@ declare global { * claims against reality instead of predicting CI / flagging symbols defined just outside the hunk. * Default OFF — unset/false keeps the reviewer prompt byte-identical and makes no extra GitHub fetch. */ GITTENSORY_REVIEW_GROUNDING?: string; + /** Convergence (e2eTests, #4190/#4189): master kill-switch for the opt-in, maintainer-triggered AI-generated + * E2E test coverage feature. Default OFF — unset/false the feature is never active for any repo regardless + * of a per-repo `features.e2eTests` override. */ + GITTENSORY_REVIEW_E2E_TESTS?: string; /** Convergence (reputation): when truthy, the INTERNAL-only ported submitter-reputation signal extends the * AI-spend gate — a new / burst / low-reputation submitter is downgraded to a deterministic-only review * (the AI neurons are skipped), and the per-(project, submitter) outcome is recorded after the gate diff --git a/src/review/e2e-test-gen-wire.ts b/src/review/e2e-test-gen-wire.ts new file mode 100644 index 0000000000..b5d10e4ef2 --- /dev/null +++ b/src/review/e2e-test-gen-wire.ts @@ -0,0 +1,16 @@ +// Convergence (E2E test generation) wiring (#4190, part of the #4189 epic): the master kill-switch for the +// `e2eTests` converged feature — an opt-in capability that generates Playwright E2E tests for a PR at a +// maintainer's request. This file is deliberately minimal for now (just the env flag), mirroring the shape of +// `rag-wire.ts`/`grounding-wire.ts` at the same stage of their own rollout — the generation/render/dispatch +// logic lands in later, separate PRs (#4191-#4197) once this flag exists for them to gate on. +// +// Single env switch: GITTENSORY_REVIEW_E2E_TESTS. Default OFF (unset/"false") — when OFF the feature never +// runs anywhere, regardless of any per-repo `.gittensory.yml` override (see `resolveConvergedFeature` in +// `./feature-activation`). Truthy follows the codebase convention (`/^(1|true|yes|on)$/i`, same as +// isRagEnabled / isGroundingEnabled / isSafetyEnabled). + +/** True when E2E test generation is enabled at the deployment level. Flag-OFF (default) → the feature is + * never active for any repo, regardless of a per-repo `features.e2eTests` override. */ +export function isE2eTestGenerationEnabled(env: { GITTENSORY_REVIEW_E2E_TESTS?: string | undefined }): boolean { + return /^(1|true|yes|on)$/i.test(env.GITTENSORY_REVIEW_E2E_TESTS ?? ""); +} diff --git a/src/review/feature-activation.ts b/src/review/feature-activation.ts index 43d6f559ed..885f0de643 100644 --- a/src/review/feature-activation.ts +++ b/src/review/feature-activation.ts @@ -19,6 +19,7 @@ // `resolveConvergedFeature` is the pure core (takes the already-loaded manifest). `convergedFeatureActive` is the // async convenience that loads the cached focus manifest itself — used at call sites that don't already hold one. import { isConvergenceRepoAllowed } from "./cutover-gate"; +import { isE2eTestGenerationEnabled } from "./e2e-test-gen-wire"; import { isGroundingEnabled } from "./grounding-wire"; import { isRagEnabled } from "./rag-wire"; import { isReputationEnabled } from "./reputation-wire"; @@ -34,6 +35,7 @@ const FEATURE_GLOBAL_FLAG: Record boolean> = unifiedComment: isUnifiedReviewCommentEnabled, safety: isSafetyEnabled, grounding: isGroundingEnabled, + e2eTests: isE2eTestGenerationEnabled, }; /** diff --git a/test/unit/e2e-test-gen-wiring.test.ts b/test/unit/e2e-test-gen-wiring.test.ts new file mode 100644 index 0000000000..2670b4e353 --- /dev/null +++ b/test/unit/e2e-test-gen-wiring.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, it } from "vitest"; +import { isE2eTestGenerationEnabled } from "../../src/review/e2e-test-gen-wire"; + +describe("isE2eTestGenerationEnabled — the e2eTests converged-feature master kill-switch", () => { + it("is off when the env flag is unset (the nullish fallback branch)", () => { + expect(isE2eTestGenerationEnabled({ GITTENSORY_REVIEW_E2E_TESTS: undefined })).toBe(false); + expect(isE2eTestGenerationEnabled({})).toBe(false); + }); + + it("is off for an explicit falsy-looking value", () => { + expect(isE2eTestGenerationEnabled({ GITTENSORY_REVIEW_E2E_TESTS: "false" })).toBe(false); + expect(isE2eTestGenerationEnabled({ GITTENSORY_REVIEW_E2E_TESTS: "0" })).toBe(false); + }); + + it("is on for every truthy-string spelling, case-insensitively (the present branch)", () => { + for (const value of ["1", "true", "TRUE", "yes", "YES", "on", "On"]) { + expect(isE2eTestGenerationEnabled({ GITTENSORY_REVIEW_E2E_TESTS: value })).toBe(true); + } + }); +}); diff --git a/test/unit/feature-activation.test.ts b/test/unit/feature-activation.test.ts index ff1755c064..8158d5d54b 100644 --- a/test/unit/feature-activation.test.ts +++ b/test/unit/feature-activation.test.ts @@ -13,13 +13,22 @@ const FLAG: Record = { unifiedComment: "GITTENSORY_REVIEW_UNIFIED_COMMENT", safety: "GITTENSORY_REVIEW_SAFETY", grounding: "GITTENSORY_REVIEW_GROUNDING", + e2eTests: "GITTENSORY_REVIEW_E2E_TESTS", }; function env(overrides: Record): Env { return overrides as unknown as Env; } function manifestWith(features: Partial>): Pick { - const base = { present: false, rag: null, reputation: null, unifiedComment: null, safety: null, grounding: null } as FocusManifest["features"]; + const base = { + present: false, + rag: null, + reputation: null, + unifiedComment: null, + safety: null, + grounding: null, + e2eTests: null, + } as FocusManifest["features"]; return { features: { ...base, ...features, present: Object.keys(features).length > 0 } }; } diff --git a/test/unit/focus-manifest.test.ts b/test/unit/focus-manifest.test.ts index 458e485ae5..f744174e5c 100644 --- a/test/unit/focus-manifest.test.ts +++ b/test/unit/focus-manifest.test.ts @@ -401,6 +401,7 @@ describe(".gittensory.yml.example field-exhaustiveness (#1670)", () => { unifiedComment: "unifiedComment:", safety: "safety:", grounding: "grounding:", + e2eTests: "e2eTests:", } satisfies Record, string>; it.each(Object.entries(FEATURES_FIELD_TOKENS))("documents features.%s", (_field, token) => { @@ -805,7 +806,7 @@ describe("compileFocusManifestPolicy", () => { gate: { present: false, enabled: null, checkMode: null, pack: null, linkedIssue: null, duplicates: null, readinessMode: null, readinessMinScore: null, slopMode: null, slopMinScore: null, slopAiAdvisory: null, sizeMode: null, lockfileIntegrityMode: null, aiReviewMode: null, aiReviewByok: null, aiReviewProvider: null, aiReviewModel: null, aiReviewAllAuthors: null, aiReviewCloseConfidence: null, aiReviewCombine: null, aiReviewOnMerge: null, aiReviewReviewers: null, mergeReadiness: null, selfAuthoredLinkedIssue: null, linkedIssueSatisfaction: null, manifestPolicy: null, dryRun: null, firstTimeContributorGrace: null, premergeContentRecheck: null, requireFreshRebaseWindowMinutes: null, claMode: null, claConsentPhrase: null, claCheckRunName: null, claCheckRunAppSlug: null, expectedCiContexts: null, aiJudgmentBlockersMode: null, copycatMode: null, copycatMinScore: null }, settings: {}, review: { present: false, footerText: null, note: null, fields: {}, enrichmentAnalyzers: {}, profile: null, tone: null, securityFocus: null, inlineComments: null, fixHandoff: null, autoMergeSummary: null, suggestions: null, changedFilesSummary: null, effortScore: null, impactMap: null, cultureProfile: null, selftune: null, reviewMemory: null, findingCategories: null, inlineCommentsPerCategory: null, minFindingSeverity: null, maxFindings: { blockers: null, nits: null }, commentVerbosity: null, pathInstructions: [], instructions: null, excludePaths: [], pathFilters: [], preMergeChecks: [], autoReview: { ...EMPTY_AUTO_REVIEW_CONFIG }, labelingRules: [], aiModel: { ...EMPTY_SELF_HOST_AI_MODEL_CONFIG }, visual: { ...EMPTY_VISUAL_CONFIG }, linkedIssueSatisfaction: null, sharedConfigSource: null }, - features: { present: false, rag: null, reputation: null, unifiedComment: null, safety: null, grounding: null }, + features: { present: false, rag: null, reputation: null, unifiedComment: null, safety: null, grounding: null, e2eTests: null }, contentLane: { present: false, entryFileGlob: null, providerFileGlob: null, artifactGlob: null, collectionField: null, maxAppendedEntries: null, duplicateKeyFields: [], validatorId: null }, repoDocGeneration: { present: false, enabled: false, scope: ["agents"], allowOverwriteExisting: false, refreshIntervalDays: 7 }, reviewRecap: { present: false, enabled: false, cadenceDays: 7 }, diff --git a/worker-configuration.d.ts b/worker-configuration.d.ts index 1c8177255d..c5fdeacf24 100644 --- a/worker-configuration.d.ts +++ b/worker-configuration.d.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// Generated by Wrangler by running `wrangler types` (hash: 2c9ae2779b21d678e1d0399a18829278) +// Generated by Wrangler by running `wrangler types` (hash: 84bd36440b87bba963f47944ddef154d) // Runtime types generated with workerd@1.20260701.1 2026-05-28 nodejs_compat interface __BaseEnv_Env { DB: D1Database; @@ -22,6 +22,7 @@ interface __BaseEnv_Env { GITTENSORY_REVIEW_SAFETY: "false"; GITTENSORY_REVIEW_SCREENSHOTS: "false"; GITTENSORY_REVIEW_GROUNDING: "false"; + GITTENSORY_REVIEW_E2E_TESTS: "false"; GITTENSORY_REVIEW_REPUTATION: "false"; GITTENSORY_REVIEW_OPS: "false"; GITTENSORY_SWEEP_WATCHDOG: "false"; @@ -75,6 +76,7 @@ declare namespace NodeJS { | "GITTENSORY_REVIEW_CONTENT_LANE" | "GITTENSORY_REVIEW_CULTURE_PROFILE" | "GITTENSORY_REVIEW_DRAFT" + | "GITTENSORY_REVIEW_E2E_TESTS" | "GITTENSORY_REVIEW_GROUNDING" | "GITTENSORY_REVIEW_IMPACT_MAP" | "GITTENSORY_REVIEW_INLINE_COMMENTS" diff --git a/wrangler.jsonc b/wrangler.jsonc index 5d673cee9e..51bb085b28 100644 --- a/wrangler.jsonc +++ b/wrangler.jsonc @@ -59,6 +59,10 @@ // post-change content of the changed files, so a non-frontier model verifies claims instead of guessing. // Default OFF — flag-OFF keeps the reviewer prompt byte-identical and makes no extra GitHub fetch. "GITTENSORY_REVIEW_GROUNDING": "false", + // Convergence (e2eTests, #4190/#4189): master kill-switch for the opt-in, maintainer-triggered AI-generated + // E2E test coverage feature. Default OFF — flag-OFF the feature is never active for any repo regardless of + // a per-repo features.e2eTests override. + "GITTENSORY_REVIEW_E2E_TESTS": "false", // Convergence (reputation): factor the INTERNAL-only ported submitter-reputation signal into the AI-spend // gate — a new / burst / low-reputation submitter is downgraded to a deterministic-only review (AI neurons // skipped), and the per-(project, submitter) outcome is recorded after the gate decides. The reputation is