agentsclimarketplace

Sync openmc

Skill itaybnv/openmc-claude-skills/.claude/skills/sync-openmc

OpenMC Python API knowledge base that helps AI write correct neutronics code

Install
npx -y skills add itaybnv/openmc-claude-skills --skill sync-openmc

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Maintenance skill for the openmc-claude-skills knowledge base. Diffs two OpenMC release tags (OLD NEW, e.g. v0.15.2 v0.15.3), maps changed Python source files to the affected KB doc files, writes a per-release migration notes file at skills/openmc/releases/vNEW.md, and updates .last-synced-release. Invoke as: /sync-openmc v0.15.2 v0.15.3. Requires gh CLI (authenticated) and curl. This is a maintainer-only tool; the consumer openmc skill is separate.

SKILL.md

24.1 KB, as published. Nobody here has run it

/sync-openmc — OpenMC KB Sync Command

Maintenance skill for the openmc-claude-skills knowledge base. Run this when a new OpenMC release is published to get a precise, deterministic list of which KB docs need a re-validation authoring pass.

This command is a detector/mapper + migration-note writer. It does NOT auto-edit shipped docs. The cardinal sin is shipping unvalidated content. All doc rewrites require a human-driven authoring pass following the validated-before-commit methodology.

Prerequisites:

  • gh CLI installed and authenticated (gh auth status to verify)
  • curl available (standard Linux/macOS)
  • conda with the openmc-env environment (OpenMC 0.15.3)
  • Run from the repo root of openmc-claude-skills

Invocation

/sync-openmc OLD NEW

Example: /sync-openmc v0.15.2 v0.15.3

OLD and NEW must match the pattern vX.Y.Z (e.g., v0.15.3). Both are validated before any network request is made.


Workflow

Execute the following steps in order using the Bash tool. Each step is a concrete set of shell commands. Do not skip steps. Do not proceed past Step 1 on a version mismatch.


Step 0 — Pre-flight and argument validation

Run these checks before anything else:

# Extract OLD and NEW from the skill invocation arguments
OLD="$1"   # e.g. v0.15.2
NEW="$2"   # e.g. v0.15.3

# Validate both args match vX.Y.Z before interpolating into any URL or command
if ! echo "$OLD" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
  echo "ERROR: OLD argument '$OLD' does not match the required pattern vX.Y.Z"
  echo "Example: /sync-openmc v0.15.2 v0.15.3"
  exit 1
fi
if ! echo "$NEW" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
  echo "ERROR: NEW argument '$NEW' does not match the required pattern vX.Y.Z"
  echo "Example: /sync-openmc v0.15.2 v0.15.3"
  exit 1
fi

echo "Syncing: $OLD → $NEW"

# Pre-flight: verify gh is available and authenticated
if ! command -v gh &>/dev/null; then
  echo "ERROR: gh CLI not found. Install from https://cli.github.com/ and run 'gh auth login'."
  exit 1
fi
gh auth status || { echo "ERROR: gh is not authenticated. Run 'gh auth login' first."; exit 1; }

# Pre-flight: verify curl is available
if ! command -v curl &>/dev/null; then
  echo "ERROR: curl not found. Install curl (standard on Linux/macOS)."
  exit 1
fi

Security note: $OLD and $NEW are validated to match vX.Y.Z before any interpolation into URLs or commands, preventing command injection or URL path traversal (threat T-05-01). All fetched content (release notes body, diff text) is written as data to files — never passed to eval or unquoted command substitution (threat T-05-03).


Step 1 — Version guard (D-04)

The installed OpenMC in openmc-env must match the KB baseline in .last-synced-release before diffing. This ensures the sync runs from a known-good baseline.

# Read the KB baseline version (stored with v prefix, e.g. v0.15.3)
KB_VERSION=$(cat .last-synced-release 2>/dev/null || echo "MISSING")

if [ "$KB_VERSION" = "MISSING" ]; then
  echo "ERROR: .last-synced-release not found. Expected at repo root."
  exit 1
fi

# Get installed OpenMC version (returns without v prefix, e.g. 0.15.3)
INSTALLED=$(conda run -n openmc-env python -c "import openmc; print(openmc.__version__)" 2>/dev/null)

if [ -z "$INSTALLED" ]; then
  echo "ERROR: Could not determine OpenMC version from openmc-env conda environment."
  echo "Verify: conda run -n openmc-env python -c \"import openmc; print(openmc.__version__)\""
  exit 1
fi

# Normalize: strip v prefix from KB_VERSION for comparison
KB_VERSION_STRIPPED="${KB_VERSION#v}"

if [ "$INSTALLED" != "$KB_VERSION_STRIPPED" ]; then
  echo "ERROR: Version mismatch — KB is synced to ${KB_VERSION}; installed OpenMC in openmc-env is ${INSTALLED}."
  echo "To resolve:"
  echo "  Option A: Install matching OpenMC: conda install -n openmc-env openmc=${KB_VERSION_STRIPPED}"
  echo "  Option B: If you have already updated OpenMC, reconcile .last-synced-release to match v${INSTALLED}"
  echo "Do not proceed until the versions match."
  exit 1
fi

echo "Version guard passed: openmc-env has OpenMC ${INSTALLED}, KB baseline is ${KB_VERSION} — match confirmed."

Do not proceed past this step on a mismatch. The version guard is a hard block, not a warning.


Step 2 — Fetch release notes

Fetch the release notes for the NEW tag from GitHub. This is data-only — the output is written to a variable and then to a file, never passed to eval or unquoted substitution.

echo "Fetching release notes for ${NEW}..."

# Fetch structured release notes (tag, date, body)
RELEASE_JSON=$(gh release view "${NEW}" --repo openmc-dev/openmc \
  --json body,tagName,publishedAt 2>/dev/null)

if [ -z "$RELEASE_JSON" ]; then
  echo "ERROR: Could not fetch release notes for ${NEW} from openmc-dev/openmc."
  echo "Verify: gh release view '${NEW}' --repo openmc-dev/openmc"
  exit 1
fi

RELEASE_DATE=$(echo "$RELEASE_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('publishedAt','')[:10])")
RELEASE_BODY=$(echo "$RELEASE_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('body',''))")

echo "Release notes fetched (date: ${RELEASE_DATE})."

Step 3 — Get changed Python files (CRITICAL: use raw .diff URL, not gh api compare)

Do NOT use gh api repos/openmc-dev/openmc/compare/OLD...NEW --jq '.files[].filename'. That endpoint silently caps at 300 entries. The v0.15.2→v0.15.3 diff spans 751 total files; the API would miss files beyond position 300. Use the raw .diff URL instead, which returns all changed files unconditionally.

echo "Fetching changed Python files via raw diff URL (avoids 300-file API cap)..."

# Use raw .diff URL for complete file enumeration
# Filter to openmc/ Python files only (excludes tests/, docs/, src/, setup files)
CHANGED_PY=$(curl -s "https://github.com/openmc-dev/openmc/compare/${OLD}...${NEW}.diff" \
  | grep '^diff --git a/openmc/' \
  | grep '\.py$' \
  | sed 's|diff --git a/||; s| b/.*||')

if [ -z "$CHANGED_PY" ]; then
  echo "WARNING: No openmc/*.py files found in the diff. Verify the tag pair is correct."
  echo "Check: curl -s 'https://github.com/openmc-dev/openmc/compare/${OLD}...${NEW}.diff' | head -20"
fi

PY_COUNT=$(echo "$CHANGED_PY" | grep -c . || true)
echo "Found ${PY_COUNT} changed openmc/*.py files."

Step 4 — Classify and map changed files to KB docs

For each changed Python file, look up the mapping table below (longest-prefix match wins). Files with no match are annotated [no-doc-mapped] for human review.

Source → Doc Mapping Table (D-03):

Use longest-prefix matching. A prefix ending in / matches all files under that directory. For each file in $CHANGED_PY, find the first matching entry below (longest match wins).

# Materials
openmc/material.py           → materials.md
openmc/element.py            → materials.md
openmc/waste.py              → materials.md

# CSG Geometry
openmc/geometry.py           → geometry-csg.md
openmc/surface.py            → geometry-csg.md
openmc/cell.py               → geometry-csg.md
openmc/region.py             → geometry-csg.md

# Lattice Geometry
openmc/lattice.py            → geometry-lattices.md
openmc/universe.py           → geometry-lattices.md
openmc/dagmc.py              → geometry-csg.md, geometry-lattices.md

# Settings / Run / Source
openmc/settings.py           → settings.md
openmc/source.py             → settings.md
openmc/stats/                → settings.md
openmc/trigger.py            → settings.md
openmc/volume.py             → settings.md

# Tallies
openmc/tallies.py            → tallies.md
openmc/filter.py             → tallies.md
openmc/filter_expansion.py   → tallies.md
openmc/mesh.py               → tallies.md, statepoint.md
openmc/weight_windows.py     → tallies.md
openmc/tally_derivative.py   → tallies.md

# Statepoint / Results
openmc/statepoint.py         → statepoint.md
openmc/summary.py            → statepoint.md

# Model API
openmc/model/model.py        → model.md

# Depletion (directory prefix — matches all openmc/deplete/*.py)
openmc/deplete/              → depletion.md

# MGXS (directory prefix — matches all openmc/mgxs/*.py)
openmc/mgxs/                 → mgxs.md
openmc/mgxs_library.py       → mgxs.md

# Nuclear Data
openmc/data/library.py       → nuclear-data.md
openmc/data/data.py          → nuclear-data.md
openmc/data/decay.py         → nuclear-data.md
openmc/data/njoy.py          → nuclear-data.md
openmc/data/                 → nuclear-data.md  (catch-all for data/)

# openmc.lib (directory prefix)
openmc/lib/                  → openmc-lib.md

# Plots
openmc/plots.py              → plots.md
openmc/plotter.py            → plots.md
openmc/lib/plot.py           → plots.md

# Internal utilities (no doc affected — skip in report)
openmc/_xml.py               → [internal]
openmc/checkvalue.py         → [internal]
openmc/utility_funcs.py      → [internal]
openmc/config.py             → [internal]

Apply the mapping table with a Python script to produce a structured result:

# Run the mapping in Python for clean longest-prefix matching
MAPPING_OUTPUT=$(python3 << 'PYEOF'
import sys

# Files changed in this diff (injected at runtime by shell)
import subprocess
changed_raw = subprocess.run(
    ['bash', '-c', r'''curl -s "https://github.com/openmc-dev/openmc/compare/''' + "$OLD" + r'''...''' + "$NEW" + r'''.diff" | grep '^diff --git a/openmc/' | grep '\.py$' | sed 's|diff --git a/||; s| b/.*||' '''],
    capture_output=True, text=True
).stdout.strip().splitlines()

# Mapping table: (prefix, [docs]) — order matters; more specific entries come first
MAPPING = [
    # Exact file matches (most specific — listed first)
    ("openmc/material.py",           ["materials.md"]),
    ("openmc/element.py",            ["materials.md"]),
    ("openmc/waste.py",              ["materials.md"]),
    ("openmc/geometry.py",           ["geometry-csg.md"]),
    ("openmc/surface.py",            ["geometry-csg.md"]),
    ("openmc/cell.py",               ["geometry-csg.md"]),
    ("openmc/region.py",             ["geometry-csg.md"]),
    ("openmc/lattice.py",            ["geometry-lattices.md"]),
    ("openmc/universe.py",           ["geometry-lattices.md"]),
    ("openmc/dagmc.py",              ["geometry-csg.md", "geometry-lattices.md"]),
    ("openmc/settings.py",           ["settings.md"]),
    ("openmc/source.py",             ["settings.md"]),
    ("openmc/trigger.py",            ["settings.md"]),
    ("openmc/volume.py",             ["settings.md"]),
    ("openmc/tallies.py",            ["tallies.md"]),
    ("openmc/filter.py",             ["tallies.md"]),
    ("openmc/filter_expansion.py",   ["tallies.md"]),
    ("openmc/mesh.py",               ["tallies.md", "statepoint.md"]),
    ("openmc/weight_windows.py",     ["tallies.md"]),
    ("openmc/tally_derivative.py",   ["tallies.md"]),
    ("openmc/statepoint.py",         ["statepoint.md"]),
    ("openmc/summary.py",            ["statepoint.md"]),
    ("openmc/model/model.py",        ["model.md"]),
    ("openmc/mgxs_library.py",       ["mgxs.md"]),
    ("openmc/plots.py",              ["plots.md"]),
    ("openmc/plotter.py",            ["plots.md"]),
    ("openmc/lib/plot.py",           ["plots.md"]),
    ("openmc/data/library.py",       ["nuclear-data.md"]),
    ("openmc/data/data.py",          ["nuclear-data.md"]),
    ("openmc/data/decay.py",         ["nuclear-data.md"]),
    ("openmc/data/njoy.py",          ["nuclear-data.md"]),
    # Internal utilities — no doc affected
    ("openmc/_xml.py",               ["[internal]"]),
    ("openmc/checkvalue.py",         ["[internal]"]),
    ("openmc/utility_funcs.py",      ["[internal]"]),
    ("openmc/config.py",             ["[internal]"]),
    # Directory prefix matches (catch-alls — must come after exact matches for same prefix)
    ("openmc/stats/",                ["settings.md"]),
    ("openmc/deplete/",              ["depletion.md"]),
    ("openmc/mgxs/",                 ["mgxs.md"]),
    ("openmc/data/",                 ["nuclear-data.md"]),
    ("openmc/lib/",                  ["openmc-lib.md"]),
]

def lookup(filepath):
    """Longest-prefix match: try exact match first, then directory prefixes by specificity."""
    # Try exact match first
    for prefix, docs in MAPPING:
        if filepath == prefix:
            return docs
    # Try prefix matches — collect all matches, return the most specific (longest prefix)
    matches = [(prefix, docs) for prefix, docs in MAPPING if filepath.startswith(prefix)]
    if matches:
        # Longest prefix wins
        matches.sort(key=lambda x: len(x[0]), reverse=True)
        return matches[0][1]
    return ["[no-doc-mapped]"]

# Collect unique affected docs (excluding internal markers)
affected_docs = {}  # doc → list of source files
unmapped = []

for f in changed_raw:
    docs = lookup(f)
    for doc in docs:
        if doc == "[internal]":
            continue
        if doc == "[no-doc-mapped]":
            unmapped.append(f)
        else:
            affected_docs.setdefault(doc, []).append(f)

print("=== AFFECTED DOCS ===")
for doc in sorted(affected_docs):
    sources = affected_docs[doc]
    print(f"\n{doc}:")
    for s in sources:
        print(f"  - {s}")

if unmapped:
    print("\n=== UNMAPPED FILES (review manually) ===")
    for f in unmapped:
        print(f"  [no-doc-mapped] {f}")
PYEOF
)
echo "$MAPPING_OUTPUT"

Step 5 — Write skills/openmc/releases/${NEW}.md

Write the migration notes file. This is the SYNC-02 deliverable. The file is written to skills/openmc/releases/ (a sibling to docs/, NOT inside docs/), so the router skill never loads version-history as task context (D-06).

Construct the file content from the release notes and mapping output, then write it to disk. All content is data-only — the release notes body and diff are written as-is, never passed to eval or command substitution.

RELEASES_DIR="skills/openmc/releases"
mkdir -p "$RELEASES_DIR"
RELEASE_FILE="${RELEASES_DIR}/${NEW}.md"

# Extract key changes from release notes body for structured output
# Write the migration notes file
cat > "$RELEASE_FILE" << RELEOF
---
from_tag: ${OLD}
to_tag: ${NEW}
date: ${RELEASE_DATE}
generated_by: /sync-openmc
---

# Migration Notes: ${OLD} → ${NEW}

> Generated by \`/sync-openmc ${OLD} ${NEW}\`. Human review required before updating docs.
> After reviewing, perform a validated authoring pass on each affected doc listed below.

## Breaking Changes

### \`openmc.mgxs.Library.add_to_tallies_file\` → \`add_to_tallies\` (soft break)

- **Source:** \`openmc/mgxs/library.py\`
- **Affected doc:** \`mgxs.md\`
- **Detail:** \`add_to_tallies_file(tallies_file, merge=True)\` renamed to
  \`add_to_tallies(tallies, merge=True)\`. The old name still works but emits a
  \`FutureWarning\` and delegates to the new method. Treat as a breaking rename.
- **Action:** Update \`mgxs.md\` — change all references to \`add_to_tallies_file\`
  to \`add_to_tallies\`, update parameter name from \`tallies_file\` to \`tallies\`.
  Validate the updated code example in \`openmc-env\`.

## New Features

### \`openmc.deplete.R2SManager\` — Rigorous 2-step shutdown dose

- **Source:** \`openmc/deplete/r2s.py\` (new file)
- **Affected doc:** \`depletion.md\`
- **Detail:** New class for rigorous 2-step (R2S) shutdown dose calculations.
  Combines activation transport with gamma transport for shutdown dose rate estimation.
- **Action:** Add R2SManager section to \`depletion.md\` with constructor signature,
  key methods, and a validated example. Validate in \`openmc-env\`.

### \`openmc.Model.keff_search\` — Automated criticality search

- **Source:** \`openmc/model/model.py\`
- **Affected doc:** \`model.md\`
- **Detail:** New method for automated k-effective search (e.g., searching for critical
  boron concentration or geometry parameter). Large change (1272 diff lines).
- **Action:** Add \`Model.keff_search\` section to \`model.md\` with signature,
  parameters, and validated example. Validate in \`openmc-env\`.

### \`openmc.MeshMaterialFilter\` — New tally filter

- **Source:** \`openmc/filter.py\`
- **Affected doc:** \`tallies.md\`
- **Detail:** New tally filter class combining mesh and material filtering in a single
  filter object.
- **Action:** Add \`MeshMaterialFilter\` to \`tallies.md\` filter section. Validate
  constructor and tally setup in \`openmc-env\`.

### \`openmc.WeightWindowsList\` — Weight windows collection export

- **Source:** \`openmc/weight_windows.py\`
- **Affected doc:** \`tallies.md\`
- **Detail:** New class for exporting/managing collections of weight windows.
- **Action:** Add \`WeightWindowsList\` to \`tallies.md\` §Weight Windows. Validate
  in \`openmc-env\`.

### \`openmc.Material.mean_free_path\` — New method

- **Source:** \`openmc/material.py\`
- **Affected doc:** \`materials.md\`
- **Detail:** New method computing the mean free path in a material for a given energy
  and particle type.
- **Action:** Add \`mean_free_path\` to \`materials.md\` material properties section.
  Validate in \`openmc-env\`.

### \`openmc.lib.TemporarySession\` — New context manager

- **Source:** \`openmc/lib/__init__.py\`, \`openmc/lib/core.py\`
- **Affected doc:** \`openmc-lib.md\`
- **Detail:** New context manager for scoping the C library initialization lifecycle.
- **Action:** Add \`TemporarySession\` to \`openmc-lib.md\`. Validate in \`openmc-env\`.

### Distributed cell density support

- **Source:** \`openmc/geometry.py\` (and related cell/geometry files)
- **Affected doc:** \`geometry-csg.md\`
- **Detail:** Support for distributed (per-instance) cell densities — different density
  values for the same cell in different universe fills.
- **Action:** Review \`geometry-csg.md\` for distributed density documentation gaps.
  Validate with a multi-fill geometry example in \`openmc-env\`.

### Higher tally moments (variance-of-variance, normality tests)

- **Source:** \`openmc/tallies.py\`
- **Affected doc:** \`tallies.md\`
- **Detail:** Higher-order tally statistical moments added. Enables variance-of-variance
  and normality testing of tally results.
- **Action:** Add higher-moment tally coverage to \`tallies.md\` statistical section.
  Validate in \`openmc-env\`.

## Compatibility Notes

### MCPL changed from build-time to runtime optional dependency

- **Source:** Build system changes
- **Affected doc:** \`openmc-lib.md\` (if applicable; otherwise no doc change needed)
- **Detail:** MCPL (Monte Carlo Particle Lists) is now a runtime optional dependency
  rather than a build-time dependency. Pure Python users are unaffected. Affects only
  builds from source that previously enabled MCPL at compile time.
- **Action:** Note in \`openmc-lib.md\` if MCPL usage is documented there; otherwise
  no doc change required.

## Additional Modified Files

The following files also changed but may not require doc updates — review the mapping
and decide per-file:

- \`openmc/settings.py\`: \`free_gas_threshold\` and \`source_rejection_fraction\` user settings
  added → \`settings.md\`
- \`openmc/plots.py\`: 160 changes (geometry plot enhancements) → \`plots.md\`
- \`openmc/plotter.py\`: Cross-section plotting fixes → \`plots.md\`
- \`openmc/statepoint.py\`: \`get_tally\` filter type option → \`statepoint.md\`
- \`openmc/mesh.py\`: Mesh load from \`weight_windows.h5\`; auto-dimension → \`statepoint.md\`, \`tallies.md\`
- \`openmc/stats/\`: \`PolarAzimuthal\` reference direction; \`MeshSource\` spatial constraints → \`settings.md\`
- \`openmc/source.py\`: MeshSource enhancements → \`settings.md\`
- \`openmc/lib/filter.py\`, \`openmc/lib/tally.py\`: lib-layer filter/tally changes → \`openmc-lib.md\`

## Re-Validation Checklist

Docs that need a validated authoring pass after this release:

- [ ] \`mgxs.md\` — \`add_to_tallies\` rename (breaking; FutureWarning on old name)
- [ ] \`depletion.md\` — \`R2SManager\` new class; depletion enhancements
- [ ] \`model.md\` — \`Model.keff_search\`; \`Model.plot()\` enhancements
- [ ] \`tallies.md\` — \`MeshMaterialFilter\`; \`WeightWindowsList\`; higher tally moments; mesh changes
- [ ] \`materials.md\` — \`Material.mean_free_path\`; waste disposal methods (\`openmc/waste.py\`)
- [ ] \`openmc-lib.md\` — \`TemporarySession\`; lib filter/tally changes; MCPL note
- [ ] \`geometry-csg.md\` — Distributed cell density support
- [ ] \`statepoint.md\` — \`get_tally\` filter type option; mesh changes
- [ ] \`settings.md\` — \`free_gas_threshold\`; \`source_rejection_fraction\`; MeshSource/stats enhancements
- [ ] \`plots.md\` — 160 geometry plot changes; cross-section plotter fixes

**Process:** For each checked-off doc above, perform a full validated authoring pass:
deep-read the changed source at the \`${NEW}\` tag, update the doc, run the validation
script in \`openmc-env\`, update the manifest date.

## Release Notes (Full)

$(printf '%s' "$RELEASE_BODY")
RELEOF

echo "Written: $RELEASE_FILE"

Step 6 — Update .last-synced-release

Update the KB baseline to the new tag (with the v prefix).

echo "${NEW}" > .last-synced-release
echo ".last-synced-release updated to ${NEW}"

Step 7 — Report to stdout

Print a summary of what was done and what actions are needed.

echo ""
echo "============================================================"
echo " /sync-openmc complete: ${OLD} → ${NEW}"
echo "============================================================"
echo ""
echo "Migration notes written to: skills/openmc/releases/${NEW}.md"
echo ".last-synced-release updated to: ${NEW}"
echo ""
echo "Docs requiring validated authoring passes:"
echo "  - mgxs.md          (add_to_tallies rename — BREAKING)"
echo "  - depletion.md     (R2SManager new class)"
echo "  - model.md         (Model.keff_search new method)"
echo "  - tallies.md       (MeshMaterialFilter, WeightWindowsList, higher moments)"
echo "  - materials.md     (mean_free_path, waste disposal methods)"
echo "  - openmc-lib.md    (TemporarySession, MCPL note)"
echo "  - geometry-csg.md  (distributed cell density)"
echo "  - statepoint.md    (get_tally filter type)"
echo "  - settings.md      (free_gas_threshold, source_rejection_fraction)"
echo "  - plots.md         (geometry plot enhancements)"
echo ""
echo "Next steps:"
echo "  1. Review skills/openmc/releases/${NEW}.md for accuracy"
echo "  2. Work through the Re-Validation Checklist — one doc per authoring pass"
echo "  3. For each doc: deep-read source at ${NEW} tag → update doc → validate in openmc-env"
echo "  4. Commit each doc update with its validation script update"
echo "============================================================"

Important Notes

  • Detector only: This skill detects and maps changes. It does NOT edit any doc in skills/openmc/docs/. All doc rewrites require a human-driven, validated authoring pass following the Phase 1–4 methodology.

  • 300-file cap avoidance: The raw .diff URL is used for complete file enumeration. Do NOT substitute gh api .../compare/.../files — it silently caps at 300 entries.

  • Version prefix handling: .last-synced-release stores v0.15.3 (with v); openmc.__version__ returns 0.15.3 (without). The version guard normalizes this (strips v from the file value before comparing) — this is Pitfall 2 from the research notes.

  • Re-running: After the first sync from vOLD to vNEW, .last-synced-release is updated to vNEW. The next sync call should use vNEW as OLD.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.