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
Original file line number Diff line number Diff line change
Expand Up @@ -480,10 +480,16 @@ features:
regardless of this setting. Default <code>false</code>.
</p>
<p>
<code>blockedPaths</code> (top-level, alongside <code>wantedPaths</code>) — globs off-limits
to contributors. Touching one yields a <code>manifest_blocked_path</code> finding,
enforceable when <code>gate.manifestPolicy: block</code> is set. Default <code>[]</code>{" "}
(nothing blocked).
<code>blockedPaths</code> (top-level, alongside <code>wantedPaths</code>) is{" "}
<strong>contributor-facing guidance only</strong> — it never blocks, holds, or produces a
gate finding. A touched path surfaces in contributor onboarding guidance and in
gittensory&apos;s own risk-reason commentary, but the gate itself never enforces it.{" "}
<strong>The only mechanism that actually holds a PR for a touched path</strong> is{" "}
<code>settings.hardGuardrailGlobs</code> (config-as-code only, described above) — a
would-merge PR that touches a configured guardrail glob is held for manual review regardless
of <code>blockedPaths</code>. A legacy top-level <code>blockedPaths</code> that once acted
as an enforcement mechanism is retired; setting it produces a migration warning pointing at{" "}
<code>settings.hardGuardrailGlobs</code>. Default <code>[]</code> (nothing listed).
</p>

<h3>settings anti-abuse block</h3>
Expand Down Expand Up @@ -557,6 +563,23 @@ features:
validatorId: my-registry-validator # Optional identifier for a custom per-entry validator. Default: none.`}
/>

<h3>repoDocGeneration</h3>
<p>
Lets gittensory open a pull request that refreshes this repo&apos;s own{" "}
<code>AGENTS.md</code>/<code>CLAUDE.md</code> (and, additively, a skill file) on a schedule
— never a direct commit. Disabled by default: an unconfigured repo, or an explicit{" "}
<code>enabled: false</code>, means no repo-doc refresh ever runs for it.
</p>
<CodeBlock
filename=".gittensory.yml"
lang="yaml"
code={`repoDocGeneration:
enabled: true # Opt in. Default: false (fully disabled).
scope: [agents] # "agents" (AGENTS.md/CLAUDE.md) and/or "skills". Default: [agents].
allowOverwriteExisting: false # Refresh a file that needs manual review to change. Default: false.
refreshIntervalDays: 7 # Minimum days between refreshes. Default: 7.`}
/>

<h2>Instance-wide write switches (SELFHOST_DEPLOYMENT_MODE)</h2>
<p>
<code>SELFHOST_DEPLOYMENT_MODE</code> forces write suppression for the whole instance,
Expand Down
1 change: 1 addition & 0 deletions src/selfhost/config-lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const TOP_LEVEL_FIELDS = [
"review",
"features",
"contentLane",
"repoDocGeneration",
] as const;

const TOP_LEVEL_FIELD_SET = new Set<string>(TOP_LEVEL_FIELDS);
Expand Down
16 changes: 15 additions & 1 deletion test/unit/selfhost-config-lint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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");

Expand Down
Loading