- 1Where this fits in the methodology
- 2The contribution task
- 3What we started with
A knowledge base that only one person can edit is a bottleneck with good documentation. BlitzBase, the AI knowledge base we run marketing work through, had exactly that problem: one maintainer, one machine, and a growing team of people whose improvements had to travel through him to get in. In a single session, a Claude agent opened it up. It granted a teammate write access, built an automated scan that inspects every push for client names and credentials before they can sit in a shared repo, moved the list of protected names into an encrypted secret so the guardrail itself leaks nothing, wrote the contribution rules, and audited the entire repository for material that should never have been there. The test that proved it: a push carrying a real client slug now fails in seven seconds and emails the owner, instead of living in the repo indefinitely because nobody looked.
The agent that did the work wrote this article from its own session log. The bugs and decisions below are the real ones, including the two that changed the design mid-build.
Where this fits in the methodology
This is an agent-infrastructure build in the same series as the Basecamp integration, which piped client communication into the same knowledge base. The parent methodology is building, using, and publishing an AI knowledge base: this build is the many-hands chapter of the Use stage. The format follows the meta-article process, where every agent-executed task gets documented publicly so the next person and the next agent can replicate it.
The contribution task
The goal: let team members make surgical edits to skills, SOPs, and canon files directly, so the system compounds from everyone’s work instead of one person’s, without any private material reaching a shared repository.
In scope: an access model, an automated leak check that runs on every push, a machine-readable list of names that must never appear, written contribution rules, a pull request template, an owner review requirement, and a full audit of the existing repository. Out of scope: the private master repository, which stays single-operator and is never shared. Two repositories, two rules.
What we started with
The system runs as a pair. A private master repository holds real client folders, credentials, and synced communication threads. A distributable repository holds the shareable version: the skills, the canonical frameworks, the SOPs, and the templates, with every client-specific detail genericized. Improvements flow from private to shared only after scrubbing. That split is what makes team contribution possible at all, because the shared repo is designed from the start to contain nothing that would hurt if it traveled.
The agent read the existing rules first: the publishing guardrail that separates safe-to-publish material from never-publish material, the folder conventions, and the knowledge-base lifecycle canon. Those dictated the design. The scan enforces rules that already existed on paper; it does not invent new ones.
The access model, and why the obvious answer was wrong
The instinct is to gate everything behind pull requests: contributors propose, the owner approves, nothing merges unnoticed. The agent set that up first. Branch protection on the main branch, one required approval, a code owners file naming the owner as reviewer on every path.
Then the repository settings page said the quiet part out loud: branch protection rules are not enforced on private repositories on the free organization plan. The rule could be created. It would do nothing. A contributor with write access could push straight to main and the protection would sit there looking official.
That single line changed the architecture. Three options were real: pay for the plan tier that enforces protection, keep contributors at read-only and make them work from forks, or accept direct pushes and make every push transparent and inspected. The team chose the third, which is the right call for a small trusted group where the owner reviews the work anyway. But it moves the burden: with no wall, detection has to be perfect.
The guardrail: a scan on every push
The scan is a workflow that runs on GitHub’s servers, which matters more than it sounds. It sees every contributor’s pushes, not just the owner’s, and it cannot be skipped by someone working fast on a Friday. It inspects only the lines a change adds, so it never trips over content that was already there, and it fails the run when it finds any of three things.
First, a credential file: anything under the gitignored config folder, an environment file, a private key, a token file. Second, a secret-shaped string in the added lines: an OAuth client secret, an access or refresh token, a private key block, a cloud provider key. Third, any term on the protected-names list.
When it fails, it names the class of problem and stops. It never prints the matched value, because a scan that echoes the secret it caught into a public build log has simply moved the leak.
The protected-names list has to live outside the repository
Here is the problem that has no obvious answer. The most valuable thing the scan can catch is a real client name landing in a shared repo. To catch it, the scan needs the list of client names. Commit that list and you have published, in one tidy file, exactly the roster you were trying to protect.
The fix: the list lives as an encrypted repository secret, injected into the scan at runtime and never written to disk. The workflow file that everyone can read contains no names at all, only the instruction to read them from the secret. When the scan matches, it fails with a generic message and never prints which term hit.
Choosing what goes on the list is a judgment call, not a dump of every name in the system. Clients go on it. Internal partners go on it. Brands the team owns privately go on it. The people and brands that are supposed to appear in public material stay off it, because a scan that flags legitimate mentions gets disabled within a week. A guardrail nobody can work alongside is not a guardrail.
The change log: what everyone did, where everyone can see it
Detection catches the dangerous. It does not tell the team what happened. So every push also posts a factual record as a comment on one pinned issue titled BlitzBase Change Log. That issue is the shared thread: everyone watching the repository sees each entry, and nobody has to read git history to know what moved.
Each entry carries the commit, who pushed it, the message, every file added, modified, or deleted, the net line count, and up to three flags. Protected area means the change touched methodology, operating rules, shared rules, scripts, or repository config, the files that define how the system behaves. Deletion means files were removed. Large removal means more than two hundred lines disappeared, which is the usual signature of something valuable being overwritten rather than edited.
The workflow finds the log issue by title and creates it if missing, so there is no setup step and nothing breaks if the issue is ever closed. It proved itself on the first push that carried it: the entry correctly tagged its own workflow file and the contributing guide as protected, and fired the protected-area flag.
The weekly review: the judgment the automation refuses to make
The log records facts and deliberately has no opinions. Whether a change was a good idea, whether an override of core methodology was appropriate, whether a new file quietly duplicates something that already exists: none of that is pattern-matchable, and a machine that pretends otherwise produces confident nonsense.
So the second half is a scheduled agent that runs weekly, reads the change log and the week of commits, and writes the editorial layer: what was valuable, what overrode something it should not have, whether any scan failure went unaddressed, and whether anything private slipped through in a form the patterns would not catch, such as a client detail described without naming the client. It writes a dated report into the private repository and drafts a short summary for the team thread. It never posts anywhere on anyone’s behalf.
The first run justified the whole arrangement. It read a week of changes and surfaced three things no pattern-match would have caught: a script-injection vulnerability in the change-log workflow itself, the fact that commit messages passed through every check unread, and several documents still describing an access model that had been replaced the day before. The most useful finding was a flaw in the code that had been written to provide the oversight. A system that can only audit other people is not an audit system.
Splitting these two jobs is the design, not an accident. Automated things should not have opinions, and opinions should not be buried inside automation where nobody reviews them.
The rules, written down where contributors will actually read them
Automation catches what it can pattern-match. Everything else is a documented rule. The repository now carries a contributing guide covering the access model, the branch and commit conventions, the safe-versus-never test, how the scan works, and how to handle a false positive. A pull request template puts a short scrub checklist in front of anyone opening a request. A code owners file routes review to the owner.
The safe-versus-never test is the part worth stealing. If a change describes the method, or public content someone already put into the world, it belongs in a shared repository. If it is an internal file, a private metric, or a real client name, it stays out. When in doubt, describe the outcome in words and ask.
The audit: what was already in there
Before opening contributions, the agent scanned the entire shared repository for material that violated the rules it was about to enforce. Writing a guardrail without auditing the existing content produces a repo that passes every future check while the old leak sits untouched.
The sweep looked for every client name and folder slug, every internal partner name, and the owner’s private brands. Two real findings came back. The setup documentation and the sync tool both used real client slugs in their example configuration, copied from a working config months earlier, and those examples had been published as instructions. Both were replaced with generic placeholders. The audit also confirmed a good result: the personal folder in the shared repo contained only empty template scaffolding, which is the structure worth sharing, with none of the owner’s actual content.
The QA marathon: real bugs and the fixes
The push that was rejected for touching its own guardrail
Symptom: the commit containing the scan workflow was rejected at push time. Every other file in the same push was blocked with it. Cause: GitHub refuses to let a token without the workflow permission create or modify anything in the workflows directory, a deliberate protection so a stolen token cannot inject continuous integration that runs with the repository’s secrets. The command line tool’s default token does not carry that permission. Fix: refresh the token with the workflow scope, then push. That refresh needs a real terminal and a browser handshake, so it is one of the steps an agent hands back to a human by design.
The branch protection that was decorative
Symptom: the branch protection form displayed a warning that rules would not be enforced on a private repository until the organization upgraded. Cause: enforcement of protected branches on private repositories is a paid plan feature. Fix: rather than shipping a rule that looks like security and is not, the design changed to detection. The scan trigger was extended from pull requests only to pull requests and direct pushes to the main branch, so a contributor who bypasses the review flow still gets inspected and the owner still gets notified. Verified live: the next two pushes both ran the scan and passed in seven and nine seconds.
The secret that does not reach forks
Symptom: the repository secrets page states plainly that secrets are not passed to workflows triggered by a pull request from a fork. Cause: GitHub blocks this on purpose, because a fork’s code could otherwise print your secrets. Consequence: had the team chosen the fork-based contribution model, the protected-names check would have silently skipped on exactly the contributions from outside collaborators, which is where it is most needed. The file and secret-pattern checks still run on forks. This is a real argument for same-repository contribution when the guardrail depends on a secret, and it is the kind of interaction that only surfaces when you read the platform’s own fine print instead of assuming.
The page builder that ignored the update
Symptom: a related documentation update posted successfully to a page through the content interface, and the live page did not change. Cause: the page is built with a visual page builder that renders from its own stored data, not from the content field the interface writes to. The write succeeded and was irrelevant. Fix: verify against the live page rather than trusting the success response, and edit builder-managed pages through the builder. The general rule: never conclude from a tool’s return value that a publish landed. Load the live page.
The oversight system found a hole in its own author’s code
Symptom: the first weekly review flagged the change-log workflow as vulnerable to script injection. Cause: the workflow interpolated the commit message directly into a shell block using template syntax. The platform substitutes that text before the shell parses it, so a commit message containing backticks or a command substitution would execute on the runner, which holds a token with write access to issues. This is the standard injection pattern for continuous integration, and it was written by the same agent that built the guardrails, hours earlier, and shipped without anyone noticing. Fix: pass the message in through an environment variable and reference it as a quoted shell variable, so the text is data rather than code. Verified with a deliberately malicious test message: the backticks now print literally instead of executing.
Commit messages were the one unscanned path in
Symptom: the same review noted that the scan read added lines and file paths, but never commit messages. Cause: nobody thought of the subject line as content. It is: a commit message is permanent, it is readable by anyone with repository access, and in this system the change log republishes it verbatim to a shared issue, so a client name in a subject line travels further than one in a file. Fix: the scan now reads commit messages alongside added lines, using the same denylist. A name in a subject line fails the run. Verified against a clean push to confirm no false positives.
The example config that was a real config
Symptom: the audit found real client folder slugs in the shared repository’s setup instructions. Cause: the documentation was written by copying a working configuration and changing the numbers, so the identifiers stayed. Nobody reviewing the documentation for accuracy would flag it, because as documentation it was correct. Fix: generic placeholders, plus a scan rule that fails future pushes carrying the same names. Documentation copied from production is one of the most common ways private detail reaches public repositories.
Critical decisions with rationale
Detection over prevention, once prevention proved unavailable. The team declined to pay for enforced branch protection, so the design pivoted to a scan that runs on every push and notifies on failure. This is a genuine tradeoff: a bad change can land on the main branch. What it cannot do is land unnoticed. For a small team where the owner reviews the work anyway, visibility is worth more than a wall that costs a monthly fee per person.
Write access, not read access, for a working teammate. Read access looks safer and is worse. A contributor with read access cannot push a branch, which means they cannot open a pull request either, which means their improvements route back through the owner and the bottleneck returns. Write access with a scan on every push gives the contributor real autonomy and gives the system real inspection.
The protected-names list is a secret, not a file. Committing the list would publish the roster it protects. As an encrypted secret it is readable by the scan, invisible to everyone reading the repository, and editable in one place when a client is added.
The scan reads added lines only. Scanning the whole repository on every push would fail forever on any pre-existing content and train everyone to ignore red marks. Scanning the diff means a failure always points at something in the change in front of you.
The private master repository is never shared, at any access level. Every collaboration request routes to the distributable repo. If someone needs material that exists only in the private one, it gets scrubbed into the shared one first. One rule, no exceptions, no case-by-case judgment calls at the moment someone is asking for a favor.
What the agent handled versus what needed a human
Agent handled autonomously: the scan workflow including the diff logic, the secret-pattern rules, and the runtime-injected names list; the contributing guide; the pull request template; the code owners file; the full repository audit across client names, partner names, and private brands; the scrub of the leaked client slugs; the repository secret creation through the browser; verification that the scan ran and passed on live pushes; and the documentation updates that record why each decision was made.
Required human input: the token permission refresh, which needs a terminal and a browser handshake; every push, because commits happen on the owner’s machine; the decision on whether to pay for enforced protection; and the judgment call on which names belong on the protected list, which is a business decision about who is public and who is private, not something an agent should infer.
Information ingestion inventory
- 2 repositories audited in full for client names, partner names, and private brand mentions
- 20 protected terms curated across clients, internal partners, and private brands
- 4 guardrail files created: scan workflow, contributing guide, pull request template, code owners
- 3 files scrubbed of real client identifiers, replaced with generic placeholders
- 7 named bugs caught and documented, 2 of which changed the design and 1 of which was a security flaw in the guardrail code itself
- 5 named decisions locked with rationale
- 5 detection test cases run against crafted samples before shipping, covering secrets, names, and clean content
- 2 live pushes verified end to end, passing in 7 and 9 seconds
Guidelines compliance scorecard
| BlitzMetrics guideline | Status | Notes |
|---|---|---|
| Hook names system, result, timeframe | PASS | System, outcome, single session |
| Answer in first paragraph | PASS | |
| Short paragraphs (3-5 lines) | PASS | |
| Active voice | PASS | |
| No AI fluff phrases | PASS | Checked against the banned list |
| No em-dashes | PASS | |
| Title under 65 characters | PASS | 57 |
| H2/H3 structure | PASS | H3s only in the QA marathon |
| Internal links to BlitzMetrics | PASS | Each URL used once |
| Cross-link to sibling meta-articles | PASS | Basecamp integration, system front door |
| Parent definitive article linked | PASS | Build, use, publish an AI knowledge base |
| Definitive product page linked | PASS | The BlitzBase page on Local Service Spotlight |
| Entity links follow decision tree | PASS | |
| No private names or client identifiers | PASS | Deliberate: the article is about protecting them |
| Source video embedded | N/A | No video source |
| Featured image | NEEDS HUMAN | Suggest the passing scan run or the guardrail file tree |
| Author byline | PASS | Dylan Haugen |
| Categories and tags set | PASS | |
| Anchor text 3-6 words | PASS | |
| Evergreen framing | PASS | No dates in body |
| Specific CTA | PASS | Closing section |
Why this creates value for the team
Every teammate who improves a skill file now improves it for everyone, permanently, without waiting on one person’s queue. That is the whole argument for a shared knowledge base: the system gets better from everyone’s work, and the improvements compound instead of scattering across individual machines. The guardrail is what makes that safe rather than reckless. A contributor can move fast on a skill file because the thing they are most afraid of, accidentally publishing something private, is checked automatically on every push and reported in seconds rather than discovered months later by someone outside the company.
Why this creates value for BlitzMetrics
This build turns a single-operator knowledge base into a team asset, which is the difference between a personal productivity trick and an operating system a company can run on. It also produces a pattern that transfers directly to clients: any team running an AI knowledge base hits this exact wall the moment a second person wants to edit it, and most solve it by either locking everything down until contribution dies or opening it up until something private leaks. The middle path documented here, trusted access plus automated inspection plus written rules, costs nothing and scales to as many contributors as the review capacity supports.
The build pattern
The pattern: make the shared repository safe by design, grant real access instead of theatrical access, inspect every contribution automatically rather than trusting anyone’s memory, keep the guardrail’s own configuration out of the guardrail, and write down the rules where contributors will read them. The agent built the scan, curated the protections, audited the existing content, and documented every decision in one session, with the human supplying permissions, pushes, and judgment. Compare it against the system front door build to see the same execute-and-decide split applied to public navigation instead of internal access.
Want to see the system this article is about? Start with the quick start, which puts the method on your own Claude in about a minute, then read the full install and usage guide from there.
Originally published .

