Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
5b7b51d
docs(designs): reconciliation tracking for marketplace installs
potiuk Sep 21, 2026
aed30bb
docs(designs): sweep when nothing is stamped, instead of staying silent
potiuk Sep 21, 2026
bd281eb
docs(designs): dev builds are versions, not a special case
potiuk Sep 21, 2026
53f0b36
docs(designs): implementation plan for reconciliation tracking
potiuk Sep 21, 2026
21089ba
chore(skills): add the generated surface_hash field
potiuk Sep 21, 2026
89dad39
feat(dev): generate a reconciliation fingerprint for every skill
potiuk Sep 21, 2026
f8d59a9
feat(validator): require the generated surface_hash on every skill
potiuk Sep 21, 2026
ee82cc5
docs(setup): specify the reconciled stamp and its marketplace flow
potiuk Sep 21, 2026
a7cb174
docs(setup): fix marketplace-exclusive framing of the reconciled stamp
potiuk Sep 21, 2026
903fcd7
feat(setup): compare each skill against the reconciliation stamp in p…
potiuk Sep 21, 2026
3bfdba2
fix(setup): key the reconciliation stamp by name, gate on nothing-con…
potiuk Sep 21, 2026
53fcb50
fix(setup): skills lives in exactly one store, never both; trim steps…
potiuk Sep 21, 2026
186d1ea
feat(setup): add the reconcile sub-action
potiuk Sep 21, 2026
13b6757
fix(setup): explain why reconcile records acknowledged on decline
potiuk Sep 21, 2026
b644133
feat(setup): verify sweeps reconciliation and reports newer plugin ve…
potiuk Sep 21, 2026
8ce6c9c
feat(setup): config and adopt record what they reconciled
potiuk Sep 21, 2026
359801f
fix(setup): config never writes the committed lock; adopt migrates th…
potiuk Sep 21, 2026
41d3353
fix(setup): config's acknowledged.skills write is scoped to work it did
potiuk Sep 21, 2026
dd32333
feat(dev): widen the surface-hash fingerprint to sibling detail files
potiuk Sep 21, 2026
b936803
chore(skills): regenerate surface_hash for skills with detail files
potiuk Sep 21, 2026
30b471c
fix(setup): widen upgrade.md's anchor check to sibling detail files too
potiuk Sep 21, 2026
0902e07
docs(specs): state the reconciliation guarantee for marketplace installs
potiuk Sep 21, 2026
3d52d23
fix(skill-evals): grade the free-text detail field on two setup fixtures
potiuk Sep 21, 2026
29ce218
fix(skill-evals): update preflight-floor/case-1-at-floor for the reco…
potiuk Sep 21, 2026
d27e620
fix(setup): step 4 skips when step 3 stops, runs through an unknown one
potiuk Sep 21, 2026
28d8949
fix(skill-evals): fix an incidental below-floor plugin in case-6-skil…
potiuk Sep 21, 2026
08c7408
docs(specs): document that the pre-flight reconciliation check is con…
potiuk Sep 21, 2026
7018b10
fix(setup): stop the one-time reconciliation sweep proposing forever
potiuk Sep 21, 2026
bd71c45
docs(setup): correct the design and spec against what shipped
potiuk Sep 21, 2026
98b8e83
test(skill-evals): pin that an existing stamp omitting a skill is silent
potiuk Sep 21, 2026
01776e8
fix(setup): state reconcile's own trigger as the absent stamp
potiuk Sep 21, 2026
c1367fe
fix(skill-evals): give two preflight-floor fixtures the hash step 4 n…
potiuk Sep 21, 2026
486ae46
chore(docs): re-measure setup-isolated-setup-update after the rebase
potiuk Sep 21, 2026
29dcf6b
feat(dev): generalize shared-block propagation to any number of blocks
potiuk Sep 21, 2026
a4b649e
chore(dev): retire check-skill-preflight.py, route the hook to check-…
potiuk Sep 21, 2026
3c541d0
fix(dev): make skill-surface-hash exclude declared blocks, not just p…
potiuk Sep 21, 2026
6b2acfc
feat(setup): extract four shared-prose blocks from setup skill detail…
potiuk Sep 21, 2026
5d2c0d2
fix(dev): re-indent declared blocks in place, restore install.md's li…
potiuk Sep 21, 2026
b1b6715
feat(setup): extract the both-stores-collision rule into a shared block
potiuk Sep 22, 2026
d86e0d1
fix(setup): restore the dropped hand-edit reassurance in the collisio…
potiuk Sep 22, 2026
9f767c3
feat(dev): add check-duplication.py, the cross-file near-duplicate pr…
potiuk Sep 22, 2026
af9cc92
feat(dev): wire the duplication check over the deduplicated surfaces
potiuk Sep 22, 2026
97b5cf7
docs(designs): fold the reconciliation plan back into its design
potiuk Sep 22, 2026
2254422
refactor(setup): split the pre-flight block into a hot path and a col…
potiuk Sep 22, 2026
b1f0fea
refactor(setup): move the conditional pre-flight steps behind the sid…
potiuk Sep 22, 2026
ccb53d0
refactor(setup): reduce steps 8, 9 and 10 to their triggers
potiuk Sep 22, 2026
52c4acf
feat(setup): answer the pre-flight with a tool instead of re-deriving it
potiuk Sep 22, 2026
e55e31c
refactor(setup): ship the pre-flight rules in the tool and emit them …
potiuk Sep 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .lychee.toml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ exclude_path = [
# repos, private IPs, synthetic issue numbers) and are not documentation.
# Link-checking them produces noise with no signal.
"tools/skill-evals/evals",

# Declared shared-block sources (`check-shared-blocks.py`). A block's
# relative links (e.g. `[install.md](install.md#anchor)`) are written to
# resolve from the *host* skill directory the block is propagated into,
# not from `tools/dev/blocks/` itself — the same file is never read
# standalone. The propagated copies are checked normally at their real
# location; checking the source here would just re-report the same
# links as broken from the wrong directory.
"tools/dev/blocks",
]

# Treat unresolvable hostnames the same as failures, no silent passes.
Expand Down
75 changes: 63 additions & 12 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,17 @@ repos:
# Skip the PR template — GitHub pre-populates a new PR description
# with the template verbatim, so a TOC block becomes per-PR noise the
# contributor has to delete by hand.
exclude: ^(\.claude/skills/.*|\.agents/skills/.*|\.github/skills/.*|skills/.*|plugins/magpie-[^/]+/skills/.*|tools/cve-tool-vulnogram/generate-cve-json/SKILL\.md|tools/skill-evals/.*|tools/spec-loop/.*|\.github/PULL_REQUEST_TEMPLATE\.md)$
# Skip every shared-block source (tools/dev/blocks/*.md plus the
# pre-flight block source tools/dev/preflight-block.md, and the
# rules sections under tools/setup-preflight, which the tool emits
# on its own stdout): their SPDX header must be the first thing
# in the file too — `_strip_licence_header()` only strips it there —
# and a TOC block ahead of it would leak the SPDX comment (and an
# empty TOC wrapper) into every propagated copy, same incompatibility
# as the skill definitions above. The block source was not excluded
# before and did carry a TOC, which rode into all 65 propagated
# copies as a table of contents for a file none of them are.
exclude: ^(\.claude/skills/.*|\.agents/skills/.*|\.github/skills/.*|skills/.*|plugins/magpie-[^/]+/skills/.*|tools/cve-tool-vulnogram/generate-cve-json/SKILL\.md|tools/skill-evals/.*|tools/spec-loop/.*|\.github/PULL_REQUEST_TEMPLATE\.md|tools/dev/blocks/.*|tools/dev/preflight-block\.md|tools/setup-preflight/src/setup_preflight/sections/.*)$
args:
- "--maxlevel"
- "3"
Expand Down Expand Up @@ -321,24 +331,65 @@ repos:
entry: python3 tools/dev/check-family-plugins.py --fix
files: ^(skills/.*/SKILL\.md|plugins/.*|\.claude-plugin/(marketplace|plugin)\.json|\.codex-plugin/plugin\.json|\.agents/plugins/marketplace\.json|(plugin|marketplace)\.json|gemini-extension\.json|apm\.yml|pyproject\.toml)$
pass_filenames: false
# The shared setup pre-flight every skill runs before it acts. It cannot be
# a hook: on most harnesses *no code runs at all* when a plugin is installed
# or upgraded (AP1 defines no hook component; Claude Code's SessionStart hook
# Every shared prose block a skill carries — the auto-inserted setup
# pre-flight, plus any number of declared blocks. It cannot be a hook: on
# most harnesses *no code runs at all* when a plugin is installed or
# upgraded (AP1 defines no hook component; Claude Code's SessionStart hook
# is wired only into magpie-setup), so the check has to be instructions the
# agent reads on invocation. It cannot be an include either: a family plugin
# must be self-contained — the packagers drop symlinks rather than follow
# them — so a shared file outside the plugin root would be unreachable from
# the install shape most adopters use. That leaves one source and 65 generated
# copies, which is exactly the drift this hook exists to prevent — edit
# `tools/dev/preflight-block.md` and let `--fix` propagate it. The `setup`
# family is exempt: those skills perform the setup the block asks for.
# the install shape most adopters use. That leaves one source and many
# generated copies per block, which is exactly the drift this hook exists
# to prevent — edit `tools/dev/preflight-block.md` (the pre-flight block)
# or `tools/dev/blocks/<name>.md` (a declared block) and let `--fix`
# propagate it. The `setup` family is exempt from the pre-flight block:
# those skills perform the setup the block asks for.
- repo: local
hooks:
- id: check-skill-preflight
name: check-skill-preflight (shared pre-flight block in every SKILL.md)
- id: check-shared-blocks
name: check-shared-blocks (shared prose blocks in every SKILL.md and sibling detail file)
language: system
entry: python3 tools/dev/check-skill-preflight.py --fix
files: ^(skills/[^/]+/SKILL\.md|plugins/magpie-[^/]+/skills/[^/]+/SKILL\.md|tools/dev/preflight-block\.md)$
entry: python3 tools/dev/check-shared-blocks.py --fix
files: ^(skills/[^/]+/[^/]+\.md|plugins/magpie-[^/]+/skills/[^/]+/[^/]+\.md|tools/dev/preflight-block\.md|tools/dev/preflight-detail\.md|tools/dev/blocks/.*\.md)$
pass_filenames: false
# The reconciliation fingerprint. Runs after check-shared-blocks so it
# hashes the file an adopter actually installs, and before the token
# count so that measurement sees the final bytes. The hash covers only
# `requires_config` and the skill's structural anchors: a reworded
# paragraph must not tell every adopter their configuration went stale,
# and a renamed step must. `files:` matches every `*.md` directly inside a
# skill directory, not just `SKILL.md`, because the fingerprint spans the
# sibling detail files too — a heading renamed in `locks.md` moves the
# `setup` digest, and a `SKILL.md`-only pattern would let that commit pass
# green here and fail on `main`.
- repo: local
hooks:
- id: skill-surface-hash
name: skill-surface-hash (reconciliation fingerprint in every SKILL.md)
language: system
entry: python3 tools/dev/skill-surface-hash.py --fix
files: ^(skills/[^/]+/[^/]+\.md|plugins/magpie-[^/]+/skills/[^/]+/[^/]+\.md)$
pass_filenames: false
# Cross-file near-duplicate prose gate: fails on a paragraph pasted from
# one scoped file into another instead of being pulled into a shared
# block. Wired only over the setup-family surface the shared-block
# extraction actually touched (`WIRED_SKILLS_ROOT` in the script) — the
# design covers the whole `skills/` tree, but that tree carries ~3800
# pre-existing near-duplicate pairs this effort never touched (see the
# script's module docstring, "Landing scope vs. the whole duplication
# problem"), so wiring it there today would fail on day one. `files:`
# only gates *whether* the run fires; the script always scans its whole
# wired scope itself (`pass_filenames: false`), since a diff-scoped run
# cannot see that a paragraph added here duplicates one that already
# exists somewhere the diff never touched.
- repo: local
hooks:
- id: check-duplication
name: check-duplication (cross-file near-duplicate prose, setup-family scope)
language: system
entry: python3 tools/dev/check-duplication.py
files: ^(plugins/magpie-setup/skills/setup/.*\.md|tools/dev/blocks/.*\.md|tools/dev/preflight-block\.md)$
pass_filenames: false
# Deterministic full-file token measurements. Run after skill fixers.
# The dedicated path-filtered CI workflow also catches deleted skills.
Expand Down
7 changes: 6 additions & 1 deletion .typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@
# Ignore git commit hashes (backtick-wrapped hex, 7-40 chars) — they
# routinely contain letter runs typos reads as words (e.g. `9331fb2ba`
# → `ba`). Matches the `In-flight` table's `Implemented by` column.
extend-ignore-re = ["`[0-9a-f]{7,40}`"]
#
# Ignore the generated `surface_hash:` frontmatter field for the same
# reason — a truncated sha256 hex digest routinely contains letter runs
# typos reads as words (e.g. `19ba62ec34a55604` → `ba`). The value is
# written only by `tools/dev/skill-surface-hash.py`, never hand-edited.
extend-ignore-re = ["`[0-9a-f]{7,40}`", "surface_hash: sha256:[0-9a-f]+"]

[default.extend-words]
# Domain terms typos' default dictionary flags as misspellings.
Expand Down
Loading
Loading