global setup and configuration.

This commit is contained in:
jb
2026-08-24 16:33:11 -04:00
parent 10f64b593b
commit 31c9363dbb
95 changed files with 12641 additions and 41 deletions
@@ -0,0 +1,59 @@
# /unslop cleanup
Surface AI patterns as reviewable edits the user accepts or rejects, rather than
a finished rewrite. Agent-invoked, never a background daemon. Route here on
`/unslop cleanup` or when the user wants suggestions instead of a silent rewrite.
Set `$INPUT` to the source.
## Report-only variant
When the user says "flag only", "just detect", "audit only", "don't change
anything", or passes `--report`, change nothing. Scan and report:
```bash
python3 scripts/banned_phrase_scan.py <<< "$INPUT"
python3 scripts/structure_scan.py <<< "$INPUT"
python3 scripts/silhouette_scan.py <<< "$INPUT"
python3 scripts/readability_metrics.py <<< "$INPUT"
```
Report each issue by span, category, severity, and why it reads as machine-
written, separating clear problems from register-dependent judgment calls (the
audit-only shape in SKILL.md **Output Format**). Re-read negations, scope, and
certainty yourself; the scanners are necessary, not sufficient.
## Suggestion flow
```bash
python3 scripts/suggest.py document.md # emit suggestions
python3 scripts/suggest.py doc.md --apply-replacements repl.json # merge model replacements
python3 scripts/check_suggestions.py suggestions.json # blocking contract gates
```
- **Detection is cheap and deterministic.** `suggest.py` runs both scanners and
emits LSP-style suggestions `{span, severity, category, rationale,
suggested_replacement, phrased_as_question}`, ordered and non-overlapping.
- **Replacement generation is delegated to a stronger model.** `suggest.py`
leaves `suggested_replacement` null; the stronger model fills them, merged back
via `--apply-replacements`.
- **Hard findings** become direct replacements; **soft findings** are register-
dependent, so their rationale is phrased as a question
(`phrased_as_question: true`).
- **Suggestions are surfaced to the user, never silently applied.**
## Contract gates
`check_suggestions.py` is the blocking contract. Every replacement clears all
four gates or it is rejected:
- `span-minimality`: the edit changes only its span (a whole-sentence rewrite
fails).
- `replacement-scanner`: each replacement passes both scanners in isolation and
adds no new violation in context.
- `accept-all`: applying every suggestion yields a document that passes both
scanners with `validate_preservation` exit 0 versus the original.
- `span-overlap`: spans must not overlap.
Non-English input is declined the way the scanners decline it: `suggest.py`
returns `non_english: true` with no suggestions. For a full rewrite instead of
suggestions, route to `references/commands/rewrite.md`.
@@ -0,0 +1,51 @@
# /unslop contribute
Turn one AI-ism caught in the wild into a scanner contract example and a structured PR. Route
here on "contribute a pattern", "add this tell", or "I found a new AI-ism".
Everything stays offline until the user approves both publication and the final
PR body. Read `references/contribute.md` for the precheck exit codes, redaction
discipline, row-diff verification, and the non-maintainer fork path.
## Flow
1. **Precheck.** `python3 scripts/contribute.py precheck /abs/path/snippet.txt`.
Stop if it exits 3. The tell is already covered, so add a REC row rather
than opening a fresh false-negative row.
2. **User confirmation gate #1 — publication.** Show the exact snippet and ask
whether it may go in a public repo. Offer redaction hints from
`python3 scripts/extract_constraints.py < snippet.txt`. Redact only with
explicit approval, and keep the tell byte-for-byte intact.
3. **Scaffold** the working bundle under `.unslop/contrib/<slug>/` (do not
commit it):
```bash
python3 scripts/contribute.py scaffold --snippet /abs/path/snippet.txt \
--tell "exact substring" --category significance_inflation \
--pattern-name exact-substring-slug --redact "Alice=NAME"
```
4. **Implement eval-first**, following `references/maintenance.md`: copy
`row_fn.json` into `evals/fixtures/contracts/scanner-examples.json`, renumber from the live
maxima, then set `exact_total` to the new `examples` length. Add the
literal-use FP example (and a REC example if a word is gated
behind a collocation). Confirm the FN example is **red** before you touch the
scanner, then update `scripts/banned_phrase_scan.py` and
`references/taboo-phrases.md` until it goes **green** while the FP example holds.
5. **Verify:** `python3 scripts/contribute.py verify --bundle .unslop/contrib/<slug>`.
It refuses TODO markers, checks specimen fidelity, and captures the
red-to-green transition.
6. **Full deterministic gate battery:** `python3 evals/check.py --full`.
7. **Render the PR body:**
`python3 scripts/contribute.py report --bundle .unslop/contrib/<slug> > pr-body.md`.
8. **User confirmation gate #2 — publication of the PR.** Show the final PR
body, get approval, then branch, `git add` the three changed files, commit,
and use `gh pr create` (or the non-maintainer fork path in
`references/contribute.md`). Network access belongs to the host agent.
The resulting branch contains the contract example, scanner change, and taboo-catalog
entry.
@@ -0,0 +1,66 @@
# /unslop mimic
Single-pass voiced writing. Draft or rewrite in a taught voice, then clear the
full gate battery. Route here on "write this like me", "match my voice", or
"mimic this author" once a voice card exists. Read `references/mimic.md` for card
anatomy, scoring, and failure modes.
## Flow
1. Load the situation sheet the task needs. Read `card.md` for the always-on core
(rhythm, contraction habits, punctuation, openers, the Never list) and the
one `card/<situation>.md` sheet that matches what you are writing. Load only
what the task needs; the card is layered so generation stays cheap.
2. Draft or rewrite in that voice. Follow the card's measured markers and
verbatim snippets; do not invent a habit the samples cannot support.
3. Run the output through **every** removal gate:
```bash
python3 scripts/banned_phrase_scan.py <<< "$OUTPUT"
python3 scripts/structure_scan.py <<< "$OUTPUT"
python3 scripts/readability_metrics.py <<< "$OUTPUT"
python3 scripts/validate_preservation.py original.txt "$OUTPUT_FILE"
python3 scripts/diff_check.py original.txt "$OUTPUT_FILE"
```
4. Score the voice:
```bash
python3 scripts/voice_score.py --profile profile.json "$OUTPUT_FILE"
```
## The rule
A mimic that scores well on voice but trips a slop gate is **rejected**. Voice
never buys an exemption from the constitution — the removal gates are hard, the
voice score is a guide. Meaning preservation versus the original draft is its own
hard gate, never blended into the voice score.
## Refine — when one pass is not enough
Most users teach once and mimic cheaply thereafter. When a single pass keeps
scoring short of the target voice, hill-climb with the refine loop — worth the
cost only then:
```bash
python3 evals/run_mimic_refine.py --samples samples/ --draft draft.md --out OUT
```
LIVE (default) calls `--generate-cmd` (default `claude -p`) once per beam per
iteration; `--candidates-dir DIR` runs the loop logic with no model calls. Hard
gates (banned-phrase, structure, draft→candidate preservation, copy-gate, 150-
word floor) discard a candidate regardless of score; survivors are scored against
a held-out DEV split with the full `voice_score` composite, and the best-so-far
never regresses. The **divergence guard** halts and sets
`reward_hacking_warning` when the A composite improves while DEV worsens for two
iterations — the reward-hacking signature. Confirm a win only when
`mimic_stats.py` shows the CI lower bound > 0 and p < 0.05. Internals, baselines,
and the failure table are in `references/mimic.md`.
## Voice check
"Does this sound like me?" — score only, change nothing. Run
`python3 scripts/voice_score.py --profile .unslop/voice/<name>/profile.json
--impostors evals/fixtures/voice/impostors --seed 7 <draft>` and report the
composite (lower is more them), the GI rank, and the two or three metric
deltas that explain the score, in plain words ("your sentences run longer than
usual; contractions match"). No rewrite unless asked. This is the cheapest
voice interaction and the usual one after teach: check drafts often, commission
rewrites rarely.
@@ -0,0 +1,46 @@
# /unslop rewrite
The default command. Read `references/core-contract.md`; it is authoritative.
Use two passes: diagnose, then repair confirmed findings and validate.
Input arrives as an argument, a file path, or stdin. Set `$INPUT` to the source
and `$OUTPUT` to your rewrite.
## Pass 1 — diagnose
1. Extract the facts and constraints that must survive:
```bash
python3 scripts/extract_constraints.py <<< "$INPUT"
```
2. Scan the source so the rewrite answers evidence, not a hunch:
```bash
python3 scripts/banned_phrase_scan.py <<< "$INPUT"
python3 scripts/structure_scan.py <<< "$INPUT"
python3 scripts/silhouette_scan.py <<< "$INPUT"
python3 scripts/readability_metrics.py <<< "$INPUT"
```
Pass `--genre docs` or `--genre social` only when the input truly belongs to
that genre. Add `banned_phrase_scan.py --include-quoted` only when the user
wants quoted examples audited too.
3. Read the selected preset only for voice. It cannot authorize a finding.
4. Classify exact spans as confirmed findings or protected source. Do not
fact-check, use the current date, or treat missing support as an AI tell.
Scanner rows remain candidates until contextual review confirms a defect.
## Pass 2 — reconstruct
Apply the core contract. Edit only a sentence containing a confirmed finding,
make the smallest repair, and copy all other sentences byte-for-byte. If there
are no findings, return the source exactly. Undo any edit that changes a fact,
meaning, register, attribution, or protected domain phrase.
## Validate
Run the gate battery and apply the blocking semantics in
`references/core-contract.md` **Validation**.
Return the cleaned text only, unless the user asked for the strict analysis
block in SKILL.md **Output Format**.
For multi-agent execution, use `references/pipeline.md`; for orchestrated
detector packs, use `references/packs/`.
@@ -0,0 +1,77 @@
# /unslop teach
Build a reusable voice from a writer's samples. **Agent-driven end to end**: the
user supplies only approvals and answers, never a directory or a command. Route
here on "teach my voice", "learn how I write", or when the user offers samples to
learn from. Any samples the user provides are fair game; there are no rights or
attestation checks.
Read `references/mimic.md` for card anatomy, sample requirements, and scoring
before you finish; this file is the flow.
## 1. Gather samples (harvest)
If the user offers none, default to bootstrapping. Harvest their transcripts and
writing folders per `references/harvest.md`:
```bash
python3 scripts/harvest_samples.py SOURCE [SOURCE...] -o candidates.json
python3 scripts/harvest_classify.py --candidates candidates.json --mode heuristic
```
Present the ranked candidates with their sources and flags; the user approves or
rejects each. Treat `suspect_ai` candidates skeptically — that human review is
the contamination defense, so never auto-approve a flagged paste. Copy only
approved samples into `.unslop/voice/<name>/samples/`. The adapter internals,
contamination tripwire, and privacy rules live in `references/harvest.md`.
## 2. Build the profile and card
Create `.unslop/voice/<name>/` yourself (it is gitignored) and run:
```bash
python3 scripts/voice_profile.py samples/ -o profile.json
python3 scripts/voice_card.py --profile profile.json --samples samples/ --out . --name <name> --provenance
```
`voice_profile.py` is the machine fingerprint the scorer refers to.
`voice_card.py` writes the layered card the generating model follows (`card.md`
plus `card/<situation>.md` sheets) and, with `--provenance`, a `provenance.json`
audit trail. Both scripts read only `.txt` and `.md` files; convert samples
first. `voice_card.py` refuses (exit 2) when the profile does not describe the
supplied samples, so a stale profile can never drive a card.
## 3. Surface confidence and gaps
Show the user `card.md`. If the profile is `low_confidence` (thin or cross-genre
samples), say the voice is provisional and ask for more same-genre samples before
trusting a mimic. For an **Uncovered** dimension the target writing will need,
ask for one short sample that exercises it — and only those the task requires, not
all ten. Prompt templates:
| Dimension | Prompt |
|-----------|--------|
| explaining-technical | "Share something you wrote explaining how a thing works." |
| anecdote | "Share a few sentences telling a small story that happened to you." |
| argument | "Share something where you defended a claim." |
| disagreement | "Share something where you pushed back on an idea." |
| praise | "Share something where you recommended something you liked." |
| hedging-uncertainty | "Share something where you were unsure and said so." |
| numbers-data | "Share something you wrote that works with quantities." |
| addressing-reader | "Share a note or instructions written to a reader." |
`openings` and `closings` are structural and covered as soon as one document
exists, so they need no prompt. The full canonical table lives in
`references/mimic.md`.
When coverage or confidence stays thin and the user cannot supply more samples,
offer the A/B calibration game (`references/calibrate.md`): it elicits voice
preferences through reversible pair choices and feeds them to the card as
`stated-preference` provenance, distinct from `measured-from-samples`.
## 4. Close with a scored demo
Prove the loop before the user trusts it: mimic one paragraph per
`references/commands/mimic.md`, run `scripts/voice_score.py` and the scanners,
and show the results. A voiced demo that trips a slop gate fails the loop; do not
ship it with an excuse.