From agent-almanac
Redacts reverse-engineering repos for public disclosure while preserving methodology and patterns. Uses private-public splits, deny-lists, orphan commits, and CI gates to block leaks.
npx claudepluginhub pjt222/agent-almanacThis skill is limited to using the following tools:
Split a reverse-engineering research repo into a private source-of-truth and a public-disclosure subset using a redaction checker, pattern deny-lists, and an orphan-commit publish pattern. Methodology travels; specific findings stay private.
Detects hardcoded secrets like API keys, tokens, and credentials in git repos using Gitleaks regex and entropy analysis. Guides repo scans, pre-commit hooks, CI/CD integration, audits.
Detects secrets, API keys, credentials, and sensitive data in codebases and git history before open sourcing. Guides scans with gitleaks, truffleHog, and pre-commit hooks.
Runs gitleaks scans for secret detection, validates configurations, and integrates with pre-commit hooks to prevent credential leaks in Git repos.
Share bugs, ideas, or general feedback.
Split a reverse-engineering research repo into a private source-of-truth and a public-disclosure subset using a redaction checker, pattern deny-lists, and an orphan-commit publish pattern. Methodology travels; specific findings stay private.
public/ worktree) where redacted content will be publishedBefore writing or promoting any content, sort each fact into one of four categories. The category determines whether and when it can ship.
| Category | Definition | Shareable? |
|---|---|---|
| methodology | The how of investigation, independent of any specific finding | Always |
| generic pattern | Class-level observations (e.g., "harnesses commonly use a single-prefix flag namespace") | Yes |
| version-specific finding | Concrete observation tied to a specific release (e.g., "in vN.M, the gate defaults off") | Only after the version-lag cool-off |
| live internal | Minified names, byte offsets, dark flag names, current-version gate logic, PRNG/salt constants, internal codenames | Never |
Annotate each draft section, capture log, or note with its category before reviewing for publication. A section that mixes categories splits — methodology lifts out clean, the rest stays private.
Expected: Every candidate fact has a category label. Drafts intended for the public mirror contain only methodology and generic-pattern entries (plus version-specific findings older than the cool-off).
On failure: If a fact resists categorization, treat it as a live internal by default. Re-categorize only after explicit review against the version-lag policy.
Decide up front how many versions sit between "current" and "shareable." Two is typical: current + 1 prior remain private, older patterns may be discussed. Write the policy into the private repo (e.g., REDACTION_POLICY.md) so future-you does not have to re-derive it.
# Redaction Policy
Version-lag cool-off: **2 releases**.
- Current release (vN): all version-specific findings PRIVATE.
- Previous release (vN-1): all version-specific findings PRIVATE.
- Releases vN-2 and earlier: version-specific findings may move to public draft after Step 5 review.
Source of truth for "current": output of `monitor-binary-version-baselines`.
Owner: <name>. Reviewed quarterly.
The "current" version must be empirical (read from the installed binary), not administrative. Tie the policy to the baseline scanner output rather than to a calendar.
Expected: A committed REDACTION_POLICY.md in the private repo with an explicit cool-off and an owner.
On failure: If stakeholders cannot agree on the cool-off, default to the most conservative proposal. Cool-offs can be shortened later; recalling a leak cannot.
Maintain patterns in a single executable script that is the source of truth for the redaction policy. The script lives in the private repo (tools/check-redaction.sh) and runs against the public mirror.
#!/usr/bin/env bash
set -u
PUBLIC_REPO="${1:-./public}"
LEAKS=0
PATTERNS=(
"minified identifier shape|<regex matching short bundle-style identifiers>"
"vendor-prefixed flag|<regex matching the vendor's flag prefix>"
"PRNG/salt constant|<regex matching the specific constants>"
)
for entry in "${PATTERNS[@]}"; do
desc="${entry%%|*}"
pattern="${entry##*|}"
if rg -q "$pattern" "$PUBLIC_REPO"; then
echo "LEAK: $desc"; LEAKS=$((LEAKS+1))
fi
done
exit $LEAKS
Each entry has a human-readable label and a regex. One entry per sensitive identifier shape (not per literal string — shapes survive version churn). The exit code equals the number of leaks; a clean run exits 0.
Expected: tools/check-redaction.sh ./public-mirror runs in under a second on a small repo and exits 0 when nothing matches.
On failure: If rg is unavailable, fall back to grep -rqE. If patterns are too broad (every run reports leaks), narrow them at the source rather than adding suppressions.
When a Phase 1-4 finding could leak through a draft, extend the scanner before the draft is written. Drafts are cheap; teaching the scanner new patterns is durable.
Workflow:
tools/check-redaction.sh (label + regex).This inverts the usual order: the scanner is updated first, the draft second. The scanner becomes the executable specification of "what is too sensitive to publish," and the draft cannot accidentally outpace it.
Expected: Pattern entries in tools/check-redaction.sh predate any public-mirror content that could match them. git log tools/check-redaction.sh shows scanner updates landing before related draft commits.
On failure: If scanner updates lag drafts, audit the public mirror against the new pattern immediately. Redact, then commit the scanner update with a note explaining the discovered pattern.
Define an explicit allow-list of files that sync to the public mirror. New files default to private; promotion requires redaction-check clearance.
# tools/public-allowlist.txt
README.md
LICENSE
guides/methodology-overview.md
guides/category-classification.md
docs/contributing.md
A tools/sync-to-public.sh reads the allow-list, copies only those files to the public mirror, and exits non-zero if the allow-list references a file that does not exist (catches typos).
#!/usr/bin/env bash
set -eu
PRIVATE_ROOT="${1:?private repo path required}"
PUBLIC_ROOT="${2:?public mirror path required}"
ALLOWLIST="$PRIVATE_ROOT/tools/public-allowlist.txt"
while IFS= read -r path; do
[ -z "$path" ] && continue
case "$path" in \#*) continue ;; esac
src="$PRIVATE_ROOT/$path"
dst="$PUBLIC_ROOT/$path"
if [ ! -e "$src" ]; then
echo "MISSING: $path"; exit 2
fi
mkdir -p "$(dirname "$dst")"
cp -a "$src" "$dst"
done < "$ALLOWLIST"
Promotion requires three things in order: the file is added to the allow-list, the file passes the redaction check, and a reviewer confirms the category labels from Step 1.
Expected: The public mirror contains exactly the files listed in tools/public-allowlist.txt. No file appears in the public mirror that is not on the allow-list.
On failure: If a file appears in the public mirror but is missing from the allow-list, treat it as a leak event — investigate how it arrived, then either remove it or formally promote it after redaction review.
The public mirror is a single git commit --orphan-rooted commit recreated at each publish. This prevents git log on the public repo from exposing pre-redaction drafts.
# In the public mirror (separate repo or worktree)
cd /path/to/public-mirror
git checkout --orphan publish-tmp
git rm -rf . # Clear the index
# Sync from private using the allow-list
bash /path/to/private/tools/sync-to-public.sh /path/to/private .
git add -A
git commit -m "Publish: <date>"
git branch -D main 2>/dev/null || true
git branch -m main
git push --force origin main
The public repo's git log shows exactly one commit. Prior drafts and any redaction iterations stay in the private repo's history. No git log -p, git reflog, or branch listing on the public repo can recover pre-redaction content because it was never committed there.
Expected: git log --oneline on the public mirror shows a single commit per publish. No references to the private repo's history (no parent SHAs, no merge commits, no tags from the private repo) appear.
On failure: If git push --force is rejected (branch protection), open a single-commit pull request from a clean orphan branch instead. Never solve a rejection by pushing the private history.
Run tools/check-redaction.sh on every commit to the public-sync branch. A failed check blocks the publish, not just warns.
# .github/workflows/redaction-check.yml (in the public mirror repo)
name: redaction-check
on:
push:
branches: [main, publish-*]
pull_request:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install ripgrep
run: sudo apt-get update && sudo apt-get install -y ripgrep
- name: Fetch redaction scanner
env:
GH_TOKEN: ${{ secrets.PRIVATE_REPO_TOKEN }}
run: |
gh api repos/<org>/<private-repo>/contents/tools/check-redaction.sh \
--jq .content | base64 -d > check-redaction.sh
chmod +x check-redaction.sh
- name: Run scanner
run: ./check-redaction.sh .
Two design choices here:
Expected: Pushes that introduce a deny-listed pattern fail CI; the publish does not land. Maintainers see the failing label (e.g., LEAK: vendor-prefixed flag) without seeing the regex itself.
On failure: If the private-repo token cannot be granted to the public CI, embed only a minimum-leak portion of the scanner in the public repo (broad shape patterns that do not themselves identify the vendor) and run the full scanner pre-push from the private repo.
When the scanner trips on legitimate content, prefer narrowing the pattern over adding an ignore-line. Broad deny-lists with local suppressions rot fast — six months later no one remembers why a particular line was suppressed, and the next leak slides past unnoticed.
Decision tree:
check-redaction.sh linking to the case that motivated it.# REASON: comment that states why the suppression is safe. Date the comment.# Bad — mystery suppression
echo "API endpoint pattern" >> ignore.txt
# Good — narrowed pattern with rationale
# Pattern v2: tightened from `\bgate\(` to `\bgate\(['\"][a-z]+_phase` after
# legitimate `gate(true)` calls in our own SDK examples started matching. 2026-04-15.
PATTERNS+=("vendor flag predicate|\\bgate\\(['\"][a-z]+_phase")
Expected: Each scanner pattern has zero or one inline comment explaining a tightening. Suppressions, if any, carry a date and a rationale.
On failure: If suppressions accumulate (more than one per quarter), the deny-list is mis-shaped. Schedule a redaction-policy review and rebuild the patterns from the categorized fact inventory.
Not all redaction work is incident-driven. Run a periodic sweep (monthly is typical) that re-categorizes the most recent additions to the private repo and re-runs the scanner against the public mirror. Drift catches itself before it becomes incident-grade.
Sweep checklist:
tools/check-redaction.sh against the public mirror (should still exit 0)tools/public-allowlist.txt matches the actual public-mirror file setExpected: A short sweep log per month in the private repo (e.g., sweeps/2026-04.md) with checklist outcomes and any actions taken.
On failure: If the sweep is repeatedly skipped, automate a calendar reminder. If the sweep keeps finding the same drift, the workflow upstream of it is the problem — investigate why categorization is being skipped at draft time.
tools/public-allowlist.txttools/check-redaction.sh ./public-mirror exits 0git log --oneline on the public mirror shows a single orphan commit per publishREDACTION_POLICY.md exists in the private repo with an explicit version-lag cool-offacme_widget_v3, widget_handler_42) — clearly invented, never traceable to a real product.git rebase or git filter-branch to scrub a leak in place on the public repo. Force-pushing rewritten history still leaves traces in clones and forks. The orphan-commit publish pattern is a structural fix; ad-hoc history rewriting is not.LEAK: vendor-prefixed flag) should appear in public CI logs.monitor-binary-version-baselines — Phase 1, baselines feed the version-lag policy: what counts as "current" is an empirical fact, not a calendar factprobe-feature-flag-state — Phases 2-3, classification findings here enter the redaction pipeline at category step (Step 1)conduct-empirical-wire-capture — Phase 4, capture artifacts (wire logs, payload schemas) need redaction before any can be referenced publiclysecurity-audit-codebase — both pipelines benefit from deny-list-style scanning; this skill specializes for research disclosure rather than secret leakagemanage-git-branches — the orphan-commit publish pattern is a branch operation; safe execution requires the branch hygiene practices documented there