geo-fix
Skill7 starsChanged 28 days agoMITView on GitHub
Apply fixes from geo-audit findings. Reads geo-audit JSON, classifies by safety tier (SAFE/MODERATE/DANGEROUS), applies framework-aware code patches for schema, robots.txt, canonical, sitemap, llms.txt, and freshness fixes. Emits content scaffolds for advisory findings. Deduplicates against seo-fix to prevent double-application.
In this repository58 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- a11y-auditSkill
- agent-benchmarkSkill
- api-auditSkill
- architectureSkill
- backlogSkill
- benchmarkSkill
- brainstormSkill
- buildSkill
- canarySkill
- ci-auditSkill
- code-auditSkill
- container-auditSkill
- content-auditSkill
- content-expandSkill
- content-fixSkill
- content-migrationSkill
- context-auditSkill
- db-auditSkill
- debugSkill
- dependency-auditSkill
- deploySkill
- design-reviewSkill
- designSkill
- docsSkill
- env-auditSkill
- executeSkill
- fix-testsSkill
- geo-auditSkill
- incidentSkill
- infra-auditSkill
- leadsSkill
- mutation-testSkill
- pentestSkill
- performance-auditSkill
- planSkill
- presentationSkill
- profile-sessionSkill
- receive-reviewSkill
- refactor-radarSkill
- refactorSkill
- release-docsSkill
- retroSkill
- reviewSkill
- security-auditSkill
- seo-auditSkill
- seo-fixSkill
- shipSkill
- skill-evalSkill
- structure-auditSkill
- test-auditSkill
- tests-performanceSkill
- ui-design-teamSkill
- using-zuvoSkill
- worktreeSkill
- write-articleSkill
- write-e2eSkill
- write-testsSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
49 rules. About 0 are common, 26 are distinctive, and 23 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈26
Distinctive · estimate
This author's own choices. Worth a look.
23
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 51
Read geo-audit JSON findings.
- Distinctive: line 58
Read these files before any work begins:
- Distinctive: line 95
If any file is missing, STOP.
- Distinctive: line 97
If native agent dispatch is unavailable, execute the workflow sequentially yourself, preserve the same validation checkpoints, and note the …
- Distinctive: line 121
Wait for explicit positive confirmation from user
- Very specific: line 126
If audit JSON timestamp is >24h old:
- Distinctive: line 128
Default mode (SAFE only): proceed with warning
- Distinctive: line 133
After applying fixes, run build verification.
- Distinctive: line 136
If no build command found: skip build verification, note in report
- Very specific: line 140
Treat exit code != 0 as a build failure even if logs contain optimistic lines such as Completed, Built, or similar
- Very specific: line 142
Only report build_result: PASS when the detected build exits with code 0
- Very specific: line 148
Before modifying any file, check for uncommitted changes in that file (git diff --name-only).
- Very specific: line 169
Run the knowledge prime protocol from knowledge-prime.md:
- Very specific: line 182
If [json-path] provided: use that file
- Very specific: line 184
If no JSON found: "No geo-audit JSON found.
- Distinctive: line 188
STOP fires again, with no way out of the loop.
- Very specific: line 192
Version handshake: Check version field. Supported versions: "1.1" (minor bumps are backward compatible).
- Distinctive: line 194
Required fields: If any missing, STOP with "Invalid audit JSON: missing field [X]":
- Very specific: line 206
PROVISIONAL audit handling: If result = "PROVISIONAL":
- Very specific: line 207
Default mode and --dry-run: proceed normally, SAFE fixes are still safe regardless of incomplete gates
- Very specific: line 212
Read timestamp field. Calculate age.
- Distinctive: line 214
If >24h: apply GATE 3 (stale audit protection)
- Very specific: line 247
Check if a matching fix_type + file pair exists in the current geo-audit findings
- Very specific: line 256
If seo-fix applied the fix but with NEEDS_REVIEW or FAILED:
- Distinctive: line 259
If no seo-fix JSON is present:
- Distinctive: line 307
When a safety upgrade fires:
- Distinctive: line 340
Before modifying any file:
- Distinctive: line 342
Check GATE 5 (dirty file check)
- Distinctive: line 343
If multiple findings target the same file: parse existing structure first, then batch all patches into one coherent edit
- Very specific: line 365
Apply: If all 3 layers pass, apply patch.
- Distinctive: line 372
NEVER: write body content text, descriptions, summaries, or factual content
- Very specific: line 413
Check package.json scripts for build, or framework-specific: astro build, next build
- Distinctive: line 415
If no build command detected: skip, note "No build verification available" in report
- Distinctive: line 417
Run the detected build command.
- Distinctive: line 427
Before each file modification, snapshot is saved (Phase 2.0)
- Distinctive: line 428
If build fails: identify which file(s) caused the failure
- Very specific: line 430
If build passes but a required artifact/endpoint check fails (for example /llms.txt returns 404 or the built file is absent), rollback the …
- Very specific: line 433
If still failing: rollback all files from current batch, mark remaining findings as NEEDS_REVIEW
- Distinctive: line 434
If build passes after selective rollback: keep successful fixes, report rolled-back ones
- Very specific: line 486
Record the verdicts: after triage: every finding is fixed, rejected (a false positive) or deferred — record each by its ID: in ONE call, …
- Very specific: line 488
If adversarial-review is not in PATH: ~/.zuvo/adversarial-review (stable.
- Distinctive: line 490
Wait for complete output. Handle findings by severity:
- Distinctive: line 497
Do NOT discard findings based on confidence alone.
- Distinctive: line 516
Do NOT simulate benefits of unverified fixes
- Very specific: line 598
After printing the report block, append the Run: line value (without the Run: prefix) to the log file path resolved per run-logger.md.
- Very specific: line 631
After work is complete, run the knowledge curation protocol from knowledge-curate.md:
- Very specific: line 649
Follow the retrospective protocol from retrospective.md.
- Distinctive: line 651
If gate check skips: print "RETRO: skipped (trivial session)" and proceed.
- Very specific: line 653
Append via wrapper (REQUIRED): Never >> directly to ~/.zuvo/runs.log — the wrapper is the gate that verifies a retro entry exists for this …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
zuvo:geo-fix -- Apply GEO Audit Fixes
Read geo-audit JSON findings. Plan patches per finding. Validate each patch. Apply by safety tier. Verify build. Report.
Scope: Post-audit fix application for GEO findings (schema, robots AI policy, canonical, sitemap, llms.txt, freshness signals, content scaffolds). Out of scope: Content writing, BLUF restructuring, heading rewriting, statistics addition, anti-pattern removal, WordPress plugin config, React SPA fixes. Out-of-scope content findings emit advisory scaffolds only (structural markers, never body content).
Mandatory File Loading
Read these files before any work begins:
Dispatch follows ../../shared/includes/execution-policy.md through env-compat. Reuse existing
authorization within that policy; session restrictions take precedence. Run each required gate
and report its actual independence or an unmet requirement.
../../shared/includes/codesift-setup.md-- CodeSift discovery and tool selection../../shared/includes/env-compat.md-- Agent dispatch and environment adaptation../../shared/includes/backlog-protocol.md-- Filing findings throughbacklog-add../../shared/includes/geo-fix-registry.md-- Canonical fix_type, safety, eta, and manual verification rules../../shared/includes/fix-output-schema.md-- JSON report contract../../shared/includes/seo-bot-registry.md-- Canonical AI/search bot policy taxonomy for robots fixes../../shared/includes/run-logger.md-- Run logging contract../../shared/includes/retrospective.md-- Retrospective protocol../../shared/includes/verification-protocol.md-- Fresh-evidence rules for build and endpoint verification../../shared/includes/knowledge-prime.md-- Project knowledge priming../../shared/includes/knowledge-curate.md-- Learning extraction after work../../shared/includes/no-pause-protocol.md-- HARD rule: no mid-batch pauses
Print the checklist:
CORE FILES LOADED:
1. codesift-setup.md -- [READ | MISSING -> STOP]
2. env-compat.md -- [READ | MISSING -> STOP]
3. backlog-protocol.md -- [READ | MISSING -> STOP]
4. geo-fix-registry.md -- [READ | MISSING -> STOP]
5. fix-output-schema.md -- [READ | MISSING -> STOP]
6. seo-bot-registry.md -- [READ | MISSING -> STOP]
7. run-logger.md -- [READ | MISSING -> STOP]
8. retrospective.md -- [READ | MISSING -> STOP]
9. verification-protocol.md -- [READ | MISSING -> STOP]
10. ../../shared/includes/knowledge-prime.md -- READ/MISSING
11. ../../shared/includes/knowledge-curate.md -- READ/MISSING
12. ../../shared/includes/no-pause-protocol.md -- READ/MISSING (HARD: no mid-batch pauses)If any file is missing, STOP.
If native agent dispatch is unavailable, execute the workflow sequentially yourself, preserve the same validation checkpoints, and note the fallback mode in the final fix report.
Safety Gates (NON-NEGOTIABLE)
GATE 1 -- Write Scope
Allowed write targets:
- Files listed in geo-fix-registry.md target paths (source/config files)
zuvo/audits/for the fix report (.mdand.json)memory/backlog.md(closing a resolved entry: tick it and its resolution marker; the archive helper moves it) andmemory/findings/(written bybacklog-add)
FORBIDDEN:
- Installing packages without explicit user confirmation. If a fix requires dependency installation, escalate to NEEDS_REVIEW with install instructions.
- Writing to files not referenced by template registry or finding evidence
- Deleting files
GATE 2 -- DANGEROUS Fix Confirmation
DANGEROUS fixes (robots-ai-policy-change, schema-restructure, and safety-upgraded findings) are NEVER auto-applied. Procedure:
- Show the exact diff that would be applied
- Explain the risk and expected GEO impact
- List target files
- Wait for explicit positive confirmation from user
- Without confirmation: mark as
MANUALand move to next finding
GATE 3 -- Stale Audit Protection
If audit JSON timestamp is >24h old:
--dry-runmode: proceed with warning- Default mode (SAFE only): proceed with warning
--autoor--allmode: require user confirmation before mutating. Without confirmation, fall back to--dry-run.
GATE 4 -- Build Verification
After applying fixes, run build verification. Detect build command from project:
package.jsonscripts:build,astro build,next build- Hugo:
hugobinary - If no build command found: skip build verification, note in report
Build verification claims follow verification-protocol.md:
- Capture stdout/stderr and the process exit code
- Treat
exit code != 0as a build failure even if logs contain optimistic lines such asCompleted,Built, or similar - Only report
build_result: PASSwhen the detected build exits with code0
Build failure -> rollback (see Phase 3 rollback model).
GATE 5 -- Dirty File Check
Before modifying any file, check for uncommitted changes in that file (git diff --name-only). If the file has uncommitted changes, mark finding as NEEDS_REVIEW instead of modifying.
Arguments
| Argument | Behavior |
| (no args) | Read latest geo-audit JSON, apply SAFE fixes, recommend MODERATE + DANGEROUS |
--dry-run | Show planned fixes without applying |
--auto | Apply SAFE + MODERATE fixes automatically (skip DANGEROUS) |
--all | Include DANGEROUS fixes (requires confirmation per fix) |
--skip-adversarial | Skip cross-provider adversarial review |
--finding G5-schema-org,G3-robots-ai | Fix specific findings by stable ID |
--fix-type schema-org-add,robots-ai-allow | Fix specific fix_type categories |
[json-path] | Use specific JSON file instead of latest |
Knowledge Prime
Run the knowledge prime protocol from knowledge-prime.md:
WORK_TYPE = "implementation"
WORK_KEYWORDS = <keywords from user request>
WORK_FILES = <files being touched>Phase 0: Load Findings
0.1 Locate audit JSON
- If
[json-path]provided: use that file - Otherwise: glob
zuvo/audits/geo-audit-*.json, parsetimestampfrom each, select most recent by timestamp (not filename) - If no JSON found: "No geo-audit JSON found. Run
zuvo:geo-auditfirst." STOP. Namegeo-audit, notseo-audit: step 2 globsgeo-audit-*.jsonand 0.2 below STOPs outright when"skill"is"seo-audit". Pointing the recovery at seo-audit sent the user to produce the one file this skill both fails to glob and explicitly refuses — the same STOP fires again, with no way out of the loop.
0.2 Validate schema and version
Version handshake: Check version field. Supported versions: "1.1" (minor bumps are backward compatible). If major version differs (e.g., "2.0"): STOP with "Unsupported audit schema version [X]. Update zuvo:geo-fix."
Required fields. If any missing, STOP with "Invalid audit JSON: missing field [X]":
Required: version, skill, timestamp, result, score.overall
Required array: findings[]
Required per finding: id, dimension, check, status, fix_type, fix_safety, fix_paramsSkill validation: "skill" field must be "geo-audit". If it is "seo-audit", STOP with "This is an seo-audit JSON. Run geo-fix on geo-audit output only."
0.3 Check result and freshness
PROVISIONAL audit handling: If result = "PROVISIONAL":
- Default mode and
--dry-run: proceed normally, SAFE fixes are still safe regardless of incomplete gates --automode: restrict to SAFE fixes only (do not auto-apply MODERATE). Warn: "Audit is PROVISIONAL -- restricting to SAFE fixes. Re-run seo-audit with --live-url for full GEO coverage."--allmode: require confirmation per fix (same as DANGEROUS gate)
Freshness check:
Read timestamp field. Calculate age.
- If <=24h: proceed
- If >24h: apply GATE 3 (stale audit protection)
0.4 Filter findings
Filter findings into two categories:
- (a) Fixable: status is
FAILorPARTIALwithfix_type!= null - (b) Scaffolds: status is any with
fix_safety="OUT_OF_SCOPE"(for scaffold emission)
Exclude findings where fix_type is not in geo-fix-registry.md fixable inventory (Fixable? = yes). Record these as NO_TEMPLATE.
0.5 Print summary
AUDIT: geo-audit 2026-04-07 (1h ago) | Score: 41/100 (D) | 18 findings
SAFE: 4 findings (auto-fixable)
MODERATE: 7 findings (fixable with validation)
DANGEROUS: 2 findings (manual only)
OUT_OF_SCOPE: 3 findings (scaffold only -- no content generation)
NO_TEMPLATE: 1 finding (fix_type not in registry)
INSUFFICIENT DATA: 1 finding (require live audit for verification)Phase 0.5: Dedup vs seo-fix
0.5.1 Read seo-fix output
Glob zuvo/audits/seo-fix-*.json. For each file, parse actions[].
0.5.2 Check for overlapping fixes
For each seo-fix action with status: "FIXED":
- Check if a matching
fix_type+filepair exists in the current geo-audit findings - Specifically check
llms-txt-add(seo-fix) againstllms-txt-generate/llms-txt-update(geo-fix) -- these are equivalent operations on the same file
0.5.3 Apply dedup
If match found:
- Skip the geo-fix finding with status
ALREADY_APPLIED_BY_SEO_FIX - Record
dedup_source: "seo-fix"in the action result
If seo-fix applied the fix but with NEEDS_REVIEW or FAILED:
- Proceed with geo-fix attempt independently
If no seo-fix JSON is present:
- Proceed normally
0.5.4 Print dedup summary
DEDUP: N findings already fixed by seo-fix, skippingPhase 1: Plan & Classify
1.1 Stack detection (self-contained)
Detect framework directly -- do NOT depend on geo-audit at runtime:
# Inline stack detection
ASTRO=$(find . -maxdepth 3 -name "astro.config.*" 2>/dev/null | wc -l)
NEXT=$(find . -maxdepth 3 -name "next.config.*" 2>/dev/null | wc -l)
HUGO=$(find . -maxdepth 2 \( -name "hugo.toml" -o -name "hugo.yaml" \) 2>/dev/null | wc -l)Cross-check with stack field in audit JSON. If mismatch: warn "Stack changed since audit. Consider re-running geo-audit."
Detect output directory for static files:
- Astro/Next.js/React:
public/ - Hugo:
static/ - Unknown: search for
public/orstatic/, default topublic/
1.2 Sort by safety tier
Order findings: SAFE first, then MODERATE, then DANGEROUS.
1.3 Context-aware safety upgrade
Per geo-fix-registry.md upgrade_eligible rules:
| fix_type | Upgrade condition | From -> To |
schema-org-add | Target file contains existing JSON-LD | MODERATE -> DANGEROUS |
schema-article-add | Target file contains existing JSON-LD | MODERATE -> DANGEROUS |
schema-faq-add | Target file contains existing JSON-LD | MODERATE -> DANGEROUS |
schema-id-link | Target file contains existing @id references | MODERATE -> DANGEROUS |
robots-ai-allow | robots.txt has existing bot rules | SAFE -> MODERATE |
canonical-add | Layout file has an existing canonical tag | SAFE -> MODERATE |
When a safety upgrade fires:
- Record
upgraded: trueandupgrade_reasonin the fix result JSON - Downgrade to
NEEDS_REVIEWif running in non-interactive mode without--force - Emit a warning block naming the conflict before applying
1.4 Resolve target files
For each fix: resolve framework-specific target file from registry templates.
Target file priority (key fix types):
| fix_type | astro | nextjs | hugo |
schema-org-add | Root layout <head> | app/layout.tsx | layouts/partials/head.html |
schema-article-add | Blog layout <head> | Post page.tsx | layouts/_default/single.html |
robots-ai-allow | public/robots.txt | public/robots.txt | static/robots.txt |
canonical-add | Base layout <head> | app/layout.tsx | layouts/partials/head.html |
llms-txt-generate | public/llms.txt | public/llms.txt | static/llms.txt |
Other fix_types: target file is deterministic from framework (single obvious location per registry).
1.5 Print fix plan table
Print table with columns: finding ID, fix_type, safety tier, target file. SAFE first, MODERATE next, DANGEROUS last.
Phase 2: Apply Fixes
For each finding, execute three stages: plan the patch, validate the patch, apply the patch. Group multiple fixes targeting the same file into a single batch edit.
2.0 Pre-flight per file
Before modifying any file:
- Save a snapshot of the original content (in memory, for rollback)
- Check GATE 5 (dirty file check)
- If multiple findings target the same file: parse existing structure first, then batch all patches into one coherent edit
2.1 SAFE fixes (auto-applied)
For each SAFE finding:
- Plan: Determine target file and insertion point per template registry priority
- Validate:
- File parse: target file is readable and has expected structure
- Dedup: the fix content does not already exist in the file
- For
robots-ai-allow: check for existing bot rules (upgrade to MODERATE if found) - For
canonical-add: check for existing canonical tag (upgrade to MODERATE if found)
- Apply: Edit the file. One edit per file (batch if multiple findings target same file).
- Record:
{ finding_id, action, file, status: "FIXED", eta_minutes, manual_checks, risk_notes }
2.2 MODERATE fixes (applied with 3-layer validation)
For each MODERATE finding:
- Plan: Determine target file per priority list. Read target + surrounding context.
- Validate (3 layers):
- File parse: target file is syntactically valid (JSON, JSX, TOML, HTML)
- Framework convention: fix follows framework idiom (e.g., Next.js uses Metadata API, Astro uses
set:html) - Finding-specific check: per geo-fix-registry.md post-conditions (e.g., schema-org: no duplicate Organization blocks; schema-article: valid ISO 8601 dates, unique
@id; schema-faq: >= 2 Q/A entries; schema-id-link: no circular@idrefs; frontmatter-date: valid YAML; sitemap-lastmod: deterministic strategy, not uniform stale dates)
- Apply: If all 3 layers pass, apply patch. If any layer fails: revert, mark
NEEDS_REVIEW. - Record:
{ finding_id, action, file, status: "FIXED" | "NEEDS_REVIEW", validation_result, eta_minutes, manual_checks, risk_notes }
2.3 OUT_OF_SCOPE findings (scaffold emission)
For findings with fix_safety: "OUT_OF_SCOPE":
- Emit structural scaffolds ONLY (HTML comment placeholders)
- NEVER write body content text, descriptions, summaries, or factual content
- NEVER populate author bios, About pages, or mission statements
Scaffold format: <!-- TODO: [description] GEO signal: [rationale] -->
Example: <!-- TODO: Add a 150-300 word organization description. Include: founding year, core mission, primary audience. GEO signal: used by AI retrieval to answer "what is {org_name}?" -->
Each scaffold MUST include a GEO rationale so the content author understands why it matters for AI retrieval.
Record: { finding_id, action, file, status: "SCAFFOLDED", scaffold_content }
Scaffolds do NOT count toward the fix success count.
2.4 DANGEROUS fixes (gated by GATE 2)
For each DANGEROUS finding:
- Plan: Generate the exact diff that would be applied
- Present to user:
- Show diff
- Explain specific risk (e.g., "Opening training bots in robots.txt may allow model scraping. Schema restructure on existing JSON-LD may break Google Rich Results.")
- List all target files
- Show expected GEO impact if fix is correct
- Wait for confirmation: positive response -> apply with 3-layer validation. No response or negative -> mark
MANUAL, move to next finding. - Record:
{ finding_id, action, file, status: "FIXED" | "MANUAL", diff, risk }
2.5 INSUFFICIENT DATA findings
Split into two categories:
- Cannot confirm bug (e.g., live crawl data inconclusive in code-only):
INSUFFICIENT_DATA. Cannot fix what is not confirmed broken. - Cannot determine params (e.g., site_url unknown but fix is otherwise safe):
offer
--dry-runsuggestion with placeholder params. Mark asNEEDS_PARAMSwith explicit manual checks.
Phase 3: Verify
3.1 Build verification
Detect project build command:
- Check
package.jsonscripts forbuild, or framework-specific:astro build,next build - Hugo: check for
hugobinary - If no build command detected: skip, note "No build verification available" in report
Run the detected build command. Record exact command and exit code.
Hard rules:
build_result: PASSrequiresexit code = 0build_result: FAILfor any non-zero exit code, regardless of log content- For public artifacts (
llms.txt,robots.txt,sitemap.xml): post-build existence check required. Missing/empty/404 = cannot stayVERIFIED
3.2 Rollback model
Per-finding rollback (not just "last fix"):
- Before each file modification, snapshot is saved (Phase 2.0)
- If build fails: identify which file(s) caused the failure
- Rollback that file to snapshot, re-run build
- If build passes but a required artifact/endpoint check fails (for example
/llms.txtreturns404or the built file is absent), rollback the related fix or downgrade it toNEEDS_REVIEWwithverification="FAILED" - If still failing: rollback all files from current batch, mark remaining findings as
NEEDS_REVIEW - If build passes after selective rollback: keep successful fixes, report rolled-back ones
3.3 Gate re-check
For each fix_type applied, run a targeted mini-check (not full cross-file audit):
| fix_type | Re-check |
robots-ai-allow | Parse robots.txt, retrieval bot allow rules present, Googlebot not blocked |
schema-org-add | Grep application/ld+json + Organization in target |
schema-article-add | Grep application/ld+json + Article in target, dateModified present |
schema-faq-add | Grep application/ld+json + FAQPage in target |
schema-id-link | @id references consistent between linked blocks |
canonical-add | Grep rel="canonical" in target layout |
sitemap-robots-ref | Sitemap: directive in robots.txt |
llms-txt-generate | llms.txt exists, valid markdown, X-Robots-Tag: noindex configured |
frontmatter-date-add | dateModified field in frontmatter |
| Others | Grep for injected content in target file |
Verification semantics:
VERIFIED: build exited0(when a build exists) and the targeted re-check passed, including artifact/endpoint checks for generated public filesESTIMATED: source-level mutation looks correct, but no deterministic artifact/endpoint check was possible after a successful buildFAILED: the re-check or artifact/endpoint check failed; do not leave the action reported as a clean success
3.4 Adversarial Review (MANDATORY -- do NOT skip)
# Scoped review patch on stdout — the git index is NEVER touched (no staging).
# PATH args = the files the applied actions touched (3.3 target list).
# Quote each SEPARATELY — never one space-joined string or a bare $FILES: zsh does
# not word-split an unquoted expansion, so the helper gets the whole list as ONE
# path, matches nothing and exits 2. Use "${FILES[@]}" for an array.
# With NO PATH args the helper reviews the WHOLE dirty tree, untracked files
# included, and that content is sent to the external providers — always scope it.
# `|| _prc=$?` (never `; _prc=$?`): under `set -e` the plain form aborts the shell
# at the assignment, so exit 3 and the BLOCKED branch would never be reached.
# The BLOCKED branch ends in `false`, so the block's own exit status is non-zero:
# printing alone lets a `set -e` / `if ! …` caller sail past a review that never
# ran. `false`, not `exit`, so an inlining caller's shell is not killed.
if [ -x "$HOME/.zuvo/build-review-patch" ]; then
_prc=0; _patch=$("$HOME/.zuvo/build-review-patch" "<fixed-file-1>" "<fixed-file-2>") || _prc=$?
if [ "$_prc" -eq 3 ]; then echo "adversarial review: skipped (no changes)"
elif [ "$_prc" -ne 0 ]; then echo "BLOCKED: build-review-patch failed (rc=$_prc). Adversarial review did NOT run; do NOT proceed to commit and do NOT report this skill complete" >&2; false
else printf '%s\n' "$_patch" | ~/.zuvo/adversarial-review --mode code; fi
else
~/.zuvo/adversarial-review --mode code --files "<changed files>"
fiRecord the verdicts after triage: every finding is fixed, rejected (a false positive) or deferred — record each by its ID: in ONE call, ~/.zuvo/adversarial-review --record-disposition ID-1 fixed --record-disposition ID-2 rejected …, per ../../shared/includes/adversarial-loop.md Step 4.9 (the review lists its IDs on stderr).
If adversarial-review is not in PATH: ~/.zuvo/adversarial-review (stable; the versioned cache path breaks after any release)
Wait for complete output. Handle findings by severity:
- CRITICAL -- confirm it first: two or more lanes in its
.agreementgroup, or your own check (a failing test, a reproduced input, the cited code read and the defect traced). Confirmed → fix immediately. A single-lane CRITICAL you cannot confirm is triaged as a WARNING and reported as[CRITICAL→WARNING single-lane](adversarial-loop.mdStep 4). - WARNING -- fix if localized (< 10 lines). Otherwise record it with
~/.zuvo/backlog-add --repo "$R" --class <C> --conf <N> --source geo-fix --file "$F" --line <n> [--anchor "$A"] --title "$T"(backlog-protocol.md"Filing from a skill", Adversarial review;<C>isCQorBUGand<N>the confidence, as for the Phase 5.1 write; pass--anchor "$A"only when the class requires one, BUG, SEC or DATA, or the finding carries one, never an invented one (--anchoris required on a BUG, SEC or DATA file record); assign"$R","$F"and"$T"before the call, and"$A"only when you pass--anchor, as "Free text goes through a variable" in that section says; an empty value you pass is a bug, andbacklog-addrefuses a missing required field (REFUSED missing-field:<f>)). Report the B- or F-id it prints; a finding still not persisted is listed underNOT PERSISTED (<reason>), never appended by hand. - INFO -- known concerns (max 3, one line each).
OUT_OF_SCOPE scaffold enforcement (MANDATORY): Adversarial reviewer MUST verify that OUT_OF_SCOPE scaffolds contain only structural markers (HTML comments, placeholder text like <!-- TODO: ... -->) and NO generated prose body content. Any generated body text = adversarial review FAIL. If this check fails, revert the scaffold and mark as FAILED.
Do NOT discard findings based on confidence alone. Confidence measures how sure the reviewer is, not how important the issue is. A CRITICAL with low confidence means "verify this -- if true, it's serious."
"Pre-existing" is NOT a reason to skip a finding. If the issue is in a file you are already editing, fix it now. If not, record it with ~/.zuvo/backlog-add --repo "$R" --class <C> --conf <N> --source drive-by:geo-fix --file "$F" --line <n> [--anchor "$A"] --title "$T" (drive-by-findings.md; backlog-protocol.md "Filing from a skill", Adversarial review; <C> is the drive-by class the finding qualifies for under drive-by-findings.md (SEC, BUG, SIZE, DUP, CPLX, PERF, DEAD or READ) and <N> the confidence; the anchor as for the WARNING command above (--anchor is required on a BUG, SEC or DATA file record); assign "$R", "$F" and "$T" before the call, and "$A" only when you pass --anchor, as "Free text goes through a variable" in that section says; an empty value you pass is a bug, and backlog-add refuses a missing required field (REFUSED missing-field:<f>)). Report the B- or F-id it prints; a finding still not persisted is listed under NOT PERSISTED (<reason>), never appended by hand. The adversarial review found a real problem -- don't dismiss it just because it existed before your changes.
Skip adversarial review ONLY if --skip-adversarial flag is passed. Note the skip in the report.
Phase 4: Report
4.1 Estimated score calculation
estimated_after_score is calculated by:
- Take all findings from audit JSON
- For findings confirmed FIXED: change status from FAIL to PASS
- For findings with
NEEDS_REVIEW,MANUAL,OUT_OF_SCOPE,NO_TEMPLATE, orINSUFFICIENT_DATA: keep original status - For
SCAFFOLDEDfindings: keep original status (scaffolds are not fixes) - Recalculate dimension scores and overall using same weights as geo-audit
- Do NOT simulate benefits of unverified fixes
4.2 Report template
Estimated effort rubric: EASY = <30min, MEDIUM = 1-4h, HARD = 1+ day.
GEO FIX REPORT -- [project name]
----
Findings: 18 total | 5 fixed | 3 needs review | 2 manual | 3 scaffolded | 1 deduped | ...
Score: 41 -> 58 (estimated from confirmed fixes only)
Build: [PASS | FAIL (rolled back N fixes) | NOT VERIFIED]
Dedup: N findings already applied by seo-fix
----
FIXED (auto-applied):
G3: Added AI retrieval bot allow rules public/robots.txt [VERIFIED] ~5 min
...
FIXED (validated):
G5: Added Organization JSON-LD src/layouts/Layout.astro [VERIFIED] ~15 min
...
NEEDS REVIEW:
G8: frontmatter dateModified Reason: [specific reason]
MANUAL (DANGEROUS -- user action required):
G4: robots.txt AI policy change Risk: [risk + suggested diff]
SCAFFOLDED (content markers -- no body content written):
G14: Organization description Scaffold: <!-- TODO: ... -->
ALREADY APPLIED BY SEO-FIX:
G11b: llms.txt generation Source: seo-fix JSON ref
[Also: OUT OF SCOPE, NO TEMPLATE, INSUFFICIENT DATA sections as applicable]4.3 Save report
- Save markdown report to
zuvo/audits/geo-fix-YYYY-MM-DD.mdAuto-increment:-2.md,-3.mdif same-day file exists. - Save fix JSON to
zuvo/audits/geo-fix-YYYY-MM-DD.json(schema:../../shared/includes/fix-output-schema.md):
{
"version": "1.2",
"skill": "geo-fix",
"source_skill": "geo-audit",
"timestamp": "[ISO 8601]",
"project": "[cwd]",
"args": "[arguments]",
"source_audit": "zuvo/audits/geo-audit-YYYY-MM-DD.json",
"result": "PARTIAL | COMPLETE | SAFE_ONLY",
"score": { "before": 41, "estimated_after": 58, "method": "confirmed-fixes-only" },
"summary": {
"total": 18, "fixed": 5, "needs_review": 3, "manual": 2,
"scaffolded": 3, "out_of_scope": 2, "no_template": 1,
"insufficient_data": 1, "already_applied_by_seo_fix": 1
},
"actions": [
{ "finding_id": "G3-robots-ai", "fix_type": "robots-ai-allow", "status": "FIXED",
"file": "public/robots.txt", "verification": "VERIFIED", "eta_minutes": 5,
"estimated_time": "<30 minutes", "manual_checks": null,
"policy_notes": [...], "advisory_scaffolds": null, "risk_notes": [],
"network_override_risk": false, "upgraded": false },
{ "finding_id": "G14-org-description", "fix_type": null, "status": "SCAFFOLDED",
"file": "src/pages/about.astro", "scaffold_content": "<!-- TODO: ... -->" },
{ "finding_id": "G11b-llms-txt", "fix_type": "llms-txt-generate",
"status": "ALREADY_APPLIED_BY_SEO_FIX",
"dedup_source": "seo-fix", "dedup_ref": "seo-fix-YYYY-MM-DD.json" }
],
"manual_checks": [...],
"estimated_time": { "easy": 3, "medium": 2, "hard": 0 },
"policy_notes": [...],
"advisory_scaffolds": [...],
"files_modified": [...],
"build_result": "PASS"
}After printing the report block, append the Run: line value (without the Run: prefix) to the log file path resolved per run-logger.md.
<DURATION>: use N-fixes (number of findings fixed).
Phase 5: Update Backlog
5.1 Backlog operations
Per shared/includes/backlog-protocol.md "Filing from a skill":
| Finding status | Backlog action |
| FIXED | No record; the matching open entries are closed once the fix is committed (Closing, not removing; the rule below the table) |
| NEEDS_REVIEW | Record (backlog-add; --file "$F" when a repo file causes it, --target "$U" for a live page), E starting geo-review:. The helper bumps a re-sighting. |
| MANUAL | Record, as for NEEDS_REVIEW, E starting geo-manual: |
| SCAFFOLDED | Record, as for NEEDS_REVIEW, E starting geo-scaffolded: (the scaffold content reference follows it) |
| OUT_OF_SCOPE | Record, as for NEEDS_REVIEW, E starting geo-manual: |
| NO_TEMPLATE | Record, as for NEEDS_REVIEW, E starting geo-manual: |
| ALREADY_APPLIED_BY_SEO_FIX | No record; the matching geo-audit entry (file plus geo check ID), after re-reading its cited code, is handled the way FIXED does: its B-id goes on the Close after commit: line, or, when seo-fix's change is already committed, the entry is closed now with the sha7 of that commit |
| INSUFFICIENT_DATA | Do not add (unconfirmed issue) |
FIXED matches each open entry with the same file (or target) and the same title check ID whose cited code this run re-read and found fixed (for a file entry, its line and anchor); every other entry with that file and check ID stays open. A target (live-page) entry is closed only by a later live audit that re-reads the page; a source-file patch alone never closes it. geo-fix does not commit, so there is no <sha7> to write: an entry FIXED matches stays open, the report lists its B-id on one line, Close after commit: B-…, B-… | none, and whoever commits the fix closes each one it lists (backlog-protocol.md "How to Persist Findings" step 3: tick - [x] and append [FIXED <sha7>]). A legacy entry written in the old {file}|{dimension}|{check} fingerprint format is matched by that fingerprint's file and check segments. E is the prefix from the table plus what was observed (for SCAFFOLDED, the scaffold content reference), the evidence that the finding is real.
A Generic write per recorded finding: ~/.zuvo/backlog-add --repo "$R" --class <C> --conf <N> --source geo-fix --file "$F" --line <n> [--anchor "$A"] --evidence "$E" --title "$T" when a repository file causes it. A finding on a live page or host with no repository file causing it takes --target "$U" --evidence "$E" in place of --file, --line and --anchor, whatever the class: ~/.zuvo/backlog-add --repo "$R" --class <C> --conf <N> --source geo-fix --target "$U" --evidence "$E" --title "$T". A live defect that a repository file causes is filed by that file (the file form), with the URL in --evidence "$E"; the target form is only for a finding with no repository file causing it. <N> is your confidence that the finding is real. This skill files CQ or BUG only: <C> is CQ for a failed check and BUG only when the finding names the input and the wrong output; BUG takes --anchor "$A", copied from the line that shows the defect ("The location rule"). T starts with the finding's stable check ID, <check-id>: <title> (e.g. robots-ai, schema-org), NOT the fix_type, so FIXED can close the entry later. A whole-file finding is --line 1 with a "Whole file: ..." title (after the check ID) and no --anchor; a whole-file BUG is filed at the line that shows the defect instead, with --anchor "$A" copied from it, never at line 1. Assign "$R", "$E" and "$T" before each call, "$F" only for a file finding, "$U" only for a target finding, "$A" only when you pass --anchor, as "Free text goes through a variable" in that section says; an empty value you pass is a bug, and backlog-add refuses a missing required field (REFUSED missing-field:<f>). Report the B- or F-id each call prints and Recorded: N (backlog: a, ledger: b) ("The report line" in backlog-protocol.md), plus each NOT PERSISTED (<reason>) by name; on a non-zero exit act on the protocol's exit table, and never append by hand.
Recording findings through backlog-add commits and stages nothing. This skill lists the wrote= paths backlog-add printed as Backlog writes: <path>, ... (Backlog writes: none when there are none) in its final summary, whether it runs standalone or inside another skill, for the calling skill's closing commit to carry when there is one (backlog-protocol.md "Filing from a skill", Committing what backlog-add wrote). With --dry-run make no backlog-add call and tick no entry: list in the report what would be recorded (status, file or target, check ID) and what would be closed.
Knowledge Curation
After work is complete, run the knowledge curation protocol from knowledge-curate.md:
WORK_TYPE = "implementation"
CALLER = "zuvo:geo-fix"
REFERENCE = <git SHA or relevant identifier>GEO-FIX COMPLETE
Run: <ISO-8601-Z> geo-fix <project> - - <VERDICT> <TASKS> <N>-fixes <NOTES> <BRANCH> <SHA7> <INCLUDES> <TIER>Retrospective (REQUIRED)
Follow the retrospective protocol from retrospective.md.
Gate check → structured questions → TSV emit → markdown append.
If gate check skips: print "RETRO: skipped (trivial session)" and proceed.
Append via wrapper (REQUIRED). Never >> directly to ~/.zuvo/runs.log — the wrapper is the gate that verifies a retro entry exists for this run. Order: retro bash executed → wrapper invoked → completion claimed.
printf '%b\n' "$RUN_LINE" | ~/.zuvo/append-runlogExpected stdout: OK: appended to runs.log (retro verified for <skill> on <project>). If exit 2 with RETRO_REQUIRED — go execute the retro bash from retrospective.md first; never bypass with ZUVO_SKIP_RETRO_GATE=1. After the wrapper succeeds, print a Logs: evidence line (tail -1 ~/.zuvo/retros.log, grep -c "^<!-- RETRO -->" ~/.zuvo/retros.md, tail -1 ~/.zuvo/runs.log) before claiming completion. Printing the markdown retro section without executing the bash leaves all three log files empty.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

