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 501d4a1af6..6f8302c993 100644 --- a/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx +++ b/apps/gittensory-ui/src/routes/docs.self-hosting-configuration.tsx @@ -480,10 +480,16 @@ features: regardless of this setting. Default false.

- blockedPaths (top-level, alongside wantedPaths) — globs off-limits - to contributors. Touching one yields a manifest_blocked_path finding, - enforceable when gate.manifestPolicy: block is set. Default []{" "} - (nothing blocked). + 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.{" "} + 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).

settings anti-abuse block

@@ -557,6 +563,23 @@ features: validatorId: my-registry-validator # Optional identifier for a custom per-entry validator. Default: none.`} /> +

repoDocGeneration

+

+ Lets gittensory open a pull request that refreshes this repo's own{" "} + AGENTS.md/CLAUDE.md (and, additively, a skill file) on a schedule + — never a direct commit. Disabled by default: an unconfigured repo, or an explicit{" "} + enabled: false, means no repo-doc refresh ever runs for it. +

+ +

Instance-wide write switches (SELFHOST_DEPLOYMENT_MODE)

SELFHOST_DEPLOYMENT_MODE forces write suppression for the whole instance, diff --git a/src/selfhost/config-lint.ts b/src/selfhost/config-lint.ts index 989f824263..2ff0af08ef 100644 --- a/src/selfhost/config-lint.ts +++ b/src/selfhost/config-lint.ts @@ -15,6 +15,7 @@ const TOP_LEVEL_FIELDS = [ "review", "features", "contentLane", + "repoDocGeneration", ] as const; const TOP_LEVEL_FIELD_SET = new Set(TOP_LEVEL_FIELDS); diff --git a/test/unit/selfhost-config-lint.test.ts b/test/unit/selfhost-config-lint.test.ts index c8f9d0c9b4..87c1d4d4cb 100644 --- a/test/unit/selfhost-config-lint.test.ts +++ b/test/unit/selfhost-config-lint.test.ts @@ -32,11 +32,13 @@ features: contentLane: entryFileGlob: data/*.json collectionField: records +repoDocGeneration: + enabled: true `); expect(result.ok).toBe(true); expect(result.warnings).toEqual([]); - expect(result.summary).toBe("Manifest parsed 12 recognized fields."); + expect(result.summary).toBe("Manifest parsed 13 recognized fields."); expect(result.recognizedFields).toEqual([ "wantedPaths", "preferredLabels", @@ -50,11 +52,23 @@ contentLane: "review", "features", "contentLane", + "repoDocGeneration", ]); expect(JSON.stringify(result)).not.toContain("private maintainer note"); expect(JSON.stringify(result)).not.toContain("operator-only"); }); + it("REGRESSION: recognizes a standalone repoDocGeneration: block instead of flagging it as unknown", () => { + // repoDocGeneration is a fully real, actively-parsed top-level manifest field (#3002) that was missing from + // this linter's TOP_LEVEL_FIELDS allowlist -- a self-host operator using it got a false "unknown top-level + // field" warning even though the field works correctly. + const result = lintManifestText("repoDocGeneration:\n enabled: true\n scope: [agents]\n"); + + expect(result.ok).toBe(true); + expect(result.warnings).toEqual([]); + expect(result.recognizedFields).toEqual(["repoDocGeneration"]); + }); + it("flags legacy blockedPaths with a migration-specific warning, not the generic unknown-field message", () => { const result = lintManifestText("wantedPaths: [src/]\nblockedPaths: [dist/]\n");