agentleFS
greglas75greglas75/zuvo/skills/geo-fix/SKILL.md

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.

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
  1. Distinctive:

    Read geo-audit JSON findings.

    line 51
  2. Distinctive:

    Read these files before any work begins:

    line 58
  3. Distinctive:

    If any file is missing, STOP.

    line 95
  4. Distinctive:

    If native agent dispatch is unavailable, execute the workflow sequentially yourself, preserve the same validation checkpoints, and note the …

    line 97
  5. Distinctive:

    Wait for explicit positive confirmation from user

    line 121
  6. Very specific:

    If audit JSON timestamp is >24h old:

    line 126
  7. Distinctive:

    Default mode (SAFE only): proceed with warning

    line 128
  8. Distinctive:

    After applying fixes, run build verification.

    line 133
  9. Distinctive:

    If no build command found: skip build verification, note in report

    line 136
  10. Very specific:

    Treat exit code != 0 as a build failure even if logs contain optimistic lines such as Completed, Built, or similar

    line 140
  11. Very specific:

    Only report build_result: PASS when the detected build exits with code 0

    line 142
  12. Very specific:

    Before modifying any file, check for uncommitted changes in that file (git diff --name-only).

    line 148
  13. Very specific:

    Run the knowledge prime protocol from knowledge-prime.md:

    line 169
  14. Very specific:

    If [json-path] provided: use that file

    line 182
  15. Very specific:

    If no JSON found: "No geo-audit JSON found.

    line 184
  16. Distinctive:

    STOP fires again, with no way out of the loop.

    line 188
  17. Very specific:

    Version handshake: Check version field. Supported versions: "1.1" (minor bumps are backward compatible).

    line 192
  18. Distinctive:

    Required fields: If any missing, STOP with "Invalid audit JSON: missing field [X]":

    line 194
  19. Very specific:

    PROVISIONAL audit handling: If result = "PROVISIONAL":

    line 206
  20. Very specific:

    Default mode and --dry-run: proceed normally, SAFE fixes are still safe regardless of incomplete gates

    line 207
  21. Very specific:

    Read timestamp field. Calculate age.

    line 212
  22. Distinctive:

    If >24h: apply GATE 3 (stale audit protection)

    line 214
  23. Very specific:

    Check if a matching fix_type + file pair exists in the current geo-audit findings

    line 247
  24. Very specific:

    If seo-fix applied the fix but with NEEDS_REVIEW or FAILED:

    line 256
  25. Distinctive:

    If no seo-fix JSON is present:

    line 259
  26. Distinctive:

    When a safety upgrade fires:

    line 307
  27. Distinctive:

    Before modifying any file:

    line 340
  28. Distinctive:

    Check GATE 5 (dirty file check)

    line 342
  29. Distinctive:

    If multiple findings target the same file: parse existing structure first, then batch all patches into one coherent edit

    line 343
  30. Very specific:

    Apply: If all 3 layers pass, apply patch.

    line 365
  31. Distinctive:

    NEVER: write body content text, descriptions, summaries, or factual content

    line 372
  32. Very specific:

    Check package.json scripts for build, or framework-specific: astro build, next build

    line 413
  33. Distinctive:

    If no build command detected: skip, note "No build verification available" in report

    line 415
  34. Distinctive:

    Run the detected build command.

    line 417
  35. Distinctive:

    Before each file modification, snapshot is saved (Phase 2.0)

    line 427
  36. Distinctive:

    If build fails: identify which file(s) caused the failure

    line 428
  37. Very specific:

    If build passes but a required artifact/endpoint check fails (for example /llms.txt returns 404 or the built file is absent), rollback the …

    line 430
  38. Very specific:

    If still failing: rollback all files from current batch, mark remaining findings as NEEDS_REVIEW

    line 433
  39. Distinctive:

    If build passes after selective rollback: keep successful fixes, report rolled-back ones

    line 434
  40. Very specific:

    Record the verdicts: after triage: every finding is fixed, rejected (a false positive) or deferred — record each by its ID: in ONE call, …

    line 486
  41. Very specific:

    If adversarial-review is not in PATH: ~/.zuvo/adversarial-review (stable.

    line 488
  42. Distinctive:

    Wait for complete output. Handle findings by severity:

    line 490
  43. Distinctive:

    Do NOT discard findings based on confidence alone.

    line 497
  44. Distinctive:

    Do NOT simulate benefits of unverified fixes

    line 516
  45. Very specific:

    After printing the report block, append the Run: line value (without the Run: prefix) to the log file path resolved per run-logger.md.

    line 598
  46. Very specific:

    After work is complete, run the knowledge curation protocol from knowledge-curate.md:

    line 631
  47. Very specific:

    Follow the retrospective protocol from retrospective.md.

    line 649
  48. Distinctive:

    If gate check skips: print "RETRO: skipped (trivial session)" and proceed.

    line 651
  49. Very specific:

    Append via wrapper (REQUIRED): Never >> directly to ~/.zuvo/runs.log — the wrapper is the gate that verifies a retro entry exists for this …

    line 653

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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.

  1. ../../shared/includes/codesift-setup.md -- CodeSift discovery and tool selection
  2. ../../shared/includes/env-compat.md -- Agent dispatch and environment adaptation
  3. ../../shared/includes/backlog-protocol.md -- Filing findings through backlog-add
  4. ../../shared/includes/geo-fix-registry.md -- Canonical fix_type, safety, eta, and manual verification rules
  5. ../../shared/includes/fix-output-schema.md -- JSON report contract
  6. ../../shared/includes/seo-bot-registry.md -- Canonical AI/search bot policy taxonomy for robots fixes
  7. ../../shared/includes/run-logger.md -- Run logging contract
  8. ../../shared/includes/retrospective.md -- Retrospective protocol
  9. ../../shared/includes/verification-protocol.md -- Fresh-evidence rules for build and endpoint verification
  10. ../../shared/includes/knowledge-prime.md -- Project knowledge priming
  11. ../../shared/includes/knowledge-curate.md -- Learning extraction after work
  12. ../../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 (.md and .json)
  • memory/backlog.md (closing a resolved entry: tick it and its resolution marker; the archive helper moves it) and memory/findings/ (written by backlog-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:

  1. Show the exact diff that would be applied
  2. Explain the risk and expected GEO impact
  3. List target files
  4. Wait for explicit positive confirmation from user
  5. Without confirmation: mark as MANUAL and move to next finding

GATE 3 -- Stale Audit Protection

If audit JSON timestamp is >24h old:

  • --dry-run mode: proceed with warning
  • Default mode (SAFE only): proceed with warning
  • --auto or --all mode: 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:

  1. package.json scripts: build, astro build, next build
  2. Hugo: hugo binary
  3. 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 != 0 as a build failure even if logs contain optimistic lines such as Completed, Built, or similar
  • Only report build_result: PASS when the detected build exits with code 0

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

ArgumentBehavior
(no args)Read latest geo-audit JSON, apply SAFE fixes, recommend MODERATE + DANGEROUS
--dry-runShow planned fixes without applying
--autoApply SAFE + MODERATE fixes automatically (skip DANGEROUS)
--allInclude DANGEROUS fixes (requires confirmation per fix)
--skip-adversarialSkip cross-provider adversarial review
--finding G5-schema-org,G3-robots-aiFix specific findings by stable ID
--fix-type schema-org-add,robots-ai-allowFix 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

  1. If [json-path] provided: use that file
  2. Otherwise: glob zuvo/audits/geo-audit-*.json, parse timestamp from each, select most recent by timestamp (not filename)
  3. If no JSON found: "No geo-audit JSON found. Run zuvo:geo-audit first." STOP. Name geo-audit, not seo-audit: step 2 globs geo-audit-*.json and 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_params

Skill 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
  • --auto mode: 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."
  • --all mode: 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 FAIL or PARTIAL with fix_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 + file pair exists in the current geo-audit findings
  • Specifically check llms-txt-add (seo-fix) against llms-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, skipping

Phase 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/ or static/, default to public/

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_typeUpgrade conditionFrom -> To
schema-org-addTarget file contains existing JSON-LDMODERATE -> DANGEROUS
schema-article-addTarget file contains existing JSON-LDMODERATE -> DANGEROUS
schema-faq-addTarget file contains existing JSON-LDMODERATE -> DANGEROUS
schema-id-linkTarget file contains existing @id referencesMODERATE -> DANGEROUS
robots-ai-allowrobots.txt has existing bot rulesSAFE -> MODERATE
canonical-addLayout file has an existing canonical tagSAFE -> MODERATE

When a safety upgrade fires:

  1. Record upgraded: true and upgrade_reason in the fix result JSON
  2. Downgrade to NEEDS_REVIEW if running in non-interactive mode without --force
  3. 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_typeastronextjshugo
schema-org-addRoot layout <head>app/layout.tsxlayouts/partials/head.html
schema-article-addBlog layout <head>Post page.tsxlayouts/_default/single.html
robots-ai-allowpublic/robots.txtpublic/robots.txtstatic/robots.txt
canonical-addBase layout <head>app/layout.tsxlayouts/partials/head.html
llms-txt-generatepublic/llms.txtpublic/llms.txtstatic/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:

  1. Save a snapshot of the original content (in memory, for rollback)
  2. Check GATE 5 (dirty file check)
  3. 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:

  1. Plan: Determine target file and insertion point per template registry priority
  2. 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)
  3. Apply: Edit the file. One edit per file (batch if multiple findings target same file).
  4. 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:

  1. Plan: Determine target file per priority list. Read target + surrounding context.
  2. 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 @id refs; frontmatter-date: valid YAML; sitemap-lastmod: deterministic strategy, not uniform stale dates)
  3. Apply: If all 3 layers pass, apply patch. If any layer fails: revert, mark NEEDS_REVIEW.
  4. 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:

  1. Plan: Generate the exact diff that would be applied
  2. 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
  3. Wait for confirmation: positive response -> apply with 3-layer validation. No response or negative -> mark MANUAL, move to next finding.
  4. 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-run suggestion with placeholder params. Mark as NEEDS_PARAMS with explicit manual checks.

Phase 3: Verify

3.1 Build verification

Detect project build command:

  1. Check package.json scripts for build, or framework-specific: astro build, next build
  2. Hugo: check for hugo binary
  3. 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: PASS requires exit code = 0
  • build_result: FAIL for 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 stay VERIFIED

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.txt returns 404 or the built file is absent), rollback the related fix or downgrade it to NEEDS_REVIEW with verification="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_typeRe-check
robots-ai-allowParse robots.txt, retrieval bot allow rules present, Googlebot not blocked
schema-org-addGrep application/ld+json + Organization in target
schema-article-addGrep application/ld+json + Article in target, dateModified present
schema-faq-addGrep application/ld+json + FAQPage in target
schema-id-link@id references consistent between linked blocks
canonical-addGrep rel="canonical" in target layout
sitemap-robots-refSitemap: directive in robots.txt
llms-txt-generatellms.txt exists, valid markdown, X-Robots-Tag: noindex configured
frontmatter-date-adddateModified field in frontmatter
OthersGrep for injected content in target file

Verification semantics:

  • VERIFIED: build exited 0 (when a build exists) and the targeted re-check passed, including artifact/endpoint checks for generated public files
  • ESTIMATED: source-level mutation looks correct, but no deterministic artifact/endpoint check was possible after a successful build
  • FAILED: 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>"
fi

Record 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 .agreement group, 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.md Step 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> is CQ or BUG and <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 (--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.
  • 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:

  1. Take all findings from audit JSON
  2. For findings confirmed FIXED: change status from FAIL to PASS
  3. For findings with NEEDS_REVIEW, MANUAL, OUT_OF_SCOPE, NO_TEMPLATE, or INSUFFICIENT_DATA: keep original status
  4. For SCAFFOLDED findings: keep original status (scaffolds are not fixes)
  5. Recalculate dimension scores and overall using same weights as geo-audit
  6. 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

  1. Save markdown report to zuvo/audits/geo-fix-YYYY-MM-DD.md Auto-increment: -2.md, -3.md if same-day file exists.
  2. 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 statusBacklog action
FIXEDNo record; the matching open entries are closed once the fix is committed (Closing, not removing; the rule below the table)
NEEDS_REVIEWRecord (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.
MANUALRecord, as for NEEDS_REVIEW, E starting geo-manual:
SCAFFOLDEDRecord, as for NEEDS_REVIEW, E starting geo-scaffolded: (the scaffold content reference follows it)
OUT_OF_SCOPERecord, as for NEEDS_REVIEW, E starting geo-manual:
NO_TEMPLATERecord, as for NEEDS_REVIEW, E starting geo-manual:
ALREADY_APPLIED_BY_SEO_FIXNo 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_DATADo 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-runlog

Expected 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.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.