[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6C24J9YBF299XQMBXBY29ZP":3,"skill-same:01M6C24J9YBF299XQMBXBY29ZP":57},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":29,"linkOnly":30,"markdownContent":31,"markdownBody":32,"frontMatter":33,"refName":34,"commitSha":35,"skillDirectory":36,"forksCount":37,"repositoryHtmlUrl":38,"repositoryHomepageUrl":6,"ownerHtmlUrl":39,"ownerBlogUrl":40,"ownerDescription":41,"updatedAt":42,"install":43,"resources":56},"01M6C24J9YBF299XQMBXBY29ZP","auditing-laravel-idioms",null,"Audit the project's cache, session and request-data usage to confirm modern Laravel idioms (typed cache getters, BackedEnum keys, whenFilledEnum) are followed. Use when asked to audit or check modern Laravel idiom adoption, or when prompted by the `followsModernLaravelIdioms` periodic baseline check.","limenet\u002Flaravel-baseline","limenet","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F474329?v=4","01M6C245N93511GTPJXWYT8EN8","Linus Metzler","01M6C245S4JHJBWSJB6XP1W5K3",2,"MIT","https:\u002F\u002Fgithub.com\u002Flimenet\u002Flaravel-baseline\u002Fblob\u002Fmain\u002Fresources\u002Fboost\u002Fskills\u002Fauditing-laravel-idioms\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28],"laravel","auditing laravel idioms","audit","cache","adoption","data","baseline","check","session","use","2026-11-10 10:12:30",false,"---\nname: auditing-laravel-idioms\ndescription: Audit the project's cache, session and request-data usage to confirm modern Laravel idioms (typed cache getters, BackedEnum keys, whenFilledEnum) are followed. Use when asked to audit or check modern Laravel idiom adoption, or when prompted by the `followsModernLaravelIdioms` periodic baseline check.\n---\n\n# Auditing Laravel idioms\n\nThis project (per the [limenet\u002Flaravel-baseline](https:\u002F\u002Fgithub.com\u002Flimenet\u002Flaravel-baseline)\nstandards) prefers current framework idioms for cache access, session access and reading backed\nenums out of request data. This skill scans the app code for the older patterns and reports where\nthey can be modernised.\n\n## When to use this skill\n\nUse this when the task is to audit or check whether the project follows modern Laravel idioms for\ncache, session and request-data usage. This is the skill the `followsModernLaravelIdioms` periodic\ncheck (from limenet\u002Flaravel-baseline) points developers to — run it when that check prompts you, or\nwhenever someone asks to review modern Laravel idiom adoption.\n\nThe idioms in scope:\n\n1. **Typed cache getters** instead of `Cache::get()` for typed values *(Laravel 12.45+ \u002F 13.x)*.\n2. **`BackedEnum` keys passed directly** to cache\u002Fsession instead of unwrapping `->value`\n   *(Laravel 12.45+ \u002F 13.x)*.\n3. **`whenFilledEnum()`** instead of `whenFilled()` plus a manual `tryFrom()` null guard when\n   reading a backed enum out of request data *(Laravel 13.16+)*.\n\nCheck the `laravel\u002Fframework` constraint in `composer.json` before auditing: skip idiom 3 entirely\nif the project is not on Laravel 13.16 or newer.\n\n## How to audit\n\nRun grep\u002Fripgrep over the application code (`app\u002F`, `routes\u002F`, and any other first-party\ndirectories) to find the older patterns. The matches are candidates, not certain violations —\nread each one in context before reporting.\n\n**Typed cache getters.** Find `Cache::get(` \u002F `cache()->get(` calls (and `->get(` on cache\nrepository instances) where the result is used as a typed scalar or array. These are candidates\nto replace with `Cache::string()` \u002F `Cache::integer()` \u002F `Cache::float()` \u002F `Cache::boolean()` \u002F\n`Cache::array()`:\n\n```bash\nrg \"Cache::get\\(|cache\\(\\)->get\\(\" app\u002F\n# only read calls have typed variants — put\u002Fadd\u002Fforever\u002Fforget\u002Fhas\u002Fincrement have none\n```\n\n**BackedEnum keys.** Find `->value` being passed into a cache or session key argument — e.g.\n`Cache::put(SomeEnum::Foo->value, ...)`, `session()->get(SomeEnum::Bar->value)`. These can drop\nthe `->value` and pass the enum case directly:\n\n```bash\nrg \"->value\" app\u002F | rg -i \"cache|session\"\n```\n\nInspect each hit: confirm the `->value` is in fact a cache\u002Fsession **key** (not a value being\nstored or compared) before flagging it.\n\n**`whenFilledEnum()`.** Find `whenFilled(` calls whose closure body resolves a backed enum — the\ntell is a `tryFrom(` (or `from(`) call on the closure parameter, usually followed by a `null`\nguard:\n\n```bash\nrg -A 6 \"whenFilled\\(\" app\u002F | rg -B 2 \"tryFrom\\(|::from\\(\"\n```\n\nRead the whole closure before flagging: the rewrite only applies when the enum resolution is the\nclosure's **guard** — i.e. an invalid value means the closure does nothing. If the `null` branch\ndoes real work (falls back to another filter, adds a validation error, throws), that behaviour\nbelongs in `whenFilledEnum()`'s optional fourth callback, so mention it rather than dropping it.\nLeave the call alone when the enum is only one of several things the closure does, or when the\nclosure keeps using the raw string as well.\n\n## What to report\n\nPresent findings for the developer to confirm — **do not auto-rewrite** unless the user explicitly\nasks. For each candidate, list:\n\n- The `file:line` location.\n- The suggested modern replacement (e.g. `Cache::get('foo')` → `Cache::string('foo')`,\n  `Cache::put(CacheKey::Foo->value, $x)` → `Cache::put(CacheKey::Foo, $x)`, or a `whenFilled()` +\n  `tryFrom()` block → `whenFilledEnum('key', Status::class, ...)`).\n\nNotes to include with the report:\n\n- These are **style \u002F modernisation improvements, not bugs** — the existing code works.\n- Typed getters **throw on a type mismatch**, so a blind replacement can change behaviour if a\n  cached value's runtime type is uncertain. Only suggest a typed getter where the expected type is\n  clear, and call out any case where it isn't.\n\n## Record the run (last)\n\nOnce the report has been presented, mark the `followsModernLaravelIdioms` periodic check as done so\nit stops prompting for the next 30 days. `limenet:laravel-baseline:periodic` asks for confirmation\ninteractively, so write the timestamp into `config\u002Fbaseline.php` directly instead. Get the current\ntime in the format the baseline writes:\n\n```bash\nddev php -r 'echo date(DATE_ATOM), PHP_EOL;'\n```\n\nSet it under the `periodic` key, adding that key if it does not exist yet, and leave `excludes` and\nevery other entry untouched:\n\n```php\nreturn [\n    'excludes' => [],\n    'periodic' => [\n        'followsModernLaravelIdioms' => '2026-01-31T09:15:00+00:00',\n    ],\n];\n```\n\nRecord the run even when there are no findings or the developer declines every suggestion — the\ndate records a completed audit, not applied rewrites. Skip it only if the audit was abandoned before\nthe whole app code was scanned.\n\n## Conventions\n\n- **Typed cache getters.** Prefer `Cache::string()`, `Cache::integer()`, `Cache::float()`,\n  `Cache::boolean()`, `Cache::array()` (each `($key, $default)`) over `Cache::get()` when reading a\n  value of a known scalar\u002Farray type.\n- **BackedEnum keys passed directly.** Pass a `BackedEnum` case straight to cache\u002Fsession keys\n  (`Cache::put(CacheKey::Profile, $data)`, `session()->put(CheckoutSession::Cart, $items)`) instead\n  of unwrapping `->value`.\n- **`whenFilledEnum()` for request data.** Use\n  `$request->whenFilledEnum('status', Status::class, fn (Status $status) => …)` over `whenFilled()`\n  with a manual `tryFrom()` and null guard. The callback fires only when the key is filled and the\n  value maps to a valid case, and receives a typed enum instance; an optional fourth callback runs\n  when it doesn't. Available on anything using `InteractsWithData` — `Request`, form requests, etc.\n\nThe first two idioms require Laravel 12.45+ \u002F 13.x; `whenFilledEnum()` requires Laravel 13.16+.\n","# Auditing Laravel idioms\n\nThis project (per the [limenet\u002Flaravel-baseline](https:\u002F\u002Fgithub.com\u002Flimenet\u002Flaravel-baseline)\nstandards) prefers current framework idioms for cache access, session access and reading backed\nenums out of request data. This skill scans the app code for the older patterns and reports where\nthey can be modernised.\n\n## When to use this skill\n\nUse this when the task is to audit or check whether the project follows modern Laravel idioms for\ncache, session and request-data usage. This is the skill the `followsModernLaravelIdioms` periodic\ncheck (from limenet\u002Flaravel-baseline) points developers to — run it when that check prompts you, or\nwhenever someone asks to review modern Laravel idiom adoption.\n\nThe idioms in scope:\n\n1. **Typed cache getters** instead of `Cache::get()` for typed values *(Laravel 12.45+ \u002F 13.x)*.\n2. **`BackedEnum` keys passed directly** to cache\u002Fsession instead of unwrapping `->value`\n   *(Laravel 12.45+ \u002F 13.x)*.\n3. **`whenFilledEnum()`** instead of `whenFilled()` plus a manual `tryFrom()` null guard when\n   reading a backed enum out of request data *(Laravel 13.16+)*.\n\nCheck the `laravel\u002Fframework` constraint in `composer.json` before auditing: skip idiom 3 entirely\nif the project is not on Laravel 13.16 or newer.\n\n## How to audit\n\nRun grep\u002Fripgrep over the application code (`app\u002F`, `routes\u002F`, and any other first-party\ndirectories) to find the older patterns. The matches are candidates, not certain violations —\nread each one in context before reporting.\n\n**Typed cache getters.** Find `Cache::get(` \u002F `cache()->get(` calls (and `->get(` on cache\nrepository instances) where the result is used as a typed scalar or array. These are candidates\nto replace with `Cache::string()` \u002F `Cache::integer()` \u002F `Cache::float()` \u002F `Cache::boolean()` \u002F\n`Cache::array()`:\n\n```bash\nrg \"Cache::get\\(|cache\\(\\)->get\\(\" app\u002F\n# only read calls have typed variants — put\u002Fadd\u002Fforever\u002Fforget\u002Fhas\u002Fincrement have none\n```\n\n**BackedEnum keys.** Find `->value` being passed into a cache or session key argument — e.g.\n`Cache::put(SomeEnum::Foo->value, ...)`, `session()->get(SomeEnum::Bar->value)`. These can drop\nthe `->value` and pass the enum case directly:\n\n```bash\nrg \"->value\" app\u002F | rg -i \"cache|session\"\n```\n\nInspect each hit: confirm the `->value` is in fact a cache\u002Fsession **key** (not a value being\nstored or compared) before flagging it.\n\n**`whenFilledEnum()`.** Find `whenFilled(` calls whose closure body resolves a backed enum — the\ntell is a `tryFrom(` (or `from(`) call on the closure parameter, usually followed by a `null`\nguard:\n\n```bash\nrg -A 6 \"whenFilled\\(\" app\u002F | rg -B 2 \"tryFrom\\(|::from\\(\"\n```\n\nRead the whole closure before flagging: the rewrite only applies when the enum resolution is the\nclosure's **guard** — i.e. an invalid value means the closure does nothing. If the `null` branch\ndoes real work (falls back to another filter, adds a validation error, throws), that behaviour\nbelongs in `whenFilledEnum()`'s optional fourth callback, so mention it rather than dropping it.\nLeave the call alone when the enum is only one of several things the closure does, or when the\nclosure keeps using the raw string as well.\n\n## What to report\n\nPresent findings for the developer to confirm — **do not auto-rewrite** unless the user explicitly\nasks. For each candidate, list:\n\n- The `file:line` location.\n- The suggested modern replacement (e.g. `Cache::get('foo')` → `Cache::string('foo')`,\n  `Cache::put(CacheKey::Foo->value, $x)` → `Cache::put(CacheKey::Foo, $x)`, or a `whenFilled()` +\n  `tryFrom()` block → `whenFilledEnum('key', Status::class, ...)`).\n\nNotes to include with the report:\n\n- These are **style \u002F modernisation improvements, not bugs** — the existing code works.\n- Typed getters **throw on a type mismatch**, so a blind replacement can change behaviour if a\n  cached value's runtime type is uncertain. Only suggest a typed getter where the expected type is\n  clear, and call out any case where it isn't.\n\n## Record the run (last)\n\nOnce the report has been presented, mark the `followsModernLaravelIdioms` periodic check as done so\nit stops prompting for the next 30 days. `limenet:laravel-baseline:periodic` asks for confirmation\ninteractively, so write the timestamp into `config\u002Fbaseline.php` directly instead. Get the current\ntime in the format the baseline writes:\n\n```bash\nddev php -r 'echo date(DATE_ATOM), PHP_EOL;'\n```\n\nSet it under the `periodic` key, adding that key if it does not exist yet, and leave `excludes` and\nevery other entry untouched:\n\n```php\nreturn [\n    'excludes' => [],\n    'periodic' => [\n        'followsModernLaravelIdioms' => '2026-01-31T09:15:00+00:00',\n    ],\n];\n```\n\nRecord the run even when there are no findings or the developer declines every suggestion — the\ndate records a completed audit, not applied rewrites. Skip it only if the audit was abandoned before\nthe whole app code was scanned.\n\n## Conventions\n\n- **Typed cache getters.** Prefer `Cache::string()`, `Cache::integer()`, `Cache::float()`,\n  `Cache::boolean()`, `Cache::array()` (each `($key, $default)`) over `Cache::get()` when reading a\n  value of a known scalar\u002Farray type.\n- **BackedEnum keys passed directly.** Pass a `BackedEnum` case straight to cache\u002Fsession keys\n  (`Cache::put(CacheKey::Profile, $data)`, `session()->put(CheckoutSession::Cart, $items)`) instead\n  of unwrapping `->value`.\n- **`whenFilledEnum()` for request data.** Use\n  `$request->whenFilledEnum('status', Status::class, fn (Status $status) => …)` over `whenFilled()`\n  with a manual `tryFrom()` and null guard. The callback fires only when the key is filled and the\n  value maps to a valid case, and receives a typed enum instance; an optional fourth callback runs\n  when it doesn't. Available on anything using `InteractsWithData` — `Request`, form requests, etc.\n\nThe first two idioms require Laravel 12.45+ \u002F 13.x; `whenFilledEnum()` requires Laravel 13.16+.\n",{"name":5,"description":7},"main","5e0daa3a0ad957378e4e551c5bdeedda5cb5240f","resources\u002Fboost\u002Fskills\u002Fauditing-laravel-idioms",0,"https:\u002F\u002Fgithub.com\u002Flimenet\u002Flaravel-baseline","https:\u002F\u002Fgithub.com\u002Flimenet","http:\u002F\u002Flinusmetzler.me","run, ride, travel, hike","2026-11-06 16:08:08",{"source":8,"skillName":5,"commands":44,"prompt":54,"zipAvailable":55},[45,48,51],{"tool":46,"command":47},"npx","npx skills add limenet\u002Flaravel-baseline --skill auditing-laravel-idioms",{"tool":49,"command":50},"bunx","bunx skills add limenet\u002Flaravel-baseline --skill auditing-laravel-idioms",{"tool":52,"command":53},"pnpm","pnpm dlx skills add limenet\u002Flaravel-baseline --skill auditing-laravel-idioms","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flimenet\u002Flaravel-baseline\u002Fblob\u002Fmain\u002Fresources\u002Fboost\u002Fskills\u002Fauditing-laravel-idioms\u002FSKILL.md",true,[],[58,73,90,101,106,111],{"skillNo":59,"name":60,"nameZh":6,"description":61,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":62,"categories":63,"keywords":64,"publishedAt":29},"01M6C24Z6FHC8JGEG4DWY84TKQ","updating-dependencies","Update the project's composer and npm dependencies, review changelogs for their impact on this project, and report majors blocked by semver. Use when asked to update or upgrade dependencies, run the monthly dependency update, or when prompted by the `updatesDependencies` periodic baseline check.","https:\u002F\u002Fgithub.com\u002Flimenet\u002Flaravel-baseline\u002Fblob\u002Fmain\u002Fresources\u002Fstandalone\u002Fskills\u002Fupdating-dependencies\u002FSKILL.md",[],[65,66,67,68,69,70,71,72,25,26,28],"updating dependencies","review","dependency update","run","update","report","semver","npm",{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":29},"01M6C24WZ5XGG5J9V5ME56NPGM","ignoring-trivy-findings","Add, renew, or prune entries in .trivyignore.yaml — either short-lived because the fixed version is still inside the npm install cooldown, or longer-lived because the upgrade is blocked by a project constraint. Use when the Trivy `security` CI job fails on a vulnerability, when asked to ignore or suppress a Trivy finding, or when reviewing existing Trivy ignores.","https:\u002F\u002Fgithub.com\u002Flimenet\u002Flaravel-baseline\u002Fblob\u002Fmain\u002Fresources\u002Fstandalone\u002Fskills\u002Fignoring-trivy-findings\u002FSKILL.md",[],[80,81,82,72,83,84,85,86,87,88,28,89],"ignoring trivy findings","trivy","security","yaml","ci","vulnerability","prune","short","install","version",{"skillNo":91,"name":92,"nameZh":6,"description":93,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":29},"01M6C24TSQ8F73SBVP3T7PHZ2X","creating-a-release","Cut, tag, and publish a new release of this project using release-it. Use when asked to create, cut, tag, or publish a release, or bump the project version.","https:\u002F\u002Fgithub.com\u002Flimenet\u002Flaravel-baseline\u002Fblob\u002Fmain\u002Fresources\u002Fstandalone\u002Fskills\u002Fcreating-a-release\u002FSKILL.md",[],[97,98,28,89,99,100],"creating a release","release","create","publish",{"skillNo":102,"name":60,"nameZh":6,"description":61,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":105,"publishedAt":29},"01M6C24RK5FJTTRE247968HJ41","https:\u002F\u002Fgithub.com\u002Flimenet\u002Flaravel-baseline\u002Fblob\u002Fmain\u002Fresources\u002Fboost\u002Fskills\u002Fupdating-dependencies\u002FSKILL.md",[],[65,69,66,67,68,70,71,72,25,26,28],{"skillNo":107,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":110,"publishedAt":29},"01M6C24PGHWX6N4V6PRRZR2AMS","https:\u002F\u002Fgithub.com\u002Flimenet\u002Flaravel-baseline\u002Fblob\u002Fmain\u002Fresources\u002Fboost\u002Fskills\u002Fignoring-trivy-findings\u002FSKILL.md",[],[80,81,83,84,82,85,86,87,88,28,89,72],{"skillNo":112,"name":92,"nameZh":6,"description":113,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":114,"categories":115,"keywords":116,"publishedAt":29},"01M6C24MN9B35Y3GF4JYAAX20Z","Cut, tag, and publish a new release of this Laravel project using release-it. Use when asked to create, cut, tag, or publish a release, or bump the project version.","https:\u002F\u002Fgithub.com\u002Flimenet\u002Flaravel-baseline\u002Fblob\u002Fmain\u002Fresources\u002Fboost\u002Fskills\u002Fcreating-a-release\u002FSKILL.md",[],[98,97,28,19,100,99,89]]