fix(dist): ship all 103 skills in dist/pi, pin LF via .gitattributes - #104
Conversation
Git for Windows sets core.autocrlf=true at the system level. Without a committed policy a Windows contributor gets a CRLF working tree while the repository content is LF. The generated distribution is byte-compared against a fresh build by its drift guard, so every file reads as different and the guard is red before it has checked anything. A guard that is always red catches nothing, which is how a missing skill reached the committed distribution unnoticed. This pins eol=lf for skills, workflows, dist, vendor, and the generator inputs and outputs, so the guarantee travels with the repository instead of depending on a local .git/config that exists on one machine. Verified with `git add --renormalize .`: zero content churn, confirming the committed content was already uniformly LF and that this change is preventive rather than corrective. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The committed Pi distribution was missing evidence-based-reviews, shipping 102 of 103 skills. Rebuilt with the standard builder (node scripts/build-pi.mjs). Result: 103 skills, 103 SKILL.md, 490 reference files. Parity now holds across skills/ (103), dist/pi (103) and SKILLS.lock (103). SKILLS.lock is untouched: no file under skills/ changed, and `gen_skills_lock.py --check` reports the lock current. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
CI status, recorded precisely.
The other two workflows did not run, and correctly so. Both are path-filtered:
This PR touches only Worth noting for the follow-up: no workflow has a |
… the catalog Every workflow file, GETTING-STARTED.md, and workflows/README.md told a new user to run only `/plugin marketplace add rampstackco/claude-skills`. That registers the marketplace and installs nothing, so the install path failed for anyone starting clean, including the workflow badged validated. README.md is the known-good source and its canonical form is a two-step: add the marketplace, then install the plugin. CHANGELOG.md already carries the same pair inline. This puts the complete two-step in all 17 affected files, matching each file's existing formatting: backticked in the workflow prerequisites, fenced in workflows/README.md, plain in GETTING-STARTED.md. Proven in a fresh environment with an isolated config dir and no prior catalog install: after the marketplace-add alone, `plugin list` reports no plugins installed, which is the bug. After the full two-step, rampstack-skills@rampstack installs at 1.2.0 and all 13 skill slugs named by content-pipeline-prove-gates resolve. The installed plugin carries 102 skills, not the 103 README advertises, because dist/pi ships 102 against 103 in skills/. That gap is pre-existing and out of scope here; PR #104 is the fix for it. WORKFLOWS.lock regenerated by tools/gen_workflows_lock.py: 15 sha256 values change and nothing else. Keys, filenames, and statuses are unchanged, and content-pipeline-prove-gates keeps its validated status. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… the catalog (#106) Every workflow file, GETTING-STARTED.md, and workflows/README.md told a new user to run only `/plugin marketplace add rampstackco/claude-skills`. That registers the marketplace and installs nothing, so the install path failed for anyone starting clean, including the workflow badged validated. README.md is the known-good source and its canonical form is a two-step: add the marketplace, then install the plugin. CHANGELOG.md already carries the same pair inline. This puts the complete two-step in all 17 affected files, matching each file's existing formatting: backticked in the workflow prerequisites, fenced in workflows/README.md, plain in GETTING-STARTED.md. Proven in a fresh environment with an isolated config dir and no prior catalog install: after the marketplace-add alone, `plugin list` reports no plugins installed, which is the bug. After the full two-step, rampstack-skills@rampstack installs at 1.2.0 and all 13 skill slugs named by content-pipeline-prove-gates resolve. The installed plugin carries 102 skills, not the 103 README advertises, because dist/pi ships 102 against 103 in skills/. That gap is pre-existing and out of scope here; PR #104 is the fix for it. WORKFLOWS.lock regenerated by tools/gen_workflows_lock.py: 15 sha256 values change and nothing else. Keys, filenames, and statuses are unchanged, and content-pipeline-prove-gates keeps its validated status. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
) scripts/build-pi.mjs --check byte-compares the committed distribution against a fresh build. The guard worked, but nothing invoked it, so it had never run in CI once. That is how dist/pi shipped 102 of 103 skills for a full release cycle without a red build, which #104 had to clean up. Triggers on skills/**, dist/**, the builder, .gitattributes, and this file. .gitattributes is load-bearing rather than incidental: the guard compares bytes, so the committed line-ending policy is what keeps a Windows checkout from reading as wholly different. Deliberate consequence, documented in the workflow header and the PR body: a skills-only PR that does not rebuild dist/pi goes red. That is the invariant working, not noise. A shipped distribution has to move with its source in the same PR or the catalog on disk and the catalog users install drift apart silently. The fix for a red run is to rebuild and commit, never to relax the path filter. Scoped to dist/pi, the only distribution target on main. A marked TODO(dist-targets) covers extending to the Codex and Antigravity builders when #87 and #88 land; pre-wiring a step for a builder that does not exist yet would fail on a missing file and teach people to ignore this workflow. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…udit template (W1-a) (#113) The audit template instructed auditors to use Search Console surfaces that no longer exist. Each line is replaced with the current surface named by the currency inventory's verdict rows (all checked 2026-08-09), or deleted where the feature itself is gone and the markup is inert. - robots.txt tester (legacy tester sunset 2023) -> GSC robots.txt report plus Google's open-source parser for local syntax testing - "fetch as Google" (name dead since 2019) -> URL Inspection "Test live URL" - Sitelinks search box / WebSite SearchAction (feature stopped appearing 2024-11-21, docs removed) -> line deleted, the markup does nothing - Mobile Usability report (retired 2023-12-04) -> Lighthouse and Core Web Vitals field data - International Targeting report (removed 2022-09-22) -> URL Inspection plus a third-party crawler Also drops the rel=next/prev pagination requirement. Google confirmed in 2019 it no longer uses those hints, and SKILL.md:65 already says so, so the template was the stale half of a real internal contradiction. The template's own self-canonical pagination line already carries the surviving guidance. Regenerates SKILLS.lock and rebuilds dist/pi, both required by the drift guard (#104/#107) for any skills/** change. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…contract The workflows tier got its honest-stop convention in #110. This is its skills-tier sibling, scoped by the 2026-08 third-party-currency inventory's Part B classification: of 103 skills, 60 specify a deliverable that demands data, measurements, or tool results the executing agent cannot guarantee obtaining. Those 60 gain the block. The 43 that do not are left alone, deliberately, on the same discipline #110 used when it left 14 done-when lines as written. Every one of the 60 gains the identical "If required data is unavailable" section: when a required input, tool, or data source is unavailable or unverifiable, the sanctioned output is the deliverable with the gap stated, naming what was needed, what was actually obtained, and which parts of the output are affected. Fabricating, estimating, or interpolating a required number is never sanctioned. A stated gap is a complete answer. Placement is one structural location across all 60: immediately before "## Reference files". That heading is the only section present in all 60 (Required inputs appears in 37, Output format in 37), so it is the sole anchor that admits a single consistent rule. It also puts the block last in the instructional body, after the output spec it governs and before the pointer list, which carries no instructions. Twenty demanding lines gain the pointer clause "or state the gap per the data-availability rule", one per skill, on the line the inventory quoted as that skill's strongest unconditional demand. Six of the twenty-six quoted lines that live in SKILL.md are left as written: Required-inputs bullets, whose escape path is the block itself exactly as #110 left prerequisites unclaused, and lines that already state an alternative. No skill is restructured; every clause edit is a single-line append. Scope is SKILL.md only. Thirty-four of the sixty quoted demanding lines live in reference files and are not clause-edited here, which is what keeps the lock movement at exactly 60 hashes. The block in SKILL.md governs those references; clausing them is a separate, larger pass. SKILLS.lock regenerates: 60 hashes move, all of them SKILL.md, none added or removed. dist/pi rebuilt from source in the same commit, per the #104 drift invariant.
… the ads cluster (W1-b)
The ads cluster catalogued Google, LinkedIn, TikTok and Meta surfaces that
have been withdrawn or renamed, and stated four platform facts that do not
match the platforms. Every correction below comes from a verdict row in the
2026-08 currency inventory, all checked 2026-08-09.
Retired surfaces (R11 to R15):
- Enhanced CPC: no new campaigns Oct 2024, force-migrated to Manual CPC
Mar 2025. Dropped from the live strategy list, reference section marked
retired with the replacement.
- Google Discovery campaigns: force-upgraded to Demand Gen Jan to Mar 2024.
- LinkedIn Message Ads: phased out May to Jul 2023 for Conversation Ads;
sponsored messaging blocked for EU targeting since Dec 2021.
- LinkedIn Stories: shut down Sep 2021, so the aspect-ratio advice pointed
at a surface that does not exist.
- YouTube "TrueView": name retired, formats are skippable in-stream and
non-skippable in-stream.
Corrected facts (S12 to S15, plus the RSA caps):
- Google DDA has no "600+ conversions/month" requirement. The floors were
removed Oct 2021 when DDA became the default.
- TikTok attribution is Engaged View-Through (6-second view), not "watched
the full video". TikTok accepts 9:16, 1:1 and 16:9, not 9:16 only.
- Meta exposes no "negative feedback rate" column and no 1.5% threshold.
Hide and report signals surface through Quality ranking.
- "Ghost bidding" is a methodology term, not a configurable Google Ads
product. Google's surfaces are Conversion Lift and Experiments.
- RSA guidance said "15+ headlines and 4+ descriptions". 15 and 4 are the
platform caps, so the old phrasing asked for the impossible.
Regenerates SKILLS.lock and rebuilds dist/pi, both required by the drift
guard (#104/#107) for any skills/** change.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… the ads cluster (W1-b) (#114) The ads cluster catalogued Google, LinkedIn, TikTok and Meta surfaces that have been withdrawn or renamed, and stated four platform facts that do not match the platforms. Every correction below comes from a verdict row in the 2026-08 currency inventory, all checked 2026-08-09. Retired surfaces (R11 to R15): - Enhanced CPC: no new campaigns Oct 2024, force-migrated to Manual CPC Mar 2025. Dropped from the live strategy list, reference section marked retired with the replacement. - Google Discovery campaigns: force-upgraded to Demand Gen Jan to Mar 2024. - LinkedIn Message Ads: phased out May to Jul 2023 for Conversation Ads; sponsored messaging blocked for EU targeting since Dec 2021. - LinkedIn Stories: shut down Sep 2021, so the aspect-ratio advice pointed at a surface that does not exist. - YouTube "TrueView": name retired, formats are skippable in-stream and non-skippable in-stream. Corrected facts (S12 to S15, plus the RSA caps): - Google DDA has no "600+ conversions/month" requirement. The floors were removed Oct 2021 when DDA became the default. - TikTok attribution is Engaged View-Through (6-second view), not "watched the full video". TikTok accepts 9:16, 1:1 and 16:9, not 9:16 only. - Meta exposes no "negative feedback rate" column and no 1.5% threshold. Hide and report signals surface through Quality ranking. - "Ghost bidding" is a methodology term, not a configurable Google Ads product. Google's surfaces are Conversion Lift and Experiments. - RSA guidance said "15+ headlines and 4+ descriptions". 15 and 4 are the platform caps, so the old phrasing asked for the impossible. Regenerates SKILLS.lock and rebuilds dist/pi, both required by the drift guard (#104/#107) for any skills/** change. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four corrections in the privacy and security-header guidance. Every one comes
from a verdict row in the 2026-08 currency inventory, all checked 2026-08-09.
- interest-cohort=(): FLoC was abandoned Jan 2022 and Chrome no longer
recognizes the directive (it logs "Unrecognized feature"). The successor
Topics API was itself retired across Chrome 144 to 150 (Jan to Jul 2026),
and third-party cookies remain. Removed from the recommended header and
the explanatory line deleted. No successor directive is worth adding.
- Do Not Track: dead as a standard and as a feature. W3C work stopped in
2019, Safari removed it in 2019, Firefox removed the setting in 135
(Feb 2025). Replaced with Global Privacy Control, which is enforceable
under CCPA and CPRA.
- Mozilla Observatory: deprecated and relaunched in 2024 as the MDN HTTP
Observatory; the old JSON API shut down 2024-10-31. URL updated in both
places that cite it.
- Cloudflare "Attack Challenge Mode": no feature by that name. The feature
is "Under Attack mode". The behavior described was already accurate.
Regenerates SKILLS.lock and rebuilds dist/pi, both required by the drift
guard (#104/#107) for any skills/** change.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…c) (#116) * fix(skills): drop dead privacy signals and fix two product names (W1-c) Four corrections in the privacy and security-header guidance. Every one comes from a verdict row in the 2026-08 currency inventory, all checked 2026-08-09. - interest-cohort=(): FLoC was abandoned Jan 2022 and Chrome no longer recognizes the directive (it logs "Unrecognized feature"). The successor Topics API was itself retired across Chrome 144 to 150 (Jan to Jul 2026), and third-party cookies remain. Removed from the recommended header and the explanatory line deleted. No successor directive is worth adding. - Do Not Track: dead as a standard and as a feature. W3C work stopped in 2019, Safari removed it in 2019, Firefox removed the setting in 135 (Feb 2025). Replaced with Global Privacy Control, which is enforceable under CCPA and CPRA. - Mozilla Observatory: deprecated and relaunched in 2024 as the MDN HTTP Observatory; the old JSON API shut down 2024-10-31. URL updated in both places that cite it. - Cloudflare "Attack Challenge Mode": no feature by that name. The feature is "Under Attack mode". The behavior described was already accurate. Regenerates SKILLS.lock and rebuilds dist/pi, both required by the drift guard (#104/#107) for any skills/** change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(skills): fold in the two approved orphan corrections (HSTS preload, GSC Page indexing) Both were verified by the 2026-08 currency inventory (checked 2026-08-09) but §6 assigned them to no wave, so Wave 1 left them out. Approved to fold in here. - HSTS preload removal is described as taking "weeks". hstspreload.org says it takes months to reach users through a Chrome update, with no guarantee for other browsers. The skill understated the commitment a reader is about to make. Corrected in security-baseline SKILL.md and headers-checklist.md. - GSC's "Coverage report" is now the "Page indexing" report; the Coverage name is gone from Search Console. Corrected in the seo-technical audit template. That file's owning PR (W1-a, #113) is already merged, so this rides here rather than opening a PR for two lines. Regenerates SKILLS.lock and rebuilds dist/pi. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
The creative-brief-selector reference bank cited domains that no longer resolve, or that resolve to the wrong company. Each replacement below was re-fetched live before this commit, not taken on the report's word. - parametric-portfolios.com (NXDOMAIN) -> www.parametricportfolio.com - aerogelichotairballooning.com (NXDOMAIN) -> aerogelicballooning.com - napavalleyaloft.com (DNS timeout) -> nvaloft.com - eldenring.bandainamcoent.com (NXDOMAIN) -> bandainamcoent.com/games/elden-ring - insomniac.com (Insomniac Events, the EDM promoter) -> insomniac.games - magnum.com (an investment-firm login page) -> magnumphotos.com - believermag.com (301 to a culture.org archive) -> www.thebeliever.net - folgers.com (301, benign) -> folgerscoffee.com Two replacements were bot-walled on direct fetch and adjudicated by search rather than called dead, the same method V6 used: www.parametricportfolio.com returns 403 to automated fetches and the naked domain serves an expired certificate, so the www form is used; www.thebeliever.net returns 403 but is confirmed live and back under McSweeney's. Four of the twelve V6 problem URLs are deliberately NOT touched here. Each needs an editorial choice the report did not make, so they are flagged for Wave 2 rather than guessed at: bombasses.com, substack.com/pricing, ranchroadboots.com, deathstranding.com. Detail in the PR body. Regenerates SKILLS.lock and rebuilds dist/pi, both required by the drift guard (#104/#107) for any skills/** change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The creative-brief-selector reference bank cited domains that no longer resolve, or that resolve to the wrong company. Each replacement below was re-fetched live before this commit, not taken on the report's word. - parametric-portfolios.com (NXDOMAIN) -> www.parametricportfolio.com - aerogelichotairballooning.com (NXDOMAIN) -> aerogelicballooning.com - napavalleyaloft.com (DNS timeout) -> nvaloft.com - eldenring.bandainamcoent.com (NXDOMAIN) -> bandainamcoent.com/games/elden-ring - insomniac.com (Insomniac Events, the EDM promoter) -> insomniac.games - magnum.com (an investment-firm login page) -> magnumphotos.com - believermag.com (301 to a culture.org archive) -> www.thebeliever.net - folgers.com (301, benign) -> folgerscoffee.com Two replacements were bot-walled on direct fetch and adjudicated by search rather than called dead, the same method V6 used: www.parametricportfolio.com returns 403 to automated fetches and the naked domain serves an expired certificate, so the www form is used; www.thebeliever.net returns 403 but is confirmed live and back under McSweeney's. Four of the twelve V6 problem URLs are deliberately NOT touched here. Each needs an editorial choice the report did not make, so they are flagged for Wave 2 rather than guessed at: bombasses.com, substack.com/pricing, ranchroadboots.com, deathstranding.com. Detail in the PR body. Regenerates SKILLS.lock and rebuilds dist/pi, both required by the drift guard (#104/#107) for any skills/** change. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ed citation (W1-e) Twenty-seven one-line corrections across 24 files. Every one comes from a verdict row in the 2026-08 currency inventory, all checked 2026-08-09. The one that matters most: pillar-content-architecture used "As Adam Kalai noted in the original CUPED paper" as its worked example of GOOD citation practice. Kalai is not an author of that paper. The CUPED authors are Deng, Xu, Kohavi and Walker (Microsoft, WSDM 2013). A fabricated citation inside the lesson on citing properly is the worst instance in the catalog, so it is corrected to the real authors. Two sibling files also mis-expanded the acronym as "Pre-Existing Data"; the correct expansion is "Pre-Experiment Data". Renamed or absorbed brands: Outbrain is now Teads (3 files), Google Podcasts folded into YouTube Music, Apple Maps Connect is now Apple Business, Amplitude Govern is now Amplitude Data, HomeAdvisor was absorbed into Angi, and the "HBO Max (Max)" parenthetical is backwards since the July 2025 rename back to HBO Max. Misattributions: Kabel was designed by Rudolf Koch, not Hermann Zapf (Zapf designed Optima, which the same file cites correctly). The BBC has used custom BBC Reith since 2017, not Gill Sans. Mailchimp retired the script wordmark in the 2018 rebrand; it is Cooper-derived serif now. Two sibling files had Anthropic's and OpenAI's marks swapped: OpenAI has the flower-like Blossom, Anthropic has neither a flower nor a hex grid. Corrected facts: X premium posts allow 25,000 characters, not 4,000. Safari's ITP spans every Apple platform including macOS, so scoping it to iOS scopes the attribution problem wrongly. Yarn 2+ uses "yarn npm audit". Folgers is the red can, not the blue one. CRAN's R package is "Sequential" and implements MaxSPRT safety surveillance, not the mSPRT A/B testing the surrounding text implies. Defunct exemplars are marked historical rather than deleted, per the report: Ueno (shut down 2021), Xobni (2014), Sprint (absorbed into T-Mobile 2020). Opsgenie gets an interim do-not-onboard note with the end-of-sale and end-of-support dates. The full monitoring-vendor list refresh is Wave 2 ruling R-6 and is deliberately not attempted here. Regenerates SKILLS.lock and rebuilds dist/pi, both required by the drift guard (#104/#107) for any skills/** change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ed citation (W1-e) (#118) * fix(skills): correct misattributions, renamed brands and one fabricated citation (W1-e) Twenty-seven one-line corrections across 24 files. Every one comes from a verdict row in the 2026-08 currency inventory, all checked 2026-08-09. The one that matters most: pillar-content-architecture used "As Adam Kalai noted in the original CUPED paper" as its worked example of GOOD citation practice. Kalai is not an author of that paper. The CUPED authors are Deng, Xu, Kohavi and Walker (Microsoft, WSDM 2013). A fabricated citation inside the lesson on citing properly is the worst instance in the catalog, so it is corrected to the real authors. Two sibling files also mis-expanded the acronym as "Pre-Existing Data"; the correct expansion is "Pre-Experiment Data". Renamed or absorbed brands: Outbrain is now Teads (3 files), Google Podcasts folded into YouTube Music, Apple Maps Connect is now Apple Business, Amplitude Govern is now Amplitude Data, HomeAdvisor was absorbed into Angi, and the "HBO Max (Max)" parenthetical is backwards since the July 2025 rename back to HBO Max. Misattributions: Kabel was designed by Rudolf Koch, not Hermann Zapf (Zapf designed Optima, which the same file cites correctly). The BBC has used custom BBC Reith since 2017, not Gill Sans. Mailchimp retired the script wordmark in the 2018 rebrand; it is Cooper-derived serif now. Two sibling files had Anthropic's and OpenAI's marks swapped: OpenAI has the flower-like Blossom, Anthropic has neither a flower nor a hex grid. Corrected facts: X premium posts allow 25,000 characters, not 4,000. Safari's ITP spans every Apple platform including macOS, so scoping it to iOS scopes the attribution problem wrongly. Yarn 2+ uses "yarn npm audit". Folgers is the red can, not the blue one. CRAN's R package is "Sequential" and implements MaxSPRT safety surveillance, not the mSPRT A/B testing the surrounding text implies. Defunct exemplars are marked historical rather than deleted, per the report: Ueno (shut down 2021), Xobni (2014), Sprint (absorbed into T-Mobile 2020). Opsgenie gets an interim do-not-onboard note with the end-of-sale and end-of-support dates. The full monitoring-vendor list refresh is Wave 2 ruling R-6 and is deliberately not attempted here. Regenerates SKILLS.lock and rebuilds dist/pi, both required by the drift guard (#104/#107) for any skills/** change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(skills): fold in the Anthropic mark orphan correction, regenerate lock and dist Third and last of the approved orphan corrections. Verified by the 2026-08 currency inventory (S19, checked 2026-08-09) but assigned to no wave by §6. - category-conventions.md:379 described Anthropic as having an "abstract gesture symbol". The S19 verdict is that Anthropic has neither a flower nor a hex grid nor a separate symbol: it uses a minimalist lowercase wordmark plus the slanted-A glyph. W1-e already corrected the two lines the verdict row cites (:264 and :340); this is the same defect on the line it did not cite. Also regenerates SKILLS.lock and dist/pi. The rebase onto main conflicted in both generated files plus the folgers reference line. The generated files were NOT hand-merged: they were staged as placeholders to let the rebase complete, then regenerated from source, which corrected 24 lines of SKILLS.lock that the placeholder had wrong. The folgers line was a genuine content conflict, resolved to carry both halves: W1-d's URL fix (folgers.com -> folgerscoffee.com, merged in #117) and W1-e's blue-can -> red-can correction. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…contract The workflows tier got its honest-stop convention in #110. This is its skills-tier sibling, scoped by the 2026-08 third-party-currency inventory's Part B classification: of 103 skills, 60 specify a deliverable that demands data, measurements, or tool results the executing agent cannot guarantee obtaining. Those 60 gain the block. The 43 that do not are left alone, deliberately, on the same discipline #110 used when it left 14 done-when lines as written. Every one of the 60 gains the identical "If required data is unavailable" section: when a required input, tool, or data source is unavailable or unverifiable, the sanctioned output is the deliverable with the gap stated, naming what was needed, what was actually obtained, and which parts of the output are affected. Fabricating, estimating, or interpolating a required number is never sanctioned. A stated gap is a complete answer. Placement is one structural location across all 60: immediately before "## Reference files". That heading is the only section present in all 60 (Required inputs appears in 37, Output format in 37), so it is the sole anchor that admits a single consistent rule. It also puts the block last in the instructional body, after the output spec it governs and before the pointer list, which carries no instructions. Twenty demanding lines gain the pointer clause "or state the gap per the data-availability rule", one per skill, on the line the inventory quoted as that skill's strongest unconditional demand. Six of the twenty-six quoted lines that live in SKILL.md are left as written: Required-inputs bullets, whose escape path is the block itself exactly as #110 left prerequisites unclaused, and lines that already state an alternative. No skill is restructured; every clause edit is a single-line append. Scope is SKILL.md only. Thirty-four of the sixty quoted demanding lines live in reference files and are not clause-edited here, which is what keeps the lock movement at exactly 60 hashes. The block in SKILL.md governs those references; clausing them is a separate, larger pass. SKILLS.lock regenerates: 60 hashes move, all of them SKILL.md, none added or removed. dist/pi rebuilt from source in the same commit, per the #104 drift invariant.
…contract (#115) The workflows tier got its honest-stop convention in #110. This is its skills-tier sibling, scoped by the 2026-08 third-party-currency inventory's Part B classification: of 103 skills, 60 specify a deliverable that demands data, measurements, or tool results the executing agent cannot guarantee obtaining. Those 60 gain the block. The 43 that do not are left alone, deliberately, on the same discipline #110 used when it left 14 done-when lines as written. Every one of the 60 gains the identical "If required data is unavailable" section: when a required input, tool, or data source is unavailable or unverifiable, the sanctioned output is the deliverable with the gap stated, naming what was needed, what was actually obtained, and which parts of the output are affected. Fabricating, estimating, or interpolating a required number is never sanctioned. A stated gap is a complete answer. Placement is one structural location across all 60: immediately before "## Reference files". That heading is the only section present in all 60 (Required inputs appears in 37, Output format in 37), so it is the sole anchor that admits a single consistent rule. It also puts the block last in the instructional body, after the output spec it governs and before the pointer list, which carries no instructions. Twenty demanding lines gain the pointer clause "or state the gap per the data-availability rule", one per skill, on the line the inventory quoted as that skill's strongest unconditional demand. Six of the twenty-six quoted lines that live in SKILL.md are left as written: Required-inputs bullets, whose escape path is the block itself exactly as #110 left prerequisites unclaused, and lines that already state an alternative. No skill is restructured; every clause edit is a single-line append. Scope is SKILL.md only. Thirty-four of the sixty quoted demanding lines live in reference files and are not clause-edited here, which is what keeps the lock movement at exactly 60 hashes. The block in SKILL.md governs those references; clausing them is a separate, larger pass. SKILLS.lock regenerates: 60 hashes move, all of them SKILL.md, none added or removed. dist/pi rebuilt from source in the same commit, per the #104 drift invariant.
What this fixes
The committed Pi distribution shipped 102 of 103 skills:
evidence-based-reviewswas absent. This PR rebuilds it, and adds the.gitattributespolicy that prevents the class of blindness which let it ship unnoticed.Refreshed onto current main (post-#106)
Update method: merge, not rebase.
mainmoved while this sat held: #106 squash-merged as45641e9, changing the install line in all 15 workflow files plusworkflows/README.mdandworkflows/GETTING-STARTED.md. I mergedorigin/maininto this branch as1e8368c. Merge rather than rebase because the branch is a pushed held draft, merge needs no force-push, and the squash-merge collapses the merge commit anyway. No conflicts.Diff scope against the refreshed
mainis unchanged, still four additions and zero modifications:Line endings: renormalize result is ZERO diffs
With this PR's
.gitattributesin effect over the merged tree:Zero files changed. #106 shipped LF, not CRLF, so there is nothing here to correct. Confirmed independently by scanning the committed blobs rather than trusting the working tree:
The attributes are genuinely in force, so that zero is a real result and not a no-op:
This is the outcome the PR wanted rather than a missed defect. It also keeps the PR's original framing intact: on line endings this change stays preventive, not corrective.
Correcting the premise (please read, it changes what this PR is)
The audit that prompted this work reported that "the committed dist is CRLF while source is LF." That is not the case, and I verified it rather than assuming it.
git ls-files --eolbefore any change:i/lfon both sides means the committed content was already uniformly LF. The CRLF existed only in the working tree copy ofdist/. Confirmed independently:git add --renormalize .produced zero content churn.The cause is that Git for Windows sets
core.autocrlf=trueat the system level. This repo happens to carrycore.autocrlf=falsein a local.git/config, which is not committed and exists on one machine. Any contributor without it gets a CRLF working tree,build-pi.mjs --checkbyte-compares a fresh build against it, every file reads as different, and the guard is red before it has checked anything. A guard that is always red catches nothing.So this PR is preventive, not corrective, on line endings. There is no normalization diff because there was nothing committed to normalize. The one real defect was the missing skill.
Diff scope
Four additions, zero modifications, zero deletions:
Guard proof, red and green both ways
A guard that has only ever been seen green is not verified. Run on
dist/pi:Re-run in full against the merged tree (not carried over from the earlier run):
--checkexitevidence-based-reviews/SKILL.mdcontent differs: evidence-based-reviews/SKILL.mdcontent differs: evidence-based-reviews/SKILL.mdWorking tree clean after restore (
git status --shortempty).Step 3 matters most: it proves the guard detects the exact failure mode at issue, rather than only detecting content edits.
Fresh-clone verification
The real test of
.gitattributesis whether it survives a contributor who does not have the local override. Cloned the branch withcore.autocrlf=trueforced:Before this PR the same clone produced a CRLF working tree and a wholesale-red guard.
Distribution target sweep
The dispatch asked for a sweep of codex, antigravity, and any other targets. Only one distribution target exists in this repository. Evidence:
Open PRs #87 and #88 would add
dist/antigravityanddist/codex, but neither is merged and neither touches.gitattributesordist/pi, so they do not overlap this PR. Inventory check across all open PRs: #104 is the only one touching.gitattributesordist/pi.The Codex and Antigravity dists are referenced only in a comparative comment at
scripts/build-pi.mjs:8-9; they live in sibling family repos, not here. I did not invent results for targets that are not present.dist/pii/lf w/lf.claude-plugin/manifestsSKILLS.lock
Untouched, and it should be. Re-confirmed after the merge:
git diff origin/main HEAD -- SKILLS.lock WORKFLOWS.lockis empty, so normalization forced no hash changes in either lock. No file underskills/changed in this PR, so there are no hashes to move.python tools/gen_skills_lock.py --checkreportsSKILLS.lock is current.There are therefore no line-ending-driven hash changes to report, because there are no hash changes at all.Verification suite
node scripts/build-pi.mjs --checknode scripts/build-pi.mjs --validatetools/gen_skills_lock.py --checkSKILLS.lock is current.tools/gen_workflows_lock.py --checktools/check_workflow_drift.pyscripts/generate_readme_catalog.py --check.github/scripts/lint_skills.pyLinter note, stated plainly: the linter exits non-zero locally with
BRAND_WATCHLIST_FILE is not set. This is environmental, not a regression. I verified it fails identically on a pristineorigin/mainworktree, so it is pre-existing and unrelated to this change. CI fetches the watchlist from the privaterampstack/lint-config, so it should pass there. Itscheck_em_dashescheck reported[OK].Recommended follow-up, not done here
build-pi.mjs --checkis not wired into CI. Nothing under.github/workflows/references it, so the distribution drift guard has never run automatically. Fixing the guard's blindness does not help if nobody runs it. A one-job addition to a workflow would close this properly, but it is outside the scope I was given, so I have left it for a separate decision.Held as a draft.