[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6X7QPPPPMB702FWSZ3TJV2G":3,"skill-same:01M6X7QPPPPMB702FWSZ3TJV2G":79},{"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},"01M6X7QPPPPMB702FWSZ3TJV2G","schema-review",null,"Use when reviewing a migration diff or schema change for scale hazards — indexes, unsafe migrations, unbounded growth, N+1. Triggers on 'review this migration', 'will this scale'.","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\u002Fschema-review\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"schema review","schema","review","migrations","when","unsafe","for","true","scale","professional","false","triggers","indexes","migration","diff","discipline","use","growth","engineering","change","2026-11-10 10:12:30",false,"---\nmodel_tier: medium\nname: schema-review\ndescription: \"Use when reviewing a migration diff or schema change for scale hazards — indexes, unsafe migrations, unbounded growth, N+1. Triggers on 'review this migration', 'will this scale'.\"\ndomain: engineering\nworkspaces:\n  - engineering\npacks:\n  - scale-discipline\ntrust:\n  level: professional\ninstall:\n  default: false\n  removable: true\n---\n\n# schema-review\n\n## When to use\n\n- A migration diff, new migration file, or schema change is under review\n  and the question is scale-shaped: indexes, reversibility, growth,\n  query patterns against the new columns.\n- The user asks \"will this scale\", \"review this migration\", \"check the\n  schema\", or a PR touches `migrations\u002F`, `schema.prisma`, or raw `.sql`\n  migration files.\n- NOT for runtime performance analysis of live traffic (no APM here —\n  route to `performance-analysis`) and NOT for authoring a new migration\n  from scratch (route to `laravel-migration` or the stack-native tool,\n  then come back with the diff), and NOT for designing the schema itself\n  (route to `database`, which owns relational modeling).\n\n## Procedure\n\n1. **Detect the stack surface** in the diff: Laravel migrations\n   (`database\u002Fmigrations\u002F*.php`), Prisma (`schema.prisma` +\n   `prisma\u002Fmigrations\u002F**\u002Fmigration.sql`), raw SQL (`*.sql`). One diff can\n   carry several.\n2. **Run the deterministic linter** on the touched files plus the query\n   surface that references the changed tables:\n\n   ```bash\n   npx tsx node_modules\u002F@event4u\u002Fagent-config\u002Fsrc\u002Fscripts\u002Flint_persistence.ts --dir \u003Cpath> [--stack eloquent|prisma|raw-sql] --format json\n   ```\n\n   The linter emits `gate` findings (pattern-detected: F1 N+1, F2\n   index-parity, F3 unbounded reads, F6 migration-safety, F7\n   growth-budget, F8 audit-coverage, F9 sync-in-handler, F11 non-durable\n   async) and `advice` findings (heuristics — never treat as blockers).\n3. **Walk the gap table** — for every `gate` finding decide: fix, or\n   waiver with a reason (`\u002F\u002F no-index: \u003Creason>`, `\u002F\u002F sync-required:\n   \u003Creason>`, `-- no-retention: \u003Creason>`, …). An empty waiver reason is\n   itself a finding.\n4. **Check the R-A6\u002FR-A7 invariants by hand** where the linter is blind:\n   reversibility of data transformations, retention policy for any new\n   append-only table (the `-- retention: \u003Cpolicy>` line), backfill plan\n   for new NOT NULL columns on large tables.\n5. **A drop or rename → run the consumer census** before judging it safe:\n   app side via [`blast-radius-analyzer`](..\u002Fblast-radius-analyzer\u002FSKILL.md),\n   catalog side via [`consumer-census`](..\u002Fdatabase\u002Freferences\u002Fconsumer-census.md).\n6. **Report waiver density neutrally** — count waivers per rule; state\n   both readings (informed exceptions vs rule misfit) and let the human\n   decide. Density alone is never a verdict.\n\n## Output\n\nThe review MUST contain:\n\n1. **Gap table** — one row per finding: `rule · file:line · finding ·\n   proposed action (fix | waiver | accepted)`, gate findings first,\n   advice findings clearly marked as advice.\n2. **Waiver-density line** — `N waivers across M findings` with the\n   two-reading note (informed exceptions vs rule misfit).\n3. A one-line verdict: ready \u002F needs fixes \u002F needs human schema decision\n   — never a bare \"looks good\" without the table.\n\n## Gotcha\n\n- The linter proves **pattern presence**, not instance-level correctness\n  — a flagged `Http::` call in a controller may be legitimately sync\n  (then it gets a `\u002F\u002F sync-required:` waiver with a reason), and a clean\n  run does not prove the schema scales. Say what was checked, not more.\n- Prisma's `@relation` fields are indexed implicitly on some connectors\n  and not on others — when the linter reports a missing FK index on a\n  Prisma model, verify the connector before calling it a defect.\n\n## Do NOT\n\n- Do NOT gate a review on `advice`-tier findings (F4 denormalization,\n  F10 event-decoupling heuristics) — they are review inputs, not\n  blockers.\n- Do NOT strip or rewrite existing waivers — surface stale-looking ones\n  and ask.\n- Do NOT invent index recommendations for columns the query surface\n  never filters or orders by — index parity cuts both ways; unused\n  indexes cost write throughput.\n","# schema-review\n\n## When to use\n\n- A migration diff, new migration file, or schema change is under review\n  and the question is scale-shaped: indexes, reversibility, growth,\n  query patterns against the new columns.\n- The user asks \"will this scale\", \"review this migration\", \"check the\n  schema\", or a PR touches `migrations\u002F`, `schema.prisma`, or raw `.sql`\n  migration files.\n- NOT for runtime performance analysis of live traffic (no APM here —\n  route to `performance-analysis`) and NOT for authoring a new migration\n  from scratch (route to `laravel-migration` or the stack-native tool,\n  then come back with the diff), and NOT for designing the schema itself\n  (route to `database`, which owns relational modeling).\n\n## Procedure\n\n1. **Detect the stack surface** in the diff: Laravel migrations\n   (`database\u002Fmigrations\u002F*.php`), Prisma (`schema.prisma` +\n   `prisma\u002Fmigrations\u002F**\u002Fmigration.sql`), raw SQL (`*.sql`). One diff can\n   carry several.\n2. **Run the deterministic linter** on the touched files plus the query\n   surface that references the changed tables:\n\n   ```bash\n   npx tsx node_modules\u002F@event4u\u002Fagent-config\u002Fsrc\u002Fscripts\u002Flint_persistence.ts --dir \u003Cpath> [--stack eloquent|prisma|raw-sql] --format json\n   ```\n\n   The linter emits `gate` findings (pattern-detected: F1 N+1, F2\n   index-parity, F3 unbounded reads, F6 migration-safety, F7\n   growth-budget, F8 audit-coverage, F9 sync-in-handler, F11 non-durable\n   async) and `advice` findings (heuristics — never treat as blockers).\n3. **Walk the gap table** — for every `gate` finding decide: fix, or\n   waiver with a reason (`\u002F\u002F no-index: \u003Creason>`, `\u002F\u002F sync-required:\n   \u003Creason>`, `-- no-retention: \u003Creason>`, …). An empty waiver reason is\n   itself a finding.\n4. **Check the R-A6\u002FR-A7 invariants by hand** where the linter is blind:\n   reversibility of data transformations, retention policy for any new\n   append-only table (the `-- retention: \u003Cpolicy>` line), backfill plan\n   for new NOT NULL columns on large tables.\n5. **A drop or rename → run the consumer census** before judging it safe:\n   app side via [`blast-radius-analyzer`](..\u002Fblast-radius-analyzer\u002FSKILL.md),\n   catalog side via [`consumer-census`](..\u002Fdatabase\u002Freferences\u002Fconsumer-census.md).\n6. **Report waiver density neutrally** — count waivers per rule; state\n   both readings (informed exceptions vs rule misfit) and let the human\n   decide. Density alone is never a verdict.\n\n## Output\n\nThe review MUST contain:\n\n1. **Gap table** — one row per finding: `rule · file:line · finding ·\n   proposed action (fix | waiver | accepted)`, gate findings first,\n   advice findings clearly marked as advice.\n2. **Waiver-density line** — `N waivers across M findings` with the\n   two-reading note (informed exceptions vs rule misfit).\n3. A one-line verdict: ready \u002F needs fixes \u002F needs human schema decision\n   — never a bare \"looks good\" without the table.\n\n## Gotcha\n\n- The linter proves **pattern presence**, not instance-level correctness\n  — a flagged `Http::` call in a controller may be legitimately sync\n  (then it gets a `\u002F\u002F sync-required:` waiver with a reason), and a clean\n  run does not prove the schema scales. Say what was checked, not more.\n- Prisma's `@relation` fields are indexed implicitly on some connectors\n  and not on others — when the linter reports a missing FK index on a\n  Prisma model, verify the connector before calling it a defect.\n\n## Do NOT\n\n- Do NOT gate a review on `advice`-tier findings (F4 denormalization,\n  F10 event-decoupling heuristics) — they are review inputs, not\n  blockers.\n- Do NOT strip or rewrite existing waivers — surface stale-looking ones\n  and ask.\n- Do NOT invent index recommendations for columns the query surface\n  never filters or orders by — index parity cuts both ways; unused\n  indexes cost write throughput.\n",{"name":5,"packs":44,"trust":46,"domain":37,"install":47,"model_tier":49,"workspaces":50,"description":7},[45],"scale-discipline",{"level":28},{"default":40,"removable":48},true,"medium",[37],"main","12bd765ce1d800501d45dfb8232102793af01290","src\u002Fskills\u002Fschema-review",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 schema-review",{"tool":66,"command":67},"bunx","bunx skills add event4u-app\u002Fagent-config --skill schema-review",{"tool":69,"command":70},"pnpm","pnpm dlx skills add event4u-app\u002Fagent-config --skill schema-review","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Fschema-review\u002FSKILL.md",[73],{"path":74,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":77,"sourceHtmlUrl":78},"evals\u002Ftriggers.json","REFERENCE","参考文档",1318,"https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Fschema-review\u002Fevals\u002Ftriggers.json",[80,97,110,122,134,144],{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":91,"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",[86],{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[92,93,94,95,20,96],"unknown key fixture","Unknown key","fixture","unknown","package",{"skillNo":98,"name":99,"nameZh":6,"description":100,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":101,"categories":102,"keywords":104,"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",[103],{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},[94,105,106,107,108,96,109],"portable","portable fixture","engineer","only","MCP",{"skillNo":111,"name":112,"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":117,"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",[116],{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},[106,118,105,94,119,120,121,96],"non portable fixture","semantic","high","runtime",{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":129,"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",[128],{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},[130,131,132,133],"candidate zero width","candidate","ZeRO","prose",{"skillNo":135,"name":136,"nameZh":6,"description":137,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":138,"categories":139,"keywords":141,"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",[140],{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},[142,131,133,143],"candidate disclosure suppression","user",{"skillNo":145,"name":146,"nameZh":6,"description":147,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":148,"categories":149,"keywords":151,"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",[150],{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},[152,131,153,154,155,156],"candidate dangerous frontmatter","frontmatter","shell","permission","tool"]