Skip to content

Build: rebasing-adapted-skill — vendor agent skills with upstream rebase + a read-only deviation audit #15

Description

@Quidge

Goal

Build a firstmate skill for vendoring agent skills that can absorb upstream updates while keeping local deviations in check. It is a port of the captain's prior art in Quidge/ltf4 plus one additive audit subcommand — no new architecture. Design settled in a captain-driven design session (2026-08-05).

Prior art (port from)

  • Quidge/ltf4 : .agents/skills/rebasing-adapted-skill/SKILL.md
  • Quidge/ltf4 : scripts/skill-adaptation.py (a uv run self-contained script, dep pyyaml)

Fetch reliably with gh-axi api repos/Quidge/ltf4/contents/<path> --header "Accept: application/vnd.github.raw" (the default YAML wrapper truncates large base64 bodies).

The model

  • Provenance file ADAPTATION.md sits in the skill root, sibling to SKILL.md. Provenance lives only there, never in SKILL.md.
  • Pins = ADAPTATION.md YAML frontmatter attributions: — a list of GitHub tree URLs pinned to full 40-char commit SHAs + path (https://github.com/<owner>/<repo>/tree/<40-hex-sha>/<path>). Immutable; no branch/tag refs. A skill may pin multiple attributions.
  • Deviation ledger = the ## Deviations body section — natural-language bullets of intentional differences from upstream, read as merge policy (keep what a bullet protects; otherwise silence = match upstream). Not a changelog.
  • The script is deliberately dumb; the agent does the semantic 3-way merge (base = pinned SHA, ours = current, theirs = chosen new SHA), reading ## Deviations as policy, showing a plan and waiting for approval before writing, then advancing pins and refreshing the ledger only on intent change. Never take ADAPTATION.md from upstream.

Settled decisions

# Question Decision
Q1 Scope Rebase-only (initial import stays a manual one-liner via template).
Q2 Keep deviations honest audit mode — read-only check of ours − base vs the declared ## Deviations, flagging undeclared drift and stale bullets.
Q3 Script vs agent boundary Dumb script (scaffold + validate + the deterministic audit diff); agent does the merge and finalizes NL bullet↔delta correlation.
Q4 Pin format GitHub tree URL with full SHA (human-clickable, one string).
Q5 Provenance marker Presence of ADAPTATION.md — no SKILL.md frontmatter stamping.

Build

Two artifacts, mirroring ltf4 with one addition and one layout change.

Script — skill-adaptation.py

  • Keep existing template <tree-url>... (stdout ADAPTATION.md stub) and validate-skill-dir <dir> [-q] (structural validity, no network).
  • Add audit <skill-dir> [-q] — read-only. Per attribution: resolve the pinned base tree, fetch base files at that SHA (deterministic), compute ours − base per path, and emit two lists: undeclared drift (real differences with no covering bullet) and stale bullets (bullets mapping to no current difference). Exit non-zero if either list is non-empty (composes as a gate); -q quiet predicate.
  • Script location (captain, this build): the script lives inside the skill dir at <skill-dir>/scripts/<script>.py — self-contained so it travels with the vendored skill — not a repo-level scripts/. (Deliberate change from ltf4's layout for vendorability.)

Skill — rebasing-adapted-skill

  • Port the ltf4 process, with audit as the first rebase step: run audit, surface undeclared drift + stale bullets, get them reconciled before planning the merge, so the 3-way merge starts from an honest ledger and can't silently clobber undeclared local work.
  • Standalone audit entry too — "is my vendored skill still honest?" without a rebase.
  • Everything else stands: multi-attribution, tree-URL pins with full SHAs, ## Deviations as policy, agent-driven merge, advance pins + refresh ledger only on intent change.

The two rot modes audit catches

  1. Undeclared drift — a local change made without a covering bullet; on the next rebase "silence = match upstream" silently reverts it. Audit: "differs from base but no ## Deviations bullet covers it — declare or drop."
  2. Stale bullet — upstream later adopts the same change; the bullet now describes a difference that no longer exists. Audit: "bullet maps to no actual difference — retire it."

Open refinement (confirm at build intake)

Whether audit correlates bullets↔deltas heuristically or simply presents both sides for the agent to correlate. Report's recommendation: present both sides, agent correlates (simplest, honest about NL ambiguity); add heuristic matching later only if worth it. The deterministic diff stays in the script.

Delivery

Firstmate shared-tracked skill → .agents/skills/ in this repo. Must load firstmate-coding-guidelines and ship through the repo's normal no-mistakes → PR path. Note the firstmate provenance parallel: firstmate's own skills carry metadata.internal: true; a vendored external skill omits it. ADAPTATION.md presence (Q5) is a compatible, orthogonal "upstream-tracked" signal — this skill, if itself vendored in, would carry ADAPTATION.md and omit internal: true.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions