@kensaurus/skills 0.0.0-stage → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) hide show
  1. package/.claude-plugin/marketplace.json +53 -0
  2. package/.claude-plugin/plugin.json +40 -0
  3. package/.cursor-plugin/plugin.json +38 -0
  4. package/.mcp.json +28 -0
  5. package/CHANGELOG.md +1790 -0
  6. package/LICENSE +21 -0
  7. package/LICENSE-APACHE +62 -0
  8. package/NOTICE +13 -0
  9. package/README.md +821 -2
  10. package/SECURITY.md +55 -0
  11. package/agents/code-reviewer.md +60 -0
  12. package/agents/completion-judge.md +89 -0
  13. package/agents/db-migrator.md +125 -0
  14. package/agents/debugger.md +47 -0
  15. package/agents/deploy-checker.md +100 -0
  16. package/agents/perf-monitor.md +74 -0
  17. package/assets/favicon.png +0 -0
  18. package/assets/logo-light.png +0 -0
  19. package/assets/logo.png +0 -0
  20. package/assets/logo.svg +6 -0
  21. package/assets/og.png +0 -0
  22. package/bin/install.mjs +1127 -0
  23. package/bin/kenji.js +2 -0
  24. package/commands/adr.md +17 -0
  25. package/commands/aeo-plan.md +18 -0
  26. package/commands/arch-boundaries.md +17 -0
  27. package/commands/aso-plan.md +18 -0
  28. package/commands/auth-flows.md +19 -0
  29. package/commands/backup-plan.md +17 -0
  30. package/commands/burndown-full.md +25 -0
  31. package/commands/capacitor-plan.md +18 -0
  32. package/commands/codemod-safety.md +22 -0
  33. package/commands/commit.md +18 -0
  34. package/commands/complete-everything.md +40 -0
  35. package/commands/cost-plan.md +19 -0
  36. package/commands/deadcode-plan.md +26 -0
  37. package/commands/deadcode.md +32 -0
  38. package/commands/debug-issue.md +17 -0
  39. package/commands/deps-plan.md +18 -0
  40. package/commands/docs-plan.md +17 -0
  41. package/commands/doctrine.md +19 -0
  42. package/commands/error-plan.md +19 -0
  43. package/commands/feedback-to-closure.md +36 -0
  44. package/commands/fix-issue.md +76 -0
  45. package/commands/gate-logic.md +26 -0
  46. package/commands/green-repo.md +36 -0
  47. package/commands/grill-me.md +19 -0
  48. package/commands/gtm-plan.md +21 -0
  49. package/commands/gtm-weekly.md +17 -0
  50. package/commands/gtm.md +22 -0
  51. package/commands/handoff.md +15 -0
  52. package/commands/housekeep-backlog.md +18 -0
  53. package/commands/housekeep-files.md +22 -0
  54. package/commands/housekeep-gates.md +18 -0
  55. package/commands/instant-nav.md +11 -0
  56. package/commands/integrity-plan.md +19 -0
  57. package/commands/launch-kit.md +16 -0
  58. package/commands/mcp-guide.md +40 -0
  59. package/commands/mobile-plan.md +19 -0
  60. package/commands/native-rn-monorepo/README.md +78 -0
  61. package/commands/native-rn-monorepo/android-build.md +26 -0
  62. package/commands/native-rn-monorepo/android-install.md +32 -0
  63. package/commands/native-rn-monorepo/android-logcat.md +37 -0
  64. package/commands/native-rn-monorepo/ios-ci-logs.md +56 -0
  65. package/commands/native-rn-monorepo/ios-ci-status.md +52 -0
  66. package/commands/native-rn-monorepo/ios-ci-trigger.md +59 -0
  67. package/commands/native-rn-monorepo/rn-reset.md +50 -0
  68. package/commands/native-rn-monorepo/rn-ship-ios.md +67 -0
  69. package/commands/native-rn-monorepo/rn-verify.md +53 -0
  70. package/commands/perf-plan.md +18 -0
  71. package/commands/plan-mode.md +74 -0
  72. package/commands/pr.md +16 -0
  73. package/commands/pricing-plan.md +20 -0
  74. package/commands/privacy-plan.md +18 -0
  75. package/commands/readability.md +12 -0
  76. package/commands/readme.md +15 -0
  77. package/commands/refactor.md +15 -0
  78. package/commands/release-prep.md +17 -0
  79. package/commands/research.md +25 -0
  80. package/commands/responsive-audit.md +21 -0
  81. package/commands/review-code.md +18 -0
  82. package/commands/rls-plan.md +18 -0
  83. package/commands/secrets-plan.md +18 -0
  84. package/commands/security-plan.md +19 -0
  85. package/commands/ship-and-observe.md +36 -0
  86. package/commands/skill-conflicts.md +19 -0
  87. package/commands/slop-plan.md +18 -0
  88. package/commands/stub-plan.md +18 -0
  89. package/commands/test-mutation.md +16 -0
  90. package/commands/test-plan.md +17 -0
  91. package/commands/test.md +29 -0
  92. package/commands/thirdparty-web-interface-guidelines.md +185 -0
  93. package/commands/uiux-plan.md +18 -0
  94. package/commands/uiux.md +45 -0
  95. package/commands/update-deps.md +21 -0
  96. package/commands/validation-plan.md +19 -0
  97. package/commands-portable/fix-issue.md +72 -0
  98. package/commands-portable/plan-mode.md +92 -0
  99. package/commands-portable/research.md +91 -0
  100. package/docs/screenshots/README.md +5 -0
  101. package/docs/screenshots/audit-dark.png +0 -0
  102. package/docs/screenshots/build-dark.png +0 -0
  103. package/docs/screenshots/grill-dark.png +0 -0
  104. package/docs/screenshots/hero-dark.png +0 -0
  105. package/docs/screenshots/hero-light.png +0 -0
  106. package/docs/screenshots/ship-dark.png +0 -0
  107. package/docs/screenshots/src/showcase.html +320 -0
  108. package/hooks/completion-gate.mjs +258 -0
  109. package/hooks/cursor-hooks.json +13 -0
  110. package/hooks/hooks.json +15 -0
  111. package/install.sh +21 -0
  112. package/llms.txt +40 -0
  113. package/mcp/README.md +266 -0
  114. package/mcp/VERSIONS.md +41 -0
  115. package/mcp/mcp-full.json.template +124 -0
  116. package/mcp/mcp.json.template +29 -0
  117. package/mcp/pinned-versions.json +27 -0
  118. package/package.json +94 -4
  119. package/rules/approved-plan-execution.mdc +65 -0
  120. package/rules/full-stack-ship-discipline.mdc +37 -0
  121. package/rules/native-rn-monorepo/README.md +63 -0
  122. package/rules/native-rn-monorepo/_project.mdc +69 -0
  123. package/rules/native-rn-monorepo/native-android.mdc +72 -0
  124. package/rules/native-rn-monorepo/native-ios.mdc +61 -0
  125. package/rules/native-rn-monorepo/react-native-js.mdc +78 -0
  126. package/rules/native-rn-monorepo/web.mdc +60 -0
  127. package/rules/project-starter/components.mdc +54 -0
  128. package/rules/project-starter/data-fetching.mdc +77 -0
  129. package/rules/project-starter/git.mdc +41 -0
  130. package/rules/project-starter/supabase.mdc +37 -0
  131. package/rules/project-starter/tailwind.mdc +48 -0
  132. package/rules/project-starter/typescript.mdc +36 -0
  133. package/rules/project-starter/web-performance.mdc +42 -0
  134. package/rules/senior-engineer.mdc +30 -0
  135. package/rules/shell-first-search.mdc +19 -0
  136. package/rules/skill-workflows.mdc +35 -0
  137. package/rules/verification-before-completion.mdc +57 -0
  138. package/skills/audit-accessibility/SKILL.md +441 -0
  139. package/skills/audit-agent-speed/SKILL.md +181 -0
  140. package/skills/audit-agent-speed/scripts/stop-typecheck.mjs +151 -0
  141. package/skills/audit-analytics/SKILL.md +138 -0
  142. package/skills/audit-auth-flows/SKILL.md +267 -0
  143. package/skills/audit-backend-architecture/SKILL.md +266 -0
  144. package/skills/audit-backend-architecture/references/patterns.md +386 -0
  145. package/skills/audit-bundle-size/SKILL.md +295 -0
  146. package/skills/audit-cicd/SKILL.md +218 -0
  147. package/skills/audit-code-quality/SKILL.md +314 -0
  148. package/skills/audit-code-review/SKILL.md +289 -0
  149. package/skills/audit-codemod-safety/SKILL.md +159 -0
  150. package/skills/audit-db-schema/SKILL.md +465 -0
  151. package/skills/audit-db-schema/references/details.md +110 -0
  152. package/skills/audit-doctrine/SKILL.md +189 -0
  153. package/skills/audit-env-parity/SKILL.md +133 -0
  154. package/skills/audit-fe-api/SKILL.md +458 -0
  155. package/skills/audit-gate-logic/SKILL.md +219 -0
  156. package/skills/audit-i18n/SKILL.md +339 -0
  157. package/skills/audit-infra-cost/SKILL.md +142 -0
  158. package/skills/audit-langfuse-llm/SKILL.md +468 -0
  159. package/skills/audit-langfuse-llm/references/details.md +226 -0
  160. package/skills/audit-llm-security/SKILL.md +147 -0
  161. package/skills/audit-monetization-iap/SKILL.md +137 -0
  162. package/skills/audit-payment-system/SKILL.md +268 -0
  163. package/skills/audit-payment-system/references/checklist.md +283 -0
  164. package/skills/audit-performance/SKILL.md +383 -0
  165. package/skills/audit-performance/references/loading-priority-2026.md +81 -0
  166. package/skills/audit-realworld/SKILL.md +287 -0
  167. package/skills/audit-registry-listing/SKILL.md +122 -0
  168. package/skills/audit-resilience/SKILL.md +153 -0
  169. package/skills/audit-responsive/SKILL.md +221 -0
  170. package/skills/audit-responsive/references/checklist.md +166 -0
  171. package/skills/audit-security/SKILL.md +289 -0
  172. package/skills/audit-skill-conflicts/SKILL.md +178 -0
  173. package/skills/audit-ui-states/SKILL.md +146 -0
  174. package/skills/audit-uiux-design-system/SKILL.md +475 -0
  175. package/skills/audit-uiux-design-system/references/details.md +71 -0
  176. package/skills/audit-ux/SKILL.md +381 -0
  177. package/skills/audit-ux/references/details.md +245 -0
  178. package/skills/audit-ux-journeys/SKILL.md +215 -0
  179. package/skills/audit-ux-journeys/references/checklist.md +179 -0
  180. package/skills/backend-db-performance/SKILL.md +441 -0
  181. package/skills/backend-error-handling/SKILL.md +489 -0
  182. package/skills/backend-error-handling/references/details.md +58 -0
  183. package/skills/backend-observability/SKILL.md +88 -0
  184. package/skills/backend-patterns/SKILL.md +499 -0
  185. package/skills/backend-patterns/references/architecture-patterns.md +298 -0
  186. package/skills/backend-realtime/SKILL.md +403 -0
  187. package/skills/backend-realtime/references/patterns.md +74 -0
  188. package/skills/burndown-full/SKILL.md +174 -0
  189. package/skills/complete-everything/SKILL.md +295 -0
  190. package/skills/data-pipeline/SKILL.md +109 -0
  191. package/skills/data-visualization/SKILL.md +488 -0
  192. package/skills/debug-error/SKILL.md +322 -0
  193. package/skills/debug-fe-be-integration/SKILL.md +459 -0
  194. package/skills/debug-sentry-monitor/SKILL.md +497 -0
  195. package/skills/debug-sentry-monitor/references/details.md +165 -0
  196. package/skills/deploy-npm/SKILL.md +394 -0
  197. package/skills/deploy-npm/references/example-mushi-mushi.md +52 -0
  198. package/skills/deploy-verify/SKILL.md +489 -0
  199. package/skills/design-api/SKILL.md +379 -0
  200. package/skills/design-canvas/SKILL.md +155 -0
  201. package/skills/design-email/SKILL.md +370 -0
  202. package/skills/design-frontend/SKILL.md +143 -0
  203. package/skills/design-generative-art/SKILL.md +474 -0
  204. package/skills/design-mobile-first/SKILL.md +506 -0
  205. package/skills/design-motion/SKILL.md +333 -0
  206. package/skills/design-motion/references/delight-interactions.md +191 -0
  207. package/skills/design-prd/SKILL.md +443 -0
  208. package/skills/design-system/SKILL.md +457 -0
  209. package/skills/design-theme/SKILL.md +226 -0
  210. package/skills/design-theme/themes/tsumagoi-ranch.md +150 -0
  211. package/skills/docs-adr/SKILL.md +168 -0
  212. package/skills/docs-coauthor/SKILL.md +368 -0
  213. package/skills/docs-comparison-pages/SKILL.md +117 -0
  214. package/skills/docs-domain-modeling/SKILL.md +97 -0
  215. package/skills/docs-launch-kit/SKILL.md +139 -0
  216. package/skills/docs-writer/SKILL.md +469 -0
  217. package/skills/enhance-agent-guardrails/SKILL.md +164 -0
  218. package/skills/enhance-arch-boundaries/SKILL.md +154 -0
  219. package/skills/enhance-capacitor-ui/SKILL.md +463 -0
  220. package/skills/enhance-capacitor-ui/references/details.md +750 -0
  221. package/skills/enhance-email-deliverability/SKILL.md +143 -0
  222. package/skills/enhance-growth-loops/SKILL.md +122 -0
  223. package/skills/enhance-lifecycle-email/SKILL.md +130 -0
  224. package/skills/enhance-motion/SKILL.md +193 -0
  225. package/skills/enhance-onboarding/SKILL.md +148 -0
  226. package/skills/enhance-pwa/SKILL.md +303 -0
  227. package/skills/enhance-readability/SKILL.md +146 -0
  228. package/skills/enhance-readme/SKILL.md +496 -0
  229. package/skills/enhance-readme/package-lock.json +187 -0
  230. package/skills/enhance-readme/package.json +17 -0
  231. package/skills/enhance-readme/scripts/generate-readme-blocks.mjs +199 -0
  232. package/skills/enhance-readme/scripts/record-readme-tour.mjs +442 -0
  233. package/skills/enhance-skill-prompts/SKILL.md +167 -0
  234. package/skills/enhance-skill-prompts/references/exemplar-audit-auth-flows.md +311 -0
  235. package/skills/enhance-ux-laws/SKILL.md +409 -0
  236. package/skills/enhance-web-conversion/SKILL.md +155 -0
  237. package/skills/enhance-web-forms/SKILL.md +154 -0
  238. package/skills/enhance-web-instant-nav/SKILL.md +138 -0
  239. package/skills/enhance-web-instant-nav/references/bfcache-blockers.md +23 -0
  240. package/skills/enhance-web-instant-nav/references/early-hints.md +33 -0
  241. package/skills/enhance-web-instant-nav/references/speculation-rules.md +44 -0
  242. package/skills/enhance-web-landing/SKILL.md +459 -0
  243. package/skills/enhance-web-landing/references/details.md +773 -0
  244. package/skills/enhance-web-redesign/SKILL.md +228 -0
  245. package/skills/enhance-web-seo/SKILL.md +276 -0
  246. package/skills/enhance-web-ui/SKILL.md +473 -0
  247. package/skills/enhance-web-ui/references/details.md +674 -0
  248. package/skills/enhance-web-ux/HEURISTICS.md +248 -0
  249. package/skills/enhance-web-ux/PATTERNS.md +375 -0
  250. package/skills/enhance-web-ux/SKILL.md +464 -0
  251. package/skills/enhance-web-ux/examples.md +222 -0
  252. package/skills/enhance-web-ux/references/details.md +406 -0
  253. package/skills/enhance-web-web3d/SKILL.md +397 -0
  254. package/skills/enhance-web-web3d/references/css-canvas-effects.md +180 -0
  255. package/skills/handoff/SKILL.md +66 -0
  256. package/skills/housekeep-backlog/SKILL.md +149 -0
  257. package/skills/housekeep-dead-code/SKILL.md +387 -0
  258. package/skills/housekeep-dead-code/references/ratchet-ci.md +205 -0
  259. package/skills/housekeep-dead-code/references/supabase-hygiene.md +152 -0
  260. package/skills/housekeep-design/SKILL.md +207 -0
  261. package/skills/housekeep-files/SKILL.md +220 -0
  262. package/skills/housekeep-files/references/naming-and-catalog.md +86 -0
  263. package/skills/housekeep-files/scripts/housekeep-files.ps1 +360 -0
  264. package/skills/housekeep-files/scripts/housekeep-files.sh +238 -0
  265. package/skills/housekeep-gates/SKILL.md +174 -0
  266. package/skills/iterate-agent-harness/SKILL.md +137 -0
  267. package/skills/iterate-gtm-weekly/SKILL.md +103 -0
  268. package/skills/iterate-post-launch/SKILL.md +292 -0
  269. package/skills/meta-mcp-builder/SKILL.md +313 -0
  270. package/skills/meta-skill-creator/SKILL.md +304 -0
  271. package/skills/mobile-capacitor-platform/SKILL.md +103 -0
  272. package/skills/mobile-emulator-start/SKILL.md +296 -0
  273. package/skills/mobile-emulator-test/SKILL.md +491 -0
  274. package/skills/mobile-emulator-test/references/details.md +478 -0
  275. package/skills/mobile-rn-performance/SKILL.md +107 -0
  276. package/skills/mobile-rn-screen/SKILL.md +476 -0
  277. package/skills/mobile-rn-screen/references/details.md +785 -0
  278. package/skills/mushi-health/SKILL.md +206 -0
  279. package/skills/mushi-integration/SKILL.md +257 -0
  280. package/skills/plan-aeo-readiness/SKILL.md +166 -0
  281. package/skills/plan-antislop/SKILL.md +281 -0
  282. package/skills/plan-aso/SKILL.md +149 -0
  283. package/skills/plan-backup-dr/SKILL.md +131 -0
  284. package/skills/plan-capacitor-hardening/SKILL.md +217 -0
  285. package/skills/plan-data-integrity/SKILL.md +187 -0
  286. package/skills/plan-dead-code/SKILL.md +386 -0
  287. package/skills/plan-dead-code/references/knip-config.md +214 -0
  288. package/skills/plan-dead-code/references/output-templates.md +133 -0
  289. package/skills/plan-dead-code/references/preservation-contract.md +50 -0
  290. package/skills/plan-dead-code/references/residue-greps.md +84 -0
  291. package/skills/plan-dependency-provenance/SKILL.md +200 -0
  292. package/skills/plan-docs-sync/SKILL.md +143 -0
  293. package/skills/plan-docs-sync/references/drift-taxonomy.md +43 -0
  294. package/skills/plan-docs-sync/references/output-templates.md +33 -0
  295. package/skills/plan-docs-sync/references/preservation-contract.md +17 -0
  296. package/skills/plan-error-handling/SKILL.md +205 -0
  297. package/skills/plan-gtm/SKILL.md +276 -0
  298. package/skills/plan-gtm/references/benchmarks-2026.md +183 -0
  299. package/skills/plan-input-validation/SKILL.md +179 -0
  300. package/skills/plan-llm-cost-guardrails/SKILL.md +176 -0
  301. package/skills/plan-mobile-readiness/SKILL.md +171 -0
  302. package/skills/plan-perf-audit/SKILL.md +145 -0
  303. package/skills/plan-perf-audit/references/audit-scope.md +51 -0
  304. package/skills/plan-perf-audit/references/output-templates.md +33 -0
  305. package/skills/plan-perf-audit/references/preservation-contract.md +13 -0
  306. package/skills/plan-pricing/SKILL.md +173 -0
  307. package/skills/plan-privacy-compliance/SKILL.md +148 -0
  308. package/skills/plan-rls-audit/SKILL.md +231 -0
  309. package/skills/plan-secrets-audit/SKILL.md +181 -0
  310. package/skills/plan-security-audit/SKILL.md +168 -0
  311. package/skills/plan-security-audit/references/output-templates.md +36 -0
  312. package/skills/plan-security-audit/references/owasp-supabase-scope.md +55 -0
  313. package/skills/plan-security-audit/references/preservation-contract.md +18 -0
  314. package/skills/plan-stub-checker/SKILL.md +216 -0
  315. package/skills/plan-stub-checker/references/detection-methodology.md +75 -0
  316. package/skills/plan-stub-checker/references/detection-taxonomy.md +34 -0
  317. package/skills/plan-stub-checker/references/output-templates.md +63 -0
  318. package/skills/plan-stub-checker/references/preservation-contract.md +24 -0
  319. package/skills/plan-test-coverage/SKILL.md +170 -0
  320. package/skills/plan-test-coverage/references/methodology.md +54 -0
  321. package/skills/plan-test-coverage/references/output-templates.md +34 -0
  322. package/skills/plan-test-coverage/references/preservation-contract.md +15 -0
  323. package/skills/plan-uiux-unification/SKILL.md +230 -0
  324. package/skills/plan-uiux-unification/references/output-templates.md +67 -0
  325. package/skills/plan-uiux-unification/references/phase-workbook.md +85 -0
  326. package/skills/plan-uiux-unification/references/preservation-contract.md +24 -0
  327. package/skills/protocol-browser-anti-stall/SKILL.md +211 -0
  328. package/skills/protocol-browser-anti-stall/references/mcp-to-cli-map.md +113 -0
  329. package/skills/protocol-browser-anti-stall/references/playwright-session-coordination.md +170 -0
  330. package/skills/research/SKILL.md +422 -0
  331. package/skills/test-exploratory/SKILL.md +165 -0
  332. package/skills/test-exploratory/references/charter-template.md +29 -0
  333. package/skills/test-load/SKILL.md +126 -0
  334. package/skills/test-mutation/SKILL.md +160 -0
  335. package/skills/test-playwright/SKILL.md +354 -0
  336. package/skills/test-qa/SKILL.md +364 -0
  337. package/skills/test-qa/references/details.md +268 -0
  338. package/skills/test-red-team/SKILL.md +386 -0
  339. package/skills/test-red-team/references/owasp-attack-checklist.md +193 -0
  340. package/skills/test-unit/SKILL.md +259 -0
  341. package/skills/test-unit/references/details.md +267 -0
  342. package/skills/test-visual-regression/SKILL.md +132 -0
  343. package/skills/thirdparty-emil-design-eng/ATTRIBUTION.md +20 -0
  344. package/skills/thirdparty-emil-design-eng/SKILL.md +21 -0
  345. package/skills/thirdparty-emil-design-eng/references/emil-design-eng.md +676 -0
  346. package/skills/thirdparty-ui-ux-pro-max/ATTRIBUTION.md +22 -0
  347. package/skills/thirdparty-ui-ux-pro-max/SKILL.md +304 -0
  348. package/skills/thirdparty-ui-ux-pro-max/data/charts.csv +26 -0
  349. package/skills/thirdparty-ui-ux-pro-max/data/colors.csv +97 -0
  350. package/skills/thirdparty-ui-ux-pro-max/data/icons.csv +101 -0
  351. package/skills/thirdparty-ui-ux-pro-max/data/landing.csv +31 -0
  352. package/skills/thirdparty-ui-ux-pro-max/data/products.csv +97 -0
  353. package/skills/thirdparty-ui-ux-pro-max/data/react-performance.csv +45 -0
  354. package/skills/thirdparty-ui-ux-pro-max/data/stacks/astro.csv +54 -0
  355. package/skills/thirdparty-ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  356. package/skills/thirdparty-ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  357. package/skills/thirdparty-ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  358. package/skills/thirdparty-ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  359. package/skills/thirdparty-ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  360. package/skills/thirdparty-ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  361. package/skills/thirdparty-ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  362. package/skills/thirdparty-ui-ux-pro-max/data/stacks/react.csv +54 -0
  363. package/skills/thirdparty-ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  364. package/skills/thirdparty-ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  365. package/skills/thirdparty-ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  366. package/skills/thirdparty-ui-ux-pro-max/data/stacks/vue.csv +50 -0
  367. package/skills/thirdparty-ui-ux-pro-max/data/styles.csv +68 -0
  368. package/skills/thirdparty-ui-ux-pro-max/data/typography.csv +58 -0
  369. package/skills/thirdparty-ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  370. package/skills/thirdparty-ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  371. package/skills/thirdparty-ui-ux-pro-max/data/web-interface.csv +31 -0
  372. package/skills/thirdparty-ui-ux-pro-max/scripts/core.py +253 -0
  373. package/skills/thirdparty-ui-ux-pro-max/scripts/design_system.py +1067 -0
  374. package/skills/thirdparty-ui-ux-pro-max/scripts/search.py +114 -0
  375. package/skills/thirdparty-web-interface-guidelines/ATTRIBUTION.md +23 -0
  376. package/skills/thirdparty-web-interface-guidelines/SKILL.md +190 -0
  377. package/skills/workflow-build-feature/SKILL.md +118 -0
  378. package/skills/workflow-coding-discipline/SKILL.md +140 -0
  379. package/skills/workflow-environment-ready/SKILL.md +128 -0
  380. package/skills/workflow-feature-flag/SKILL.md +262 -0
  381. package/skills/workflow-feedback-to-closure/SKILL.md +165 -0
  382. package/skills/workflow-fix-and-ship/SKILL.md +136 -0
  383. package/skills/workflow-git-commit/SKILL.md +200 -0
  384. package/skills/workflow-green-repo/SKILL.md +166 -0
  385. package/skills/workflow-grilling/SKILL.md +73 -0
  386. package/skills/workflow-gtm/SKILL.md +153 -0
  387. package/skills/workflow-housekeep/SKILL.md +453 -0
  388. package/skills/workflow-housekeep/references/templates.md +109 -0
  389. package/skills/workflow-launch-ready/SKILL.md +145 -0
  390. package/skills/workflow-merge-conflicts/SKILL.md +62 -0
  391. package/skills/workflow-onboard/SKILL.md +99 -0
  392. package/skills/workflow-parallel-agents/SKILL.md +164 -0
  393. package/skills/workflow-pr/SKILL.md +197 -0
  394. package/skills/workflow-quality-gate/SKILL.md +147 -0
  395. package/skills/workflow-refactor/SKILL.md +274 -0
  396. package/skills/workflow-release-prep/SKILL.md +207 -0
  397. package/skills/workflow-ship-and-observe/SKILL.md +164 -0
  398. package/skills/workflow-spec-tdd/SKILL.md +141 -0
  399. package/skills/workflow-spec-tdd/references/spec-template.md +126 -0
  400. package/skills/workflow-spec-tdd/references/tdd-patterns.md +167 -0
  401. package/skills-cursor/babysit/SKILL.md +17 -0
  402. package/skills-cursor/canvas/SKILL.md +142 -0
  403. package/skills-cursor/canvas/sdk/canvas-tokens.d.ts +235 -0
  404. package/skills-cursor/canvas/sdk/chart-primitives.d.ts +200 -0
  405. package/skills-cursor/canvas/sdk/dag-layout.d.ts +102 -0
  406. package/skills-cursor/canvas/sdk/diff-view.d.ts +130 -0
  407. package/skills-cursor/canvas/sdk/form-primitives.d.ts +194 -0
  408. package/skills-cursor/canvas/sdk/hooks.d.ts +117 -0
  409. package/skills-cursor/canvas/sdk/index.d.ts +47 -0
  410. package/skills-cursor/canvas/sdk/theme.d.ts +61 -0
  411. package/skills-cursor/canvas/sdk/todo-list.d.ts +49 -0
  412. package/skills-cursor/canvas/sdk/ui-primitives.d.ts +549 -0
  413. package/skills-cursor/canvas/sdk/ui-primitives.test.d.ts +2 -0
  414. package/skills-cursor/create-hook/SKILL.md +238 -0
  415. package/skills-cursor/create-rule/SKILL.md +185 -0
  416. package/skills-cursor/create-skill/SKILL.md +269 -0
  417. package/skills-cursor/create-skill/references/authoring-guide.md +182 -0
  418. package/skills-cursor/create-subagent/SKILL.md +228 -0
  419. package/skills-cursor/migrate-to-skills/SKILL.md +121 -0
  420. package/skills-cursor/shell/SKILL.md +22 -0
  421. package/skills-cursor/split-to-prs/SKILL.md +47 -0
  422. package/skills-cursor/statusline/SKILL.md +193 -0
  423. package/skills-cursor/update-cli-config/SKILL.md +85 -0
  424. package/skills-cursor/update-cursor-settings/SKILL.md +137 -0
  425. package/skills.sh.json +297 -0
@@ -0,0 +1,220 @@
1
+ ---
2
+ name: housekeep-files
3
+ description: >
4
+ Copy-not-move organizer for document trees: hash inventory, dry run,
5
+ labeled copies, search catalog, verify every source survived. Use when
6
+ "organize my Downloads", "sort my company folders", or "file my receipts".
7
+ Repo cleanup → workflow-housekeep.
8
+ license: MIT
9
+ ---
10
+
11
+ # housekeep-files — File the documents, keep every original
12
+
13
+ **Degree of freedom: MIXED.** Which owner, area, and doc type a file belongs
14
+ to, and which layout option fits the person `[HIGH freedom]`. The
15
+ copy-not-move rule, the hash inventory before the first copy, and the
16
+ verify gate `[LOW freedom — run exactly]`.
17
+
18
+ Apply-now for one drifted **file tree**: a Downloads pile, a cloud folder
19
+ named for one company that holds two, receipts spread across three places.
20
+ The output is an added, labeled copy of the documents plus a catalog an
21
+ agent can grep. The input tree is left complete. Retiring the duplicates
22
+ later is a separate, human-run decision.
23
+
24
+ ## This skill vs neighbors
25
+
26
+ | Skill | Owns |
27
+ |---|---|
28
+ | **housekeep-files** (this) | Personal / business document trees on disk or a synced drive |
29
+ | `workflow-housekeep` | A git repository: README, dead artifacts, dependencies |
30
+ | `housekeep-backlog` | Parked work register, not files |
31
+ | `plan-data-integrity` | Database destructive-op safety |
32
+ | `plan-secrets-audit` | Finding leaked keys; this skill only refuses to copy them |
33
+
34
+ ## How to reason (every file)
35
+
36
+ 1. **Owner** — which legal entity or person pays for or signs this? Two
37
+ companies are two sets of books, even when one person runs both; a CV
38
+ or an ID scan belongs to neither company.
39
+ 2. **Area** — company / finance / product / client / site / tax / identity.
40
+ 3. **Doc type and date** — invoice, receipt, contract, tax-return, payroll,
41
+ registration, lease, cv, brand, plan, correspondence, other. Date from
42
+ the filename first, then the parent folder, else `undated`.
43
+ 4. **Copy or index** — signing keys, credentials, media over the size cap,
44
+ installers: never copied, only cataloged where they already are.
45
+
46
+ An ambiguous file goes to `90_inbox` with its best-guess tags. Guessing an
47
+ owner wrong files company A's receipt under company B; `90_inbox` files it
48
+ nowhere wrong.
49
+
50
+ ## Worked example
51
+
52
+ > **Owner:** `Form 9 - Certificate.pdf` sits in a folder named for
53
+ > company B; the form is company B's incorporation paper → `acme-uk`.
54
+ > **Area / type:** company / registration; no date in the name → `undated`.
55
+ > **Copy or index:** PDF, 80 KB → copy.
56
+ > **Label:** `acme-uk_company_undated_registration__Form 9 - Certificate.pdf`
57
+ > — original name kept after `__` so the old string still matches search.
58
+ > **Catalog line:** entity, area, doc_type, tags `["acme","companies-house","incorporation"]`,
59
+ > `original_path`, `canonical_path`, `sha256`, `persist: copied-source-kept`.
60
+ > **Neighbor:** `AuthKey_XXXX.p8` in an app folder → `indexed-in-place`,
61
+ > reason `secret`; the catalog records its folder, not its bytes.
62
+
63
+ ---
64
+
65
+ ## Phase 0 — Inventory the tree, then pick the layout with the human
66
+
67
+ Read before moving anything: the top two levels of every source root,
68
+ which folders already exist at the destination, and which names repeat
69
+ in more than one place. Then offer the options below and let the person
70
+ choose; each is a different tree, so the plan cannot be written first.
71
+
72
+ ### Option A — Root per owner (default)
73
+
74
+ ```
75
+ <Drive>/<Owner-A>/ 00_company 10_finance 20_<site-or-venture> 30_products 40_clients 90_inbox
76
+ <Drive>/<Owner-B>/ 00_company 10_finance 90_inbox
77
+ <Drive>/_personal/ tax identity job-search family
78
+ ```
79
+
80
+ Best when owners are separate legal entities or the accountant for one
81
+ must never see the other. Two or three levels deep. Numbered areas keep a
82
+ fixed order without freezing IDs the way full Johnny.Decimal does.
83
+
84
+ ### Option B — One root, owners inside
85
+
86
+ ```
87
+ <Drive>/Documents/<Owner-A>/… <Drive>/Documents/<Owner-B>/… <Drive>/Documents/_personal/…
88
+ ```
89
+
90
+ Best when one root folder is already shared or synced and re-sharing is
91
+ costly. Same area folders inside each owner.
92
+
93
+ ### Option C — PARA-lite for a single owner
94
+
95
+ ```
96
+ <Drive>/10_projects 20_areas 30_resources 40_archive
97
+ ```
98
+
99
+ Best for one person with no company split. Active work moves between
100
+ projects and archive; areas hold the standing responsibilities.
101
+
102
+ ### Label and metadata options (combine with any layout)
103
+
104
+ | Option | When |
105
+ |---|---|
106
+ | Catalog only (`_ai-catalog.jsonl`, names untouched) | Names already carry date and subject, or apps read files by name |
107
+ | Catalog + prefix on vague names (`prefix=yes` rows) | Loose files like `Form 9.pdf`, `scan001.jpg`; original kept after `__` |
108
+ | Folder rename only | Whole folders like `#projectX` → `30_products/project-x`, internals untouched |
109
+
110
+ Why these and not cloud properties or hidden sidecars: cloud custom
111
+ properties are API fields, not files; hidden sidecar folders often do not
112
+ sync. A visible catalog plus an ASCII prefix is what a later agent on any
113
+ machine can grep. Sources and the exact schema:
114
+ [references/naming-and-catalog.md](references/naming-and-catalog.md).
115
+
116
+ ### Move instead of copy
117
+
118
+ Only when the human states that the source tree may lose paths and the
119
+ target is on the same volume. Even then run `inventory` first and `verify`
120
+ after. The bundled scripts do not move; a move is a manual step the
121
+ person performs after `verify` passes on the copies.
122
+
123
+ ## Phase 1 — Write `plan.tsv` [HIGH freedom]
124
+
125
+ One row per source folder or loose file. Tab-separated, header row:
126
+
127
+ ```
128
+ source destination entity area project doc_type tags prefix catalog_root
129
+ ```
130
+
131
+ - `source` — existing file or folder. A folder row copies its whole tree
132
+ under `destination`, internals unrenamed.
133
+ - `entity` — short ASCII token per owner (`acme-uk`, `acme-sg`, `personal`).
134
+ - `prefix` — `yes` only for loose files whose name says neither owner nor
135
+ date. Folder rows are `no`.
136
+ - `tags` — comma-separated, English plus the person's own language, words
137
+ they would actually type: `acme,invoice,請求書`.
138
+ - `catalog_root` — the owner root that gets a `_ai-catalog.jsonl`.
139
+ - `exclude` (optional 10th column) — `;`-separated relative-path substrings
140
+ inside a folder row to catalog in place instead of copying: a code
141
+ checkout beside its own zip, a cache. `node_modules`, `.git`,
142
+ `__pycache__`, `.venv`, `.next`, `.cache` are always skipped.
143
+
144
+ Keep dated expense month-folders and app folders exactly as named. Do not
145
+ plan rows for RAW, video, camera-card dumps, or installers; list those
146
+ folders in `count-only.txt` so the verify gate proves they were untouched.
147
+
148
+ ## Phase 2 — Inventory, dry run, apply, verify [LOW freedom — this order]
149
+
150
+ Windows (PowerShell 5.1+):
151
+
152
+ ```powershell
153
+ $S = "$HOME\.cursor\skills\housekeep-files\scripts\housekeep-files.ps1"
154
+ & $S -Mode inventory -Plan .\plan.tsv -Out .\work -CountOnly .\count-only.txt
155
+ & $S -Mode dry-run -Plan .\plan.tsv -Out .\work # read work\preview.tsv, fix the plan, rerun
156
+ & $S -Mode apply -Plan .\plan.tsv -Out .\work
157
+ & $S -Mode verify -Plan .\plan.tsv -Out .\work -CountOnly .\count-only.txt
158
+ ```
159
+
160
+ macOS / Linux (bash, `shasum` or `sha256sum`):
161
+
162
+ ```bash
163
+ S="$HOME/.cursor/skills/housekeep-files/scripts/housekeep-files.sh"
164
+ "$S" inventory plan.tsv work count-only.txt
165
+ "$S" dry-run plan.tsv work
166
+ "$S" apply plan.tsv work
167
+ "$S" verify plan.tsv work count-only.txt
168
+ ```
169
+
170
+ What the scripts enforce, identically on both platforms:
171
+
172
+ - `inventory` writes `work/inventory.csv` (path, bytes, sha256) for every
173
+ source file in the plan — hash for files that will be copied, size only
174
+ for in-place items so a streaming drive never downloads media — and
175
+ `work/count-only.csv` for the untouched folders. `apply` refuses to run
176
+ without it.
177
+ - `dry-run` writes `work/preview.tsv` with one of `copy`,
178
+ `indexed-in-place` (reason `secret`, `excluded`, `artifact`, `ext`,
179
+ `size`), or `skipped-exists` per file, plus the proposed name. Nothing on
180
+ disk changes. A folder row that expands to thousands of files is a code
181
+ checkout to `exclude`, not a document set.
182
+ - `apply` copies only when the destination path is absent, hashes the
183
+ copy, and marks a mismatch `failed` with the source untouched. It never
184
+ calls a delete. It appends `_ai-catalog.jsonl` at each `catalog_root`
185
+ and at `work/catalog.jsonl`, and drops a `_SEARCH.md` where none exists.
186
+ - `verify` re-checks every inventory path (exists, same size), re-hashes
187
+ every copy, recounts every count-only folder, and exits non-zero on the
188
+ first missing file. Its `work/verify-report.txt` is the evidence.
189
+
190
+ Leave a `README-MOVED.txt` in the old root naming the new roots and
191
+ stating that the old tree was not removed.
192
+
193
+ ## Self-critique before reporting
194
+
195
+ - **Inventory predates the first copy** — `inventory.csv` mtime is earlier
196
+ than the first `copied-source-kept` line.
197
+ - **Zero deletes** — the scripts were run unmodified; `apply-log.tsv` has
198
+ no `removed` action; every `count-only` folder count is unchanged.
199
+ - **Every source path in `inventory.csv` still exists** at its original
200
+ size — `verify` exit code 0, report listed.
201
+ - **No secret gained a second copy** — every `.p8 / .p12 / keystore /
202
+ credentials` row reads `indexed-in-place`.
203
+ - **Prefixed names keep the original after `__`**, and no new path exceeds
204
+ the length cap.
205
+ - **Storage growth stated** — total bytes copied, so the human can decide
206
+ when to retire the originals.
207
+ - **Nothing person-specific leaked into shared artifacts** — the catalog
208
+ holds paths and labels; the skill and its examples hold placeholders.
209
+
210
+ ## Output format
211
+
212
+ 1. **Layout chosen** — option letter, roots created, area folders
213
+ 2. **Counts** — copied | skipped-exists | indexed-in-place by reason | failed
214
+ 3. **Verify** — exit code, source paths checked, hashes matched,
215
+ count-only folders unchanged
216
+ 4. **Catalog** — where `_ai-catalog.jsonl` and `_SEARCH.md` landed, line count
217
+ 5. **Left for the human** — duplicates to retire later, `90_inbox` items
218
+
219
+ The turn may end after `verify` exits 0 and the report is written; a
220
+ non-zero verify is a finding to fix, never a reason to delete anything.
@@ -0,0 +1,86 @@
1
+ # Naming, catalog schema, and sources
2
+
3
+ ## Filename label
4
+
5
+ Applied only to a copied file whose row has `prefix=yes` and whose name
6
+ does not already start with a date (`20YYMMDD`, `20YY-MM`, `20YY_`) or an
7
+ entity token. The original name is kept after `__`.
8
+
9
+ ```
10
+ {entity}_{area}_{yyyy-mm-dd|yyyy-mm|undated}_{doc-type}__{original-file-name}
11
+ ```
12
+
13
+ | Slot | Values |
14
+ |---|---|
15
+ | entity | short ASCII per legal entity or person, e.g. `acme-uk`, `acme-sg`, `personal` |
16
+ | area | `company`, `finance`, `product`, `client`, `site`, `tax`, `identity`, `job`, `family`, `inbox` |
17
+ | doc-type | `invoice`, `receipt`, `tax-return`, `payroll`, `contract`, `insurance`, `registration`, `lease`, `cv`, `seal`, `brand`, `plan`, `correspondence`, `statement`, `other` |
18
+ | date | from the filename, else the parent folder name, else `undated` |
19
+
20
+ Skip the prefix when the new full path would exceed the length cap
21
+ (default 200 characters). Windows tools misbehave near 260; a synced drive
22
+ adds its own folder depth on the other machine.
23
+
24
+ Never rename inside an app or build folder: `google-services.json`,
25
+ `assetlinks.json`, provisioning profiles, keystores are read by name.
26
+
27
+ ## What is never copied (indexed in place)
28
+
29
+ | Reason | Rule |
30
+ |---|---|
31
+ | `secret` | path matches `credential`, `keystore`, `.p8`, `.p12`, `.pem`, `.key`, `.jks`, `mobileprovision`, `.cer`, `.der`, `certsigningrequest`, `.b64`, `service-account`, `client_secret`, `google-services.json`, `googleservice-info`, `oauth`, `private-key`, `backup_code`, `.env`, `play-publisher`, `apple-credentials`, `env-backups`, `recovery`, `2fa`, `mfa`, `totp`, `アクセスキー` |
32
+ | `excluded` | relative path contains a substring from the row's `exclude` column |
33
+ | `artifact` | path contains `node_modules`, `.git`, `__pycache__`, `.venv`, `.next`, or `.cache` |
34
+ | `ext` | extension outside the document allowlist: `pdf doc docx xls xlsx xlsm ppt pptx csv txt md html htm xtx xml data zip jpg jpeg png heic svg gif webp rtf odt ods eml msg` |
35
+ | `size` | larger than the cap (default 200 MB) |
36
+
37
+ A second copy of a signing key is a second thing to rotate. A video is a
38
+ Drive upload the human did not ask for. Both still get a catalog line so
39
+ search finds where they already live.
40
+
41
+ ## Catalog line (`_ai-catalog.jsonl`, one JSON object per line)
42
+
43
+ ```json
44
+ {"run":"2026-01-15T03:40:12Z","entity":"acme-uk","area":"company","project":"","doc_type":"registration",
45
+ "date":"undated","tags":["acme","companies-house","incorporation"],
46
+ "original_path":"D:\\Drive\\Old Mixed Folder\\Form 9 - Certificate.pdf",
47
+ "original_name":"Form 9 - Certificate.pdf",
48
+ "canonical_path":"D:\\Drive\\Acme_UK\\00_company\\acme-uk_company_undated_registration__Form 9 - Certificate.pdf",
49
+ "bytes":80123,"sha256":"…","persist":"copied-source-kept","reason":""}
50
+ ```
51
+
52
+ `persist` ∈ `copied-source-kept` | `indexed-in-place` | `skipped-exists` |
53
+ `failed`. The catalog stores paths and labels only; never file contents,
54
+ account numbers, or key material.
55
+
56
+ `_SEARCH.md` at each root tells a later agent: grep `_ai-catalog.jsonl`
57
+ first, then the prefixed filename, then the original name after `__`.
58
+
59
+ ## Verify report
60
+
61
+ `verify` fails on the first of: an inventory path missing or resized, a
62
+ copy whose SHA-256 differs from the inventory, an in-place row whose file
63
+ is gone, a count-only folder whose file count changed. The report lists
64
+ each check with its count and the first offending path.
65
+
66
+ ## Sources
67
+
68
+ - Multi-entity bookkeeping keeps one set of books per legal entity —
69
+ numetix.ai, "Multi-Entity Accounting for Service Firms".
70
+ - Drive structure two to three levels deep, date-first names, quarterly
71
+ archive rather than delete — drdaveheath.com, "Google Drive folder
72
+ structure best practices (2026 guide)".
73
+ - Johnny.Decimal caps each level at ten and freezes IDs — johnnydecimal.com
74
+ documentation; its forum's official stance is not to mix it with PARA.
75
+ - Drive custom properties are API metadata capped at 124 bytes per
76
+ property, not files — developers.google.com Drive API "Add custom file
77
+ properties".
78
+ - Tags embedded in filenames survive Dropbox and Google Drive sync; hidden
79
+ sidecar folders may not — docs.tagspaces.org "Organizing Files and
80
+ Folders with Tags".
81
+ - Do not use robocopy `/MOV` or `/MIR` when avoiding data loss; robocopy
82
+ does not verify the copy by hash — learn.microsoft.com "Use Robocopy to
83
+ Preseed Files for DFS Replication".
84
+ - Moving a folder inside My Drive keeps the file ID and share links;
85
+ inherited permissions change — Google Workspace Admin Help, "Moving
86
+ content from Drive shared folders".
@@ -0,0 +1,360 @@
1
+ <#
2
+ FILE: housekeep-files.ps1
3
+ PURPOSE: Copy-not-move document organizer with a hash inventory, dry run,
4
+ labeled copies, a JSONL catalog, and a verify gate. Windows twin of
5
+ housekeep-files.sh (same plan.tsv, same outputs).
6
+
7
+ OVERVIEW:
8
+ - inventory : sha256 + size of every source file in plan.tsv -> work\inventory.csv;
9
+ file counts of count-only folders -> work\count-only.csv
10
+ - dry-run : work\preview.tsv with the action per file; no disk change
11
+ - apply : Copy-Item only when the destination is absent, hash the copy,
12
+ append _ai-catalog.jsonl at each catalog_root and work\catalog.jsonl,
13
+ write apply-log.tsv. Never deletes.
14
+ - verify : every inventory path exists at the same size, every copy re-hashes
15
+ equal, every in-place file exists, count-only counts unchanged.
16
+ Exit 1 on the first failure. -> work\verify-report.txt
17
+
18
+ DEPENDENCIES: Windows PowerShell 5.1 or PowerShell 7. No modules.
19
+
20
+ USAGE:
21
+ .\housekeep-files.ps1 -Mode inventory -Plan plan.tsv -Out work -CountOnly count-only.txt
22
+ .\housekeep-files.ps1 -Mode dry-run -Plan plan.tsv -Out work
23
+ .\housekeep-files.ps1 -Mode apply -Plan plan.tsv -Out work
24
+ .\housekeep-files.ps1 -Mode verify -Plan plan.tsv -Out work -CountOnly count-only.txt
25
+
26
+ plan.tsv header (tab-separated; `exclude` is optional):
27
+ source destination entity area project doc_type tags prefix catalog_root exclude
28
+ exclude = ';'-separated relative-path substrings to catalog in place instead of copying
29
+ (code checkouts, caches). node_modules/.git/__pycache__/.venv/.next/.cache are always skipped.
30
+
31
+ NOTES:
32
+ - There is no Remove-Item, Move-Item, or robocopy in this file by design.
33
+ - -LiteralPath everywhere: folder names carry #, spaces, CJK, brackets.
34
+ - Keep this file ASCII. Windows PowerShell 5.1 decodes a BOM-less script with the
35
+ ANSI code page, so a literal CJK or em-dash character breaks parsing (cp1252) or
36
+ silently garbles a pattern (cp932). Write non-ASCII as a regex \uXXXX escape.
37
+ - Output files are UTF-8 without BOM so other tools and the bash twin read them.
38
+ #>
39
+ [CmdletBinding()]
40
+ param(
41
+ [Parameter(Mandatory = $true)][ValidateSet('inventory', 'dry-run', 'apply', 'verify')][string]$Mode,
42
+ [Parameter(Mandatory = $true)][string]$Plan,
43
+ [Parameter(Mandatory = $true)][string]$Out,
44
+ [string]$CountOnly = '',
45
+ [int]$MaxMB = 200,
46
+ [int]$MaxPath = 200
47
+ )
48
+
49
+ Set-StrictMode -Version 2
50
+ $ErrorActionPreference = 'Stop'
51
+ $Utf8NoBom = New-Object System.Text.UTF8Encoding($false)
52
+
53
+ $DocExt = @('.pdf', '.doc', '.docx', '.xls', '.xlsx', '.xlsm', '.ppt', '.pptx', '.csv', '.txt', '.md',
54
+ '.html', '.htm', '.xtx', '.xml', '.data', '.zip', '.jpg', '.jpeg', '.png', '.heic', '.svg', '.gif',
55
+ '.webp', '.rtf', '.odt', '.ods', '.eml', '.msg')
56
+ $SecretRe = 'credential|keystore|\.p8$|\.p12$|\.pem$|\.key$|\.jks$|mobileprovision|\.cer$|\.der$|certsigningrequest|\.b64$|service-account|client_secret|google-services\.json|googleservice-info|oauth|private-key|backup_code|\.env$|play-publisher|apple-credentials|env-backups|recovery|2fa|mfa|totp|\u30A2\u30AF\u30BB\u30B9\u30AD\u30FC'
57
+ $ArtifactRe = '\\(node_modules|\.git|__pycache__|\.venv|\.next|\.cache)\\'
58
+ $DatedNameRe = '^(20\d{6}|20\d{2}-\d{2}|20\d{2}_)'
59
+ $RunStamp = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
60
+
61
+ function Write-Utf8Lines([string]$Path, [string[]]$Lines) {
62
+ [System.IO.File]::WriteAllLines($Path, $Lines, $Utf8NoBom)
63
+ }
64
+ function Append-Utf8Lines([string]$Path, [string[]]$Lines) {
65
+ [System.IO.File]::AppendAllLines($Path, [string[]]$Lines, $Utf8NoBom)
66
+ }
67
+ function Get-Sha256([string]$LiteralPath) {
68
+ (Get-FileHash -LiteralPath $LiteralPath -Algorithm SHA256).Hash.ToLowerInvariant()
69
+ }
70
+ function Read-Tsv([string]$Path) {
71
+ $lines = [System.IO.File]::ReadAllLines($Path, [System.Text.Encoding]::UTF8) | Where-Object { $_.Trim() -ne '' }
72
+ $header = $lines[0].Split("`t")
73
+ $rows = @()
74
+ foreach ($line in $lines[1..($lines.Count - 1)]) {
75
+ if ($line.TrimStart().StartsWith('#')) { continue }
76
+ $cells = $line.Split("`t")
77
+ $row = @{}
78
+ for ($i = 0; $i -lt $header.Count; $i++) {
79
+ $val = ''
80
+ if ($i -lt $cells.Count) { $val = $cells[$i].Trim() }
81
+ $row[$header[$i].Trim()] = $val
82
+ }
83
+ $rows += , $row
84
+ }
85
+ return $rows
86
+ }
87
+ function Get-DateToken([string]$Name, [string]$ParentName) {
88
+ foreach ($candidate in @($Name, $ParentName)) {
89
+ if ([string]::IsNullOrEmpty($candidate)) { continue }
90
+ $m = [regex]::Match($candidate, '(20\d{2})[-_.]?(\d{2})[-_.]?(\d{2})(?!\d)')
91
+ if ($m.Success) {
92
+ $mo = [int]$m.Groups[2].Value; $d = [int]$m.Groups[3].Value
93
+ if ($mo -ge 1 -and $mo -le 12 -and $d -ge 1 -and $d -le 31) { return ('{0}-{1:00}-{2:00}' -f $m.Groups[1].Value, $mo, $d) }
94
+ }
95
+ $m = [regex]::Match($candidate, '(20\d{2})[-_]?(\d{2})(?!\d)')
96
+ if ($m.Success) {
97
+ $mo = [int]$m.Groups[2].Value
98
+ if ($mo -ge 1 -and $mo -le 12) { return ('{0}-{1:00}' -f $m.Groups[1].Value, $mo) }
99
+ }
100
+ }
101
+ return 'undated'
102
+ }
103
+ function Json-Escape([string]$s) {
104
+ if ($null -eq $s) { return '' }
105
+ return $s.Replace('\', '\\').Replace('"', '\"').Replace("`r", '\r').Replace("`n", '\n').Replace("`t", '\t')
106
+ }
107
+ function To-CatalogLine($item) {
108
+ $tags = @()
109
+ foreach ($t in ($item.tags -split ',')) { if ($t.Trim() -ne '') { $tags += ('"' + (Json-Escape $t.Trim()) + '"') } }
110
+ $fields = @(
111
+ ('"run":"' + $RunStamp + '"'),
112
+ ('"entity":"' + (Json-Escape $item.entity) + '"'),
113
+ ('"area":"' + (Json-Escape $item.area) + '"'),
114
+ ('"project":"' + (Json-Escape $item.project) + '"'),
115
+ ('"doc_type":"' + (Json-Escape $item.doc_type) + '"'),
116
+ ('"date":"' + $item.date + '"'),
117
+ ('"tags":[' + ($tags -join ',') + ']'),
118
+ ('"original_path":"' + (Json-Escape $item.source) + '"'),
119
+ ('"original_name":"' + (Json-Escape $item.name) + '"'),
120
+ ('"canonical_path":"' + (Json-Escape $item.canonical) + '"'),
121
+ ('"bytes":' + $item.bytes),
122
+ ('"sha256":"' + $item.sha256 + '"'),
123
+ ('"persist":"' + $item.persist + '"'),
124
+ ('"reason":"' + $item.reason + '"')
125
+ )
126
+ return '{' + ($fields -join ',') + '}'
127
+ }
128
+
129
+ # Expand plan rows into per-file items with a proposed action.
130
+ function Expand-Plan($rows) {
131
+ $items = @()
132
+ foreach ($row in $rows) {
133
+ $src = $row['source']
134
+ if (-not (Test-Path -LiteralPath $src)) { Write-Warning "plan source missing, skipped: $src"; continue }
135
+ $srcItem = Get-Item -LiteralPath $src
136
+ $files = @()
137
+ if ($srcItem.PSIsContainer) {
138
+ $files = Get-ChildItem -LiteralPath $src -Recurse -File -Force
139
+ } else {
140
+ $files = @($srcItem)
141
+ }
142
+ foreach ($f in $files) {
143
+ # OS / sync-client metadata files are recreated and removed by the client itself; never inventory them.
144
+ if ($f.Name -in @('desktop.ini', '.DS_Store', 'Thumbs.db')) { continue }
145
+ $rel = $f.Name
146
+ if ($srcItem.PSIsContainer) {
147
+ $rel = $f.FullName.Substring($srcItem.FullName.Length).TrimStart('\')
148
+ }
149
+ $destDir = $row['destination']
150
+ $relDir = [System.IO.Path]::GetDirectoryName($rel)
151
+ if ($relDir) { $destDir = Join-Path $destDir $relDir }
152
+ $lowerPath = $f.FullName.ToLowerInvariant()
153
+ $ext = $f.Extension.ToLowerInvariant()
154
+ $action = 'copy'; $reason = ''
155
+ $excluded = $false
156
+ foreach ($pat in (($row['exclude']) -split ';')) {
157
+ if ($pat.Trim() -ne '' -and $rel.ToLowerInvariant().Contains($pat.Trim().ToLowerInvariant())) { $excluded = $true; break }
158
+ }
159
+ if ($lowerPath -match $SecretRe) { $action = 'indexed-in-place'; $reason = 'secret' }
160
+ elseif ($excluded) { $action = 'indexed-in-place'; $reason = 'excluded' }
161
+ elseif ($lowerPath -match $ArtifactRe) { $action = 'indexed-in-place'; $reason = 'artifact' }
162
+ elseif ($DocExt -notcontains $ext) { $action = 'indexed-in-place'; $reason = 'ext' }
163
+ elseif ($f.Length -gt ($MaxMB * 1MB)) { $action = 'indexed-in-place'; $reason = 'size' }
164
+
165
+ # Parent-folder date only inside a folder row; a loose file's parent is the old root, whose name says nothing about the file.
166
+ $parentForDate = ''
167
+ if ($srcItem.PSIsContainer -and $f.Directory.FullName -ne $srcItem.FullName) { $parentForDate = $f.Directory.Name }
168
+ $date = Get-DateToken $f.Name $parentForDate
169
+ $newName = $f.Name
170
+ if ($action -eq 'copy' -and $row['prefix'] -eq 'yes') {
171
+ $entityTok = $row['entity']
172
+ if ($f.Name -notmatch $DatedNameRe -and -not $f.Name.StartsWith($entityTok + '_')) {
173
+ $cand = '{0}_{1}_{2}_{3}__{4}' -f $entityTok, $row['area'], $date, $row['doc_type'], $f.Name
174
+ if ((Join-Path $destDir $cand).Length -le $MaxPath) { $newName = $cand }
175
+ }
176
+ }
177
+ $canonical = ''
178
+ if ($action -eq 'copy') { $canonical = Join-Path $destDir $newName }
179
+ $items += , @{
180
+ source = $f.FullName; name = $f.Name; bytes = $f.Length; destDir = $destDir; newName = $newName
181
+ canonical = $canonical; action = $action; reason = $reason; date = $date
182
+ entity = $row['entity']; area = $row['area']; project = $row['project']; doc_type = $row['doc_type']
183
+ tags = $row['tags']; catalog_root = $row['catalog_root']; sha256 = ''; persist = ''
184
+ }
185
+ }
186
+ }
187
+ return $items
188
+ }
189
+
190
+ function Read-CountOnly([string]$Path) {
191
+ if ([string]::IsNullOrEmpty($Path)) { return @() }
192
+ return [System.IO.File]::ReadAllLines($Path, [System.Text.Encoding]::UTF8) | Where-Object { $_.Trim() -ne '' -and -not $_.TrimStart().StartsWith('#') } | ForEach-Object { $_.Trim() }
193
+ }
194
+ function Count-Files([string]$Folder) {
195
+ if (-not (Test-Path -LiteralPath $Folder)) { return -1 }
196
+ return @(Get-ChildItem -LiteralPath $Folder -Recurse -File -Force | Where-Object { $_.Name -notin @('desktop.ini', '.DS_Store', 'Thumbs.db') }).Count
197
+ }
198
+
199
+ New-Item -ItemType Directory -Force -Path $Out | Out-Null
200
+ $Out = (Resolve-Path -LiteralPath $Out).Path
201
+ $Plan = (Resolve-Path -LiteralPath $Plan).Path
202
+ if ($CountOnly) { $CountOnly = (Resolve-Path -LiteralPath $CountOnly).Path }
203
+ $inventoryPath = Join-Path $Out 'inventory.csv'
204
+ $countPath = Join-Path $Out 'count-only.csv'
205
+ $previewPath = Join-Path $Out 'preview.tsv'
206
+ $catalogPath = Join-Path $Out 'catalog.jsonl'
207
+ $applyLogPath = Join-Path $Out 'apply-log.tsv'
208
+ $verifyPath = Join-Path $Out 'verify-report.txt'
209
+
210
+ $rows = Read-Tsv $Plan
211
+ Write-Host ("plan rows: {0}" -f $rows.Count)
212
+
213
+ switch ($Mode) {
214
+ 'inventory' {
215
+ $items = Expand-Plan $rows
216
+ $lines = @('path,bytes,sha256')
217
+ $i = 0
218
+ foreach ($it in $items) {
219
+ $i++
220
+ if ($i % 50 -eq 0) { Write-Host ("hashing {0}/{1}" -f $i, $items.Count) }
221
+ # Hash only what will be copied; in-place items (media, secrets, installers) are size-checked
222
+ # so a streaming cloud drive is not forced to download them.
223
+ $h = ''
224
+ if ($it.action -eq 'copy') { $h = Get-Sha256 $it.source }
225
+ $lines += ('"' + $it.source.Replace('"', '""') + '",' + $it.bytes + ',' + $h)
226
+ }
227
+ Write-Utf8Lines $inventoryPath $lines
228
+ $clines = @('folder,files')
229
+ foreach ($folder in (Read-CountOnly $CountOnly)) {
230
+ $clines += ('"' + $folder.Replace('"', '""') + '",' + (Count-Files $folder))
231
+ }
232
+ Write-Utf8Lines $countPath $clines
233
+ Write-Host ("inventory: {0} files -> {1}; count-only folders: {2} -> {3}" -f $items.Count, $inventoryPath, ($clines.Count - 1), $countPath)
234
+ }
235
+ 'dry-run' {
236
+ $items = Expand-Plan $rows
237
+ $lines = @("action`treason`tsource`tdestination`tnew_name`tentity`tarea`tproject`tdoc_type`tdate`ttags")
238
+ $counts = @{}
239
+ foreach ($it in $items) {
240
+ $action = $it.action
241
+ if ($action -eq 'copy' -and (Test-Path -LiteralPath $it.canonical)) { $action = 'skipped-exists' }
242
+ $key = $action; if ($it.reason) { $key = $action + ':' + $it.reason }
243
+ if (-not $counts.ContainsKey($key)) { $counts[$key] = 0 }
244
+ $counts[$key]++
245
+ $lines += ($action, $it.reason, $it.source, $it.destDir, $it.newName, $it.entity, $it.area, $it.project, $it.doc_type, $it.date, $it.tags) -join "`t"
246
+ }
247
+ Write-Utf8Lines $previewPath $lines
248
+ Write-Host ("preview -> {0}" -f $previewPath)
249
+ foreach ($k in ($counts.Keys | Sort-Object)) { Write-Host (" {0,-24} {1}" -f $k, $counts[$k]) }
250
+ }
251
+ 'apply' {
252
+ if (-not (Test-Path -LiteralPath $inventoryPath)) { throw "inventory.csv missing under $Out - run -Mode inventory first" }
253
+ $inv = @{}
254
+ foreach ($r in (Import-Csv -LiteralPath $inventoryPath -Encoding UTF8)) { $inv[$r.path] = $r }
255
+ $items = Expand-Plan $rows
256
+ $log = @("action`tsource`tcanonical`tbytes`tsha256")
257
+ $catalogLines = @()
258
+ $perRoot = @{}
259
+ $counts = @{ 'copied-source-kept' = 0; 'skipped-exists' = 0; 'indexed-in-place' = 0; 'failed' = 0 }
260
+ $copiedBytes = [long]0
261
+ $n = 0
262
+ foreach ($it in $items) {
263
+ $n++
264
+ if ($n % 50 -eq 0) { Write-Host ("apply {0}/{1}" -f $n, $items.Count) }
265
+ if (-not $inv.ContainsKey($it.source)) { throw "source not in inventory (plan changed after inventory?): $($it.source)" }
266
+ $it.sha256 = $inv[$it.source].sha256
267
+ if ($it.action -eq 'indexed-in-place') {
268
+ $it.persist = 'indexed-in-place'; $it.canonical = $it.source
269
+ }
270
+ elseif (Test-Path -LiteralPath $it.canonical) {
271
+ $it.persist = 'skipped-exists'
272
+ }
273
+ else {
274
+ try {
275
+ New-Item -ItemType Directory -Force -Path $it.destDir | Out-Null
276
+ Copy-Item -LiteralPath $it.source -Destination $it.canonical
277
+ $destHash = Get-Sha256 $it.canonical
278
+ if ($destHash -eq $it.sha256) { $it.persist = 'copied-source-kept'; $copiedBytes += [long]$it.bytes }
279
+ else { $it.persist = 'failed'; $it.reason = 'hash-mismatch' }
280
+ } catch {
281
+ $it.persist = 'failed'; $it.reason = ('copy-error: ' + $_.Exception.Message.Replace("`n", ' '))
282
+ }
283
+ }
284
+ $counts[$it.persist]++
285
+ $log += ($it.persist, $it.source, $it.canonical, $it.bytes, $it.sha256) -join "`t"
286
+ $line = To-CatalogLine $it
287
+ $catalogLines += $line
288
+ if ($it.catalog_root) {
289
+ if (-not $perRoot.ContainsKey($it.catalog_root)) { $perRoot[$it.catalog_root] = @() }
290
+ $perRoot[$it.catalog_root] += $line
291
+ }
292
+ }
293
+ Write-Utf8Lines $applyLogPath $log
294
+ Append-Utf8Lines $catalogPath $catalogLines
295
+ $searchMd = @(
296
+ '# _SEARCH.md - how to find a file here',
297
+ '',
298
+ '1. grep `_ai-catalog.jsonl` in this folder: tags, entity, area, doc_type, date, original_name.',
299
+ '2. Search the prefixed filename: `{entity}_{area}_{date}_{doc_type}__{original name}`.',
300
+ '3. Search the original name after `__`; it is unchanged.',
301
+ '',
302
+ 'persist values: copied-source-kept (original still at original_path), indexed-in-place (only copy is at original_path), skipped-exists, failed.',
303
+ 'Keys, credentials, videos, and installers are never copied here; the catalog points to where they already live.'
304
+ )
305
+ foreach ($root in $perRoot.Keys) {
306
+ New-Item -ItemType Directory -Force -Path $root | Out-Null
307
+ Append-Utf8Lines (Join-Path $root '_ai-catalog.jsonl') $perRoot[$root]
308
+ $sp = Join-Path $root '_SEARCH.md'
309
+ if (-not (Test-Path -LiteralPath $sp)) { Write-Utf8Lines $sp $searchMd }
310
+ }
311
+ Write-Host ("apply done: copied={0} skipped-exists={1} indexed-in-place={2} failed={3} copiedMB={4:N1}" -f $counts['copied-source-kept'], $counts['skipped-exists'], $counts['indexed-in-place'], $counts['failed'], ($copiedBytes / 1MB))
312
+ Write-Host ("log -> {0}`ncatalog -> {1}" -f $applyLogPath, $catalogPath)
313
+ if ($counts['failed'] -gt 0) { exit 2 }
314
+ }
315
+ 'verify' {
316
+ if (-not (Test-Path -LiteralPath $inventoryPath)) { throw "inventory.csv missing under $Out" }
317
+ $report = @("verify run $RunStamp")
318
+ $fail = 0
319
+ $checked = 0
320
+ foreach ($r in (Import-Csv -LiteralPath $inventoryPath -Encoding UTF8)) {
321
+ $checked++
322
+ if (-not (Test-Path -LiteralPath $r.path)) { $fail++; $report += "MISSING source: $($r.path)"; continue }
323
+ $len = (Get-Item -LiteralPath $r.path -Force).Length
324
+ if ([string]$len -ne [string]$r.bytes) { $fail++; $report += "RESIZED source: $($r.path) $($r.bytes) -> $len" }
325
+ }
326
+ $report += "sources checked: $checked"
327
+ $copies = 0; $inplace = 0
328
+ if (Test-Path -LiteralPath $catalogPath) {
329
+ foreach ($line in [System.IO.File]::ReadAllLines($catalogPath, [System.Text.Encoding]::UTF8)) {
330
+ if ($line.Trim() -eq '') { continue }
331
+ $o = $line | ConvertFrom-Json
332
+ if ($o.persist -eq 'copied-source-kept') {
333
+ $copies++
334
+ if (-not (Test-Path -LiteralPath $o.canonical_path)) { $fail++; $report += "MISSING copy: $($o.canonical_path)"; continue }
335
+ $h = Get-Sha256 $o.canonical_path
336
+ if ($h -ne $o.sha256) { $fail++; $report += "HASH MISMATCH copy: $($o.canonical_path)" }
337
+ } elseif ($o.persist -eq 'indexed-in-place') {
338
+ $inplace++
339
+ if (-not (Test-Path -LiteralPath $o.original_path)) { $fail++; $report += "MISSING in-place: $($o.original_path)" }
340
+ }
341
+ }
342
+ }
343
+ $report += "copies re-hashed: $copies"
344
+ $report += "in-place files present-checked: $inplace"
345
+ if (Test-Path -LiteralPath $countPath) {
346
+ $cc = 0
347
+ foreach ($r in (Import-Csv -LiteralPath $countPath -Encoding UTF8)) {
348
+ $cc++
349
+ $now = Count-Files $r.folder
350
+ if ([string]$now -ne [string]$r.files) { $fail++; $report += "COUNT CHANGED: $($r.folder) $($r.files) -> $now" }
351
+ }
352
+ $report += "count-only folders rechecked: $cc"
353
+ }
354
+ $report += "failures: $fail"
355
+ $report += $(if ($fail -eq 0) { 'RESULT: PASS - every source present, every copy hash-equal, media counts unchanged' } else { 'RESULT: FAIL' })
356
+ Write-Utf8Lines $verifyPath $report
357
+ $report | ForEach-Object { Write-Host $_ }
358
+ if ($fail -gt 0) { exit 1 }
359
+ }
360
+ }