From 745888422082d2f0337570291291432e3274b517 Mon Sep 17 00:00:00 2001
From: JSONbored <49853598+JSONbored@users.noreply.github.com>
Date: Sun, 12 Jul 2026 06:26:57 -0700
Subject: [PATCH 1/2] fix(config): stop documenting the retired blockedPaths
key as a live feature
blockedPaths was fully retired from the FocusManifest parser in #2974
(2026-07-04) -- it produces zero findings and is not enforceable under
any gate.manifestPolicy mode. That retirement commit missed the two
checked-in bootstrap templates (.gittensory.yml.example,
config/examples/gittensory.full.yml), which kept documenting it with
example values and false claims that it feeds guidance/becomes an
enforceable blocker. This is very likely why all 3 live self-hosted
repos still carry a dead blockedPaths: [] key today.
Fixes the false claims in both templates (byte-synced, both edited
identically), fixes the self-hosting docs page's self-contradicting
paragraph, and extends config-templates.test.ts to also run
lintManifestText (the only function with the retired-field check) so
a retired field reintroduced into a shipped template fails CI
automatically going forward -- the previous zero-warnings test used
the lenient parser, which structurally cannot catch this class of bug.
Also removes the dead "manifest_blocked_path" string from
processors.ts's policyCodes Set (no producer has emitted that code
since the retirement).
Refs #5294
---
.gittensory.yml.example | 25 ++++++++-----------
.../docs.self-hosting-configuration.tsx | 12 ++++-----
config/examples/gittensory.full.yml | 25 ++++++++-----------
src/queue/processors.ts | 1 -
test/unit/config-templates.test.ts | 13 ++++++++++
test/unit/queue-2.test.ts | 7 +++---
6 files changed, 44 insertions(+), 39 deletions(-)
diff --git a/.gittensory.yml.example b/.gittensory.yml.example
index d76e7049e1..e354ff6d9f 100644
--- a/.gittensory.yml.example
+++ b/.gittensory.yml.example
@@ -48,24 +48,21 @@
# ----------------------------------------------------------------------------
# 1. FOCUS / GUARDRAILS (focus manifest)
# ----------------------------------------------------------------------------
-# Declares the repo's work areas and off-limits paths. wantedPaths/blockedPaths feed advisory-only
-# guidance findings; testExpectations/linkedIssuePolicy feed manifest_missing_tests and
-# manifest_linked_issue_required, which — when `gate.manifestPolicy: block` is set below — can become
-# enforceable blockers. Hard path HOLDS are a separate mechanism: settings.hardGuardrailGlobs, below.
+# Declares the repo's work areas. wantedPaths feeds advisory-only guidance findings;
+# testExpectations/linkedIssuePolicy feed manifest_missing_tests and manifest_linked_issue_required,
+# which — when `gate.manifestPolicy: block` is set below — can become enforceable blockers. Hard path
+# HOLDS are a separate mechanism: settings.hardGuardrailGlobs, below.
# Work areas the maintainer wants. PRs touching these are preferred/encouraged.
# Glob list. Default: [] (no preference).
wantedPaths:
- "src/**"
-# Paths off-limits to contributors — CONTRIBUTOR-FACING GUIDANCE ONLY. Touching one surfaces in
-# onboarding guidance and gittensory's own risk-reason commentary; it never blocks, holds, or produces
-# a gate finding, even under gate.manifestPolicy: block. The only mechanism that actually holds a PR
-# for a touched path is settings.hardGuardrailGlobs, below.
-# Glob list. Default: [] (nothing listed).
-blockedPaths:
- - "vendor/**"
- - ".github/workflows/**"
+# blockedPaths is LEGACY and fully retired (#2974, 2026-07-04): the FocusManifest parser no longer
+# reads this key at all, it produces zero findings, and it is not enforceable under any
+# gate.manifestPolicy mode. A key left over from an older config has no runtime effect other than a
+# migration warning from `npm run selfhost:config-lint`. Use settings.hardGuardrailGlobs below for
+# real, enforceable path-based holds.
# Labels the maintainer prefers on incoming PRs; a missing preferred label is
# surfaced (never blocks). String list. Default: [].
@@ -269,8 +266,8 @@ gate:
mergeReadiness: off
# Manifest-policy gate. When `block`, this repo's declared policy from
- # section 1 (blockedPaths, required linked issue, testExpectations) becomes
- # an enforceable blocker. Independent of mergeReadiness.
+ # section 1 (required linked issue, testExpectations) becomes an
+ # enforceable blocker. Independent of mergeReadiness.
# off | advisory | block. Default: off.
manifestPolicy: off
diff --git a/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx b/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx
index 601349a67b..7da2bb8bb1 100644
--- a/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx
+++ b/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx
@@ -605,15 +605,13 @@ features:
blockedPaths (top-level, alongside wantedPaths) is{" "}
- contributor-facing guidance only — it never blocks, holds, or produces a
- gate finding. A touched path surfaces in contributor onboarding guidance and in
- gittensory's own risk-reason commentary, but the gate itself never enforces it.{" "}
+ fully retired (#2974) — the FocusManifest parser no longer reads this key at
+ all, it produces zero findings, and it is not enforceable under any{" "}
+ gate.manifestPolicy mode. Setting it in a config produces only a migration
+ warning from npm run selfhost:config-lint, nothing else.{" "}
The only mechanism that actually holds a PR for a touched path is{" "}
settings.hardGuardrailGlobs (config-as-code only, described above) — a
- would-merge PR that touches a configured guardrail glob is held for manual review regardless
- of blockedPaths. A legacy top-level blockedPaths that once acted
- as an enforcement mechanism is retired; setting it produces a migration warning pointing at{" "}
- settings.hardGuardrailGlobs. Default [] (nothing listed).
+ would-merge PR that touches a configured guardrail glob is held for manual review.
settings anti-abuse block
diff --git a/config/examples/gittensory.full.yml b/config/examples/gittensory.full.yml
index db42c3d608..6c5091006d 100644
--- a/config/examples/gittensory.full.yml
+++ b/config/examples/gittensory.full.yml
@@ -62,24 +62,21 @@
# ----------------------------------------------------------------------------
# 1. FOCUS / GUARDRAILS (focus manifest)
# ----------------------------------------------------------------------------
-# Declares the repo's work areas and off-limits paths. wantedPaths/blockedPaths feed advisory-only
-# guidance findings; testExpectations/linkedIssuePolicy feed manifest_missing_tests and
-# manifest_linked_issue_required, which — when `gate.manifestPolicy: block` is set below — can become
-# enforceable blockers. Hard path HOLDS are a separate mechanism: settings.hardGuardrailGlobs, below.
+# Declares the repo's work areas. wantedPaths feeds advisory-only guidance findings;
+# testExpectations/linkedIssuePolicy feed manifest_missing_tests and manifest_linked_issue_required,
+# which — when `gate.manifestPolicy: block` is set below — can become enforceable blockers. Hard path
+# HOLDS are a separate mechanism: settings.hardGuardrailGlobs, below.
# Work areas the maintainer wants. PRs touching these are preferred/encouraged.
# Glob list. Default: [] (no preference).
wantedPaths:
- "src/**"
-# Paths off-limits to contributors — CONTRIBUTOR-FACING GUIDANCE ONLY. Touching one surfaces in
-# onboarding guidance and gittensory's own risk-reason commentary; it never blocks, holds, or produces
-# a gate finding, even under gate.manifestPolicy: block. The only mechanism that actually holds a PR
-# for a touched path is settings.hardGuardrailGlobs, below.
-# Glob list. Default: [] (nothing listed).
-blockedPaths:
- - "vendor/**"
- - ".github/workflows/**"
+# blockedPaths is LEGACY and fully retired (#2974, 2026-07-04): the FocusManifest parser no longer
+# reads this key at all, it produces zero findings, and it is not enforceable under any
+# gate.manifestPolicy mode. A key left over from an older config has no runtime effect other than a
+# migration warning from `npm run selfhost:config-lint`. Use settings.hardGuardrailGlobs below for
+# real, enforceable path-based holds.
# Labels the maintainer prefers on incoming PRs; a missing preferred label is
# surfaced (never blocks). String list. Default: [].
@@ -283,8 +280,8 @@ gate:
mergeReadiness: off
# Manifest-policy gate. When `block`, this repo's declared policy from
- # section 1 (blockedPaths, required linked issue, testExpectations) becomes
- # an enforceable blocker. Independent of mergeReadiness.
+ # section 1 (required linked issue, testExpectations) becomes an
+ # enforceable blocker. Independent of mergeReadiness.
# off | advisory | block. Default: off.
manifestPolicy: off
diff --git a/src/queue/processors.ts b/src/queue/processors.ts
index eca651be86..58de1a6252 100644
--- a/src/queue/processors.ts
+++ b/src/queue/processors.ts
@@ -7317,7 +7317,6 @@ async function maybeApplyManifestPolicyGate(
hasNoIssueRationale: hasClearNoIssueRationale(args.pr),
});
const policyCodes = new Set([
- "manifest_blocked_path",
"manifest_linked_issue_required",
"manifest_missing_tests",
]);
diff --git a/test/unit/config-templates.test.ts b/test/unit/config-templates.test.ts
index c30e7eb3ed..d5dd0600e7 100644
--- a/test/unit/config-templates.test.ts
+++ b/test/unit/config-templates.test.ts
@@ -9,6 +9,7 @@ import {
resolveReviewPromptOverrides,
reviewConfigToJson,
} from "../../src/signals/focus-manifest";
+import { lintManifestText } from "../../src/selfhost/config-lint";
// #1682: self-host operators need discoverable, copy-paste templates under config/examples/ that
// parse cleanly, stay in sync with the canonical root files, and keep the minimal starter safe.
@@ -51,6 +52,18 @@ describe("config/examples review templates (#1682)", () => {
expect(manifest.features.rag).toBeNull();
});
+ // #5294 (drift-audit roadmap #5270): parseFocusManifestContent above is the LENIENT parser (never
+ // warns on an unrecognized/retired top-level field by design) -- it structurally cannot catch a
+ // retired field like the old `blockedPaths` example creeping back into these shipped templates.
+ // lintManifestText is the ONLY function with the retired-field check (config-lint.ts's
+ // RETIRED_FIELD_MIGRATION_WARNINGS); assert it separately so a retired field reintroduced here fails
+ // CI instead of only being caught by eye.
+ it("lints gittensory.full.yml with zero warnings, including no retired top-level fields", () => {
+ const result = lintManifestText(readConfigExample("gittensory.full.yml"));
+ expect(result.warnings).toEqual([]);
+ expect(result.ok).toBe(true);
+ });
+
it("documents every shipped review.auto_review eligibility knob in gittensory.full.yml (#2055)", () => {
const full = readConfigExample("gittensory.full.yml");
for (const field of ["skip_labels", "skip_docs_only", "max_added_lines", "max_files"]) {
diff --git a/test/unit/queue-2.test.ts b/test/unit/queue-2.test.ts
index c13ac3f7f2..da4d86428d 100644
--- a/test/unit/queue-2.test.ts
+++ b/test/unit/queue-2.test.ts
@@ -3524,9 +3524,10 @@ describe("queue processors", () => {
});
// #4607 (maybeApplyManifestPolicyGate extraction): buildFocusManifestGuidance can produce findings whose
- // code is NOT one of the three enforceable manifest-policy codes (manifest_blocked_path /
- // manifest_linked_issue_required / manifest_missing_tests) -- e.g. manifest_off_focus, when wantedPaths is
- // configured and no changed path matches it. Those non-enforceable findings must be filtered out before
+ // code is NOT one of the two enforceable manifest-policy codes (manifest_linked_issue_required /
+ // manifest_missing_tests -- manifest_blocked_path was retired #2974/removed from this Set #5294) -- e.g.
+ // manifest_off_focus, when wantedPaths is configured and no changed path matches it. Those non-enforceable
+ // findings must be filtered out before
// ever reaching the advisory/gate, never published alongside an enforceable one from the same pass.
it("filters out a non-enforceable manifest finding (manifest_off_focus) while still surfacing an enforceable one", async () => {
const env = createTestEnv({ GITHUB_APP_PRIVATE_KEY: await generatePrivateKeyPem() });
From b34d2417754231d82f1c0d6806ae47897450ff2e Mon Sep 17 00:00:00 2001
From: JSONbored <49853598+JSONbored@users.noreply.github.com>
Date: Sun, 12 Jul 2026 06:56:21 -0700
Subject: [PATCH 2/2] fix(ui): prettier formatting for the blockedPaths
retirement doc fix
CI's ui:lint caught formatting the earlier commit's editor didn't
apply. No content change, whitespace wrapping only.
---
.../src/routes/docs.self-hosting-configuration.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx b/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx
index 7da2bb8bb1..a77a772954 100644
--- a/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx
+++ b/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx
@@ -605,8 +605,8 @@ features:
blockedPaths (top-level, alongside wantedPaths) is{" "}
- fully retired (#2974) — the FocusManifest parser no longer reads this key at
- all, it produces zero findings, and it is not enforceable under any{" "}
+ fully retired (#2974) — the FocusManifest parser no longer reads this key
+ at all, it produces zero findings, and it is not enforceable under any{" "}
gate.manifestPolicy mode. Setting it in a config produces only a migration
warning from npm run selfhost:config-lint, nothing else.{" "}
The only mechanism that actually holds a PR for a touched path is{" "}