[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6X72FTPNEG6KAPW59BP1TQ3":3,"skill-same:01M6X72FTPNEG6KAPW59BP1TQ3":73},{"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":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":51,"commitSha":52,"skillDirectory":53,"forksCount":54,"repositoryHtmlUrl":55,"repositoryHomepageUrl":56,"ownerHtmlUrl":57,"ownerBlogUrl":56,"ownerDescription":58,"updatedAt":59,"install":60,"resources":72},"01M6X72FTPNEG6KAPW59BP1TQ3","laravel-validation",null,"When writing validation — Form Requests, rules, custom rule objects, request-boundary design — even when the user just says 'validate this input' or 'check the request' without naming it.","event4u-app\u002Fagent-config","event4u-app","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F199339632?v=4","01M6X5TWBNCQCE1VDKT4E9KF7N","event4u.app","01M6X5TWF4HRM266RG2Q5VVH1X",19,"MIT","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Flaravel-validation\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"validation","laravel","laravel validation","input","when","request","custom","true","requests","naming","form","professional","design","false","objects","check","just","Rules","boundary","writing","2026-11-10 10:12:30",false,"---\nmodel_tier: medium\nname: laravel-validation\ndescription: \"When writing validation — Form Requests, rules, custom rule objects, request-boundary design — even when the user just says 'validate this input' or 'check the request' without naming it.\"\ndomain: engineering\nworkspaces:\n  - engineering\npacks:\n  - laravel\ntrust:\n  level: professional\ninstall:\n  default: false\n  removable: true\n---\n\n# laravel-validation\n\n## When to use\n\nUse when creating FormRequests, validation rules, or custom rule objects.\n\nDo NOT use when:\n- Authorization logic only (use `security` skill)\n- API response format (use `api-design` skill)\n\n## Procedure: Create a FormRequest\n\n### Step 0: Inspect\n\n1. Check existing FormRequests — match style, naming, authorization, rule structure.\n2. Check existing custom rules — reuse before creating new ones.\n3. Check API error response format — match it.\n\n### Step 1: Create the class\n\n1. Name: `{Action}{Entity}Request` — e.g. `CreateProjectRequest`.\n2. Implement `authorize()` using Policies.\n3. Implement `rules()` with array syntax — never pipe-separated.\n4. Use `prepareForValidation()` only when normalization is truly necessary.\n\n### Step 2: Rules\n\n1. Use Laravel's `Illuminate\\Validation\\Rules` classes where possible.\n2. Keep rules explicit — prefer clarity over cleverness.\n3. For nested arrays: validate structure AND leaf values.\n4. Extract custom rule objects for complex\u002Freusable logic.\n\n### Step 3: Test\n\n- Test required fields, invalid formats, boundary conditions, conditional rules.\n- Test authorization where relevant.\n- Use focused tests per validation concern.\n\n## Conventions\n\n→ See guideline `php\u002Fvalidations.md` for array syntax, route params, property mapping, custom rules.\n\n## Output format\n\n1. FormRequest class with rules, messages, and authorization\n2. Custom Rule object if validation logic is complex\n\n## Gotcha\n\n- `required` ≠ not `nullable` — `required` means present, `nullable` means value can be null.\n- Custom Rule objects must return `$fail` callback, not throw exceptions.\n- Don't validate data you already trust (e.g., from a verified internal service).\n\n## Do NOT\n\n- Do NOT validate in controllers — use FormRequest classes.\n- Do NOT use `$request->all()` — use `$request->validated()`.\n- Do NOT put business logic in validation classes.\n\n## Verification\n\nConfirm new rules with a concrete probe: a Pest feature test that POSTs with `curl`-shaped payloads through the browser\u002FHTTP client, or a `phpunit`\u002F`pest` run against the FormRequest. Add at least one negative case per rule (missing, wrong type, boundary). Never claim rules work without running them.\n\n## Anti-bruteforce — diagnose before retry\n\nWhen a rule fires unexpectedly, do not blindly toggle `required` \u002F `nullable` \u002F `sometimes` until tests pass. Print `$request->all()` once, compare against the rule set, identify the root cause, then make a targeted fix.\n\n## Clarification guard — ambiguous field → ask\n\nIf a field's intent is unclear (is `tags` a CSV string, an array, or JSON? is `email` required at create or only at update?), ask the user or check the existing schema \u002F API contract before guessing. Hidden assumptions in validation rules surface as production 422s.\n\n## Auto-trigger keywords\n\n- validation\n- Form Request\n- validation rules\n- custom rule\n","# laravel-validation\n\n## When to use\n\nUse when creating FormRequests, validation rules, or custom rule objects.\n\nDo NOT use when:\n- Authorization logic only (use `security` skill)\n- API response format (use `api-design` skill)\n\n## Procedure: Create a FormRequest\n\n### Step 0: Inspect\n\n1. Check existing FormRequests — match style, naming, authorization, rule structure.\n2. Check existing custom rules — reuse before creating new ones.\n3. Check API error response format — match it.\n\n### Step 1: Create the class\n\n1. Name: `{Action}{Entity}Request` — e.g. `CreateProjectRequest`.\n2. Implement `authorize()` using Policies.\n3. Implement `rules()` with array syntax — never pipe-separated.\n4. Use `prepareForValidation()` only when normalization is truly necessary.\n\n### Step 2: Rules\n\n1. Use Laravel's `Illuminate\\Validation\\Rules` classes where possible.\n2. Keep rules explicit — prefer clarity over cleverness.\n3. For nested arrays: validate structure AND leaf values.\n4. Extract custom rule objects for complex\u002Freusable logic.\n\n### Step 3: Test\n\n- Test required fields, invalid formats, boundary conditions, conditional rules.\n- Test authorization where relevant.\n- Use focused tests per validation concern.\n\n## Conventions\n\n→ See guideline `php\u002Fvalidations.md` for array syntax, route params, property mapping, custom rules.\n\n## Output format\n\n1. FormRequest class with rules, messages, and authorization\n2. Custom Rule object if validation logic is complex\n\n## Gotcha\n\n- `required` ≠ not `nullable` — `required` means present, `nullable` means value can be null.\n- Custom Rule objects must return `$fail` callback, not throw exceptions.\n- Don't validate data you already trust (e.g., from a verified internal service).\n\n## Do NOT\n\n- Do NOT validate in controllers — use FormRequest classes.\n- Do NOT use `$request->all()` — use `$request->validated()`.\n- Do NOT put business logic in validation classes.\n\n## Verification\n\nConfirm new rules with a concrete probe: a Pest feature test that POSTs with `curl`-shaped payloads through the browser\u002FHTTP client, or a `phpunit`\u002F`pest` run against the FormRequest. Add at least one negative case per rule (missing, wrong type, boundary). Never claim rules work without running them.\n\n## Anti-bruteforce — diagnose before retry\n\nWhen a rule fires unexpectedly, do not blindly toggle `required` \u002F `nullable` \u002F `sometimes` until tests pass. Print `$request->all()` once, compare against the rule set, identify the root cause, then make a targeted fix.\n\n## Clarification guard — ambiguous field → ask\n\nIf a field's intent is unclear (is `tags` a CSV string, an array, or JSON? is `email` required at create or only at update?), ask the user or check the existing schema \u002F API contract before guessing. Hidden assumptions in validation rules surface as production 422s.\n\n## Auto-trigger keywords\n\n- validation\n- Form Request\n- validation rules\n- custom rule\n",{"name":5,"packs":44,"trust":45,"domain":46,"install":47,"model_tier":49,"workspaces":50,"description":7},[20],{"level":30},"engineering",{"default":40,"removable":48},true,"medium",[46],"main","12bd765ce1d800501d45dfb8232102793af01290","src\u002Fskills\u002Flaravel-validation",1,"https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config","https:\u002F\u002Fevent4u.app","https:\u002F\u002Fgithub.com\u002Fevent4u-app","Your events in your hand","2026-11-14 02:29:41",{"source":8,"skillName":5,"commands":61,"prompt":71,"zipAvailable":48},[62,65,68],{"tool":63,"command":64},"npx","npx skills add event4u-app\u002Fagent-config --skill laravel-validation",{"tool":66,"command":67},"bunx","bunx skills add event4u-app\u002Fagent-config --skill laravel-validation",{"tool":69,"command":70},"pnpm","pnpm dlx skills add event4u-app\u002Fagent-config --skill laravel-validation","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Flaravel-validation\u002FSKILL.md",[],[74,92,105,117,129,139],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":85,"publishedAt":39},"01M6X84PK96XBPENXH66JCTSD1","unknown-key-fixture","Declares a key the schema does not know.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Fscripts\u002Ffixtures\u002Fbody-portable\u002Funknown-key\u002FSKILL.md",[80],{"categoryNo":81,"categoryName":82,"taxonomyType":83,"taxonomyTypeDesc":84},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[86,87,88,89,90,91],"unknown key fixture","Unknown key","fixture","unknown","schema","package",{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":99,"publishedAt":39},"01M6X84HW7NAHZ7GZMQ9RXK1XJ","portable-fixture","Declares only semantics the MCP-lite carrier transports whole.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Fscripts\u002Ffixtures\u002Fbody-portable\u002Fportable\u002FSKILL.md",[98],{"categoryNo":81,"categoryName":82,"taxonomyType":83,"taxonomyTypeDesc":84},[88,100,101,102,103,91,104],"portable","portable fixture","engineer","only","MCP",{"skillNo":106,"name":107,"nameZh":6,"description":108,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":109,"categories":110,"keywords":112,"publishedAt":39},"01M6X84F29FE0RGGZ1ZTFGZTX2","non-portable-fixture","Declares a runtime semantic the carrier drops.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Fscripts\u002Ffixtures\u002Fbody-portable\u002Fnon-portable\u002FSKILL.md",[111],{"categoryNo":81,"categoryName":82,"taxonomyType":83,"taxonomyTypeDesc":84},[101,113,100,88,114,115,116,91],"non portable fixture","semantic","high","runtime",{"skillNo":118,"name":119,"nameZh":6,"description":120,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":124,"publishedAt":39},"01M6X848F706PT9MDCX75JKJ6B","candidate-zero-width","A candidate whose prose carries an invisible joiner.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fskill-scout-candidates\u002Fzero-width-injection\u002FSKILL.md",[123],{"categoryNo":81,"categoryName":82,"taxonomyType":83,"taxonomyTypeDesc":84},[125,126,127,128],"candidate zero width","candidate","ZeRO","prose",{"skillNo":130,"name":131,"nameZh":6,"description":132,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":133,"categories":134,"keywords":136,"publishedAt":39},"01M6X841SSC2T31VDF41SA6DG1","candidate-disclosure-suppression","A candidate whose prose tells the agent to withhold from the user.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fskill-scout-candidates\u002Fdisclosure-suppression\u002FSKILL.md",[135],{"categoryNo":81,"categoryName":82,"taxonomyType":83,"taxonomyTypeDesc":84},[137,126,128,138],"candidate disclosure suppression","user",{"skillNo":140,"name":141,"nameZh":6,"description":142,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":143,"categories":144,"keywords":146,"publishedAt":39},"01M6X83TFS5AGPBPVTQNWP0BB3","candidate-dangerous-frontmatter","A candidate claiming an unscoped tool grant and a permission bypass.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fskill-scout-candidates\u002Fdangerous-frontmatter\u002FSKILL.md",[145],{"categoryNo":81,"categoryName":82,"taxonomyType":83,"taxonomyTypeDesc":84},[147,126,148,149,150,151],"candidate dangerous frontmatter","frontmatter","shell","permission","tool"]