@nextsparkjs/ai-workflow 0.1.0-beta.100

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 (272) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -0
  3. package/claude/_docs/workflows-optimizations.md +359 -0
  4. package/claude/agents/api-tester.md +634 -0
  5. package/claude/agents/architecture-supervisor.md +1351 -0
  6. package/claude/agents/backend-developer.md +997 -0
  7. package/claude/agents/backend-validator.md +417 -0
  8. package/claude/agents/bdd-docs-writer.md +737 -0
  9. package/claude/agents/block-developer.md +677 -0
  10. package/claude/agents/code-reviewer.md +1432 -0
  11. package/claude/agents/db-developer.md +721 -0
  12. package/claude/agents/db-validator.md +407 -0
  13. package/claude/agents/demo-video-generator.md +493 -0
  14. package/claude/agents/documentation-writer.md +1268 -0
  15. package/claude/agents/frontend-developer.md +1234 -0
  16. package/claude/agents/frontend-validator.md +777 -0
  17. package/claude/agents/functional-validator.md +630 -0
  18. package/claude/agents/mock-analyst.md +387 -0
  19. package/claude/agents/product-manager.md +963 -0
  20. package/claude/agents/qa-automation.md +1762 -0
  21. package/claude/agents/release-manager.md +634 -0
  22. package/claude/agents/selectors-translator.md +262 -0
  23. package/claude/agents/unit-test-writer.md +785 -0
  24. package/claude/agents/visual-comparator.md +329 -0
  25. package/claude/agents/workflow-maintainer.md +352 -0
  26. package/claude/commands/do/README.md +88 -0
  27. package/claude/commands/do/create-api.md +64 -0
  28. package/claude/commands/do/create-entity.md +66 -0
  29. package/claude/commands/do/create-migration.md +64 -0
  30. package/claude/commands/do/create-plugin.md +56 -0
  31. package/claude/commands/do/create-theme.md +70 -0
  32. package/claude/commands/do/mock-data.md +67 -0
  33. package/claude/commands/do/reset-db.md +71 -0
  34. package/claude/commands/do/setup-scheduled-action.md +75 -0
  35. package/claude/commands/do/sync-code-review.md +117 -0
  36. package/claude/commands/do/update-selectors.md +112 -0
  37. package/claude/commands/do/use-skills.md +90 -0
  38. package/claude/commands/do/validate-blocks.md +69 -0
  39. package/claude/commands/how-to/README.md +261 -0
  40. package/claude/commands/how-to/add-metadata.md +692 -0
  41. package/claude/commands/how-to/add-taxonomies.md +806 -0
  42. package/claude/commands/how-to/add-translations.md +571 -0
  43. package/claude/commands/how-to/create-api.md +577 -0
  44. package/claude/commands/how-to/create-block.md +575 -0
  45. package/claude/commands/how-to/create-child-entities.md +771 -0
  46. package/claude/commands/how-to/create-entity.md +597 -0
  47. package/claude/commands/how-to/create-migrations.md +605 -0
  48. package/claude/commands/how-to/create-plugin.md +654 -0
  49. package/claude/commands/how-to/customize-app.md +481 -0
  50. package/claude/commands/how-to/customize-dashboard.md +553 -0
  51. package/claude/commands/how-to/customize-theme.md +438 -0
  52. package/claude/commands/how-to/define-features-flows.md +632 -0
  53. package/claude/commands/how-to/deploy.md +507 -0
  54. package/claude/commands/how-to/handle-file-uploads.md +746 -0
  55. package/claude/commands/how-to/implement-search.md +1001 -0
  56. package/claude/commands/how-to/install-plugins.md +352 -0
  57. package/claude/commands/how-to/manage-test-coverage.md +984 -0
  58. package/claude/commands/how-to/run-tests.md +400 -0
  59. package/claude/commands/how-to/set-app-languages.md +601 -0
  60. package/claude/commands/how-to/set-plans-and-permissions.md +575 -0
  61. package/claude/commands/how-to/set-scheduled-actions.md +527 -0
  62. package/claude/commands/how-to/set-user-roles-and-permissions.md +550 -0
  63. package/claude/commands/how-to/setup-authentication.md +388 -0
  64. package/claude/commands/how-to/setup-claude-code.md +440 -0
  65. package/claude/commands/how-to/setup-database.md +274 -0
  66. package/claude/commands/how-to/setup-email-providers.md +598 -0
  67. package/claude/commands/how-to/setup-mobile-dev.md +627 -0
  68. package/claude/commands/how-to/start.md +500 -0
  69. package/claude/commands/how-to/use-devtools.md +639 -0
  70. package/claude/commands/how-to/use-superadmin.md +622 -0
  71. package/claude/commands/session/README.md +193 -0
  72. package/claude/commands/session/block-create.md +190 -0
  73. package/claude/commands/session/block-list.md +203 -0
  74. package/claude/commands/session/block-update.md +192 -0
  75. package/claude/commands/session/block-validate.md +218 -0
  76. package/claude/commands/session/changelog.md +115 -0
  77. package/claude/commands/session/close.md +225 -0
  78. package/claude/commands/session/commit.md +174 -0
  79. package/claude/commands/session/db-entity.md +206 -0
  80. package/claude/commands/session/db-fix.md +212 -0
  81. package/claude/commands/session/db-sample.md +206 -0
  82. package/claude/commands/session/demo.md +178 -0
  83. package/claude/commands/session/doc-bdd.md +207 -0
  84. package/claude/commands/session/doc-feature.md +218 -0
  85. package/claude/commands/session/doc-read.md +225 -0
  86. package/claude/commands/session/execute.md +204 -0
  87. package/claude/commands/session/explain.md +202 -0
  88. package/claude/commands/session/fix-bug.md +210 -0
  89. package/claude/commands/session/fix-build.md +182 -0
  90. package/claude/commands/session/fix-test.md +189 -0
  91. package/claude/commands/session/pending.md +232 -0
  92. package/claude/commands/session/refine.md +188 -0
  93. package/claude/commands/session/resume.md +192 -0
  94. package/claude/commands/session/review.md +192 -0
  95. package/claude/commands/session/scope-change.md +181 -0
  96. package/claude/commands/session/start-blocks.md +347 -0
  97. package/claude/commands/session/start.md +604 -0
  98. package/claude/commands/session/status.md +169 -0
  99. package/claude/commands/session/test-fix.md +221 -0
  100. package/claude/commands/session/test-run.md +203 -0
  101. package/claude/commands/session/test-write.md +242 -0
  102. package/claude/commands/session/validate.md +162 -0
  103. package/claude/config/context.json +40 -0
  104. package/claude/config/github.json +69 -0
  105. package/claude/config/github.schema.json +106 -0
  106. package/claude/config/team.json +46 -0
  107. package/claude/config/team.schema.json +106 -0
  108. package/claude/config/workspace.json +43 -0
  109. package/claude/config/workspace.schema.json +75 -0
  110. package/claude/skills/README.md +228 -0
  111. package/claude/skills/accessibility/SKILL.md +573 -0
  112. package/claude/skills/api-bypass-layers/SKILL.md +550 -0
  113. package/claude/skills/asana-integration/SKILL.md +499 -0
  114. package/claude/skills/better-auth/SKILL.md +666 -0
  115. package/claude/skills/billing-subscriptions/SKILL.md +660 -0
  116. package/claude/skills/block-decision-matrix/SKILL.md +359 -0
  117. package/claude/skills/clickup-integration/SKILL.md +434 -0
  118. package/claude/skills/core-theme-responsibilities/SKILL.md +485 -0
  119. package/claude/skills/create-plugin/SKILL.md +425 -0
  120. package/claude/skills/create-theme/SKILL.md +331 -0
  121. package/claude/skills/cypress-api/SKILL.md +511 -0
  122. package/claude/skills/cypress-api/scripts/generate-api-controller.py +329 -0
  123. package/claude/skills/cypress-api/scripts/generate-api-test.py +930 -0
  124. package/claude/skills/cypress-e2e/SKILL.md +526 -0
  125. package/claude/skills/cypress-e2e/scripts/extract-selectors.py +383 -0
  126. package/claude/skills/cypress-e2e/scripts/generate-uat-test.py +788 -0
  127. package/claude/skills/cypress-selectors/SKILL.md +309 -0
  128. package/claude/skills/cypress-selectors/scripts/extract-missing.py +243 -0
  129. package/claude/skills/cypress-selectors/scripts/generate-block-selectors.py +283 -0
  130. package/claude/skills/cypress-selectors/scripts/validate-selectors.py +145 -0
  131. package/claude/skills/database-migrations/SKILL.md +335 -0
  132. package/claude/skills/database-migrations/scripts/generate-sample-data.py +284 -0
  133. package/claude/skills/database-migrations/scripts/validate-migration.py +323 -0
  134. package/claude/skills/design-system/SKILL.md +682 -0
  135. package/claude/skills/documentation/SKILL.md +540 -0
  136. package/claude/skills/entity-api/SKILL.md +482 -0
  137. package/claude/skills/entity-system/SKILL.md +635 -0
  138. package/claude/skills/entity-system/scripts/generate-child-migration.py +298 -0
  139. package/claude/skills/entity-system/scripts/generate-metas-migration.py +233 -0
  140. package/claude/skills/entity-system/scripts/generate-migration.py +382 -0
  141. package/claude/skills/entity-system/scripts/generate-sample-data.py +418 -0
  142. package/claude/skills/entity-system/scripts/scaffold-entity.py +661 -0
  143. package/claude/skills/github/SKILL.md +467 -0
  144. package/claude/skills/i18n-nextintl/SKILL.md +302 -0
  145. package/claude/skills/i18n-nextintl/scripts/add-translation.py +243 -0
  146. package/claude/skills/i18n-nextintl/scripts/extract-hardcoded.py +246 -0
  147. package/claude/skills/i18n-nextintl/scripts/validate-translations.py +260 -0
  148. package/claude/skills/impact-analysis/SKILL.md +203 -0
  149. package/claude/skills/jest-unit/SKILL.md +306 -0
  150. package/claude/skills/jest-unit/references/component-testing.md +371 -0
  151. package/claude/skills/jest-unit/references/mocking-patterns.md +380 -0
  152. package/claude/skills/jest-unit/references/service-hook-testing.md +454 -0
  153. package/claude/skills/jira-integration/SKILL.md +539 -0
  154. package/claude/skills/media-library/SKILL.md +743 -0
  155. package/claude/skills/mock-analysis/SKILL.md +276 -0
  156. package/claude/skills/monorepo-architecture/SKILL.md +162 -0
  157. package/claude/skills/nextjs-api-development/SKILL.md +364 -0
  158. package/claude/skills/nextjs-api-development/scripts/generate-crud-tests.py +456 -0
  159. package/claude/skills/nextjs-api-development/scripts/scaffold-endpoint.py +481 -0
  160. package/claude/skills/nextjs-api-development/scripts/validate-api.py +283 -0
  161. package/claude/skills/notion-integration/SKILL.md +641 -0
  162. package/claude/skills/npm-development-workflow/SKILL.md +480 -0
  163. package/claude/skills/page-builder-blocks/SKILL.md +530 -0
  164. package/claude/skills/page-builder-blocks/scripts/scaffold-block.py +444 -0
  165. package/claude/skills/permissions-system/SKILL.md +619 -0
  166. package/claude/skills/plugins/SKILL.md +340 -0
  167. package/claude/skills/plugins/references/plugin-templates.md +414 -0
  168. package/claude/skills/plugins/references/plugin-testing.md +353 -0
  169. package/claude/skills/plugins/references/plugin-types.md +198 -0
  170. package/claude/skills/plugins/scripts/scaffold-plugin.py +443 -0
  171. package/claude/skills/pom-patterns/SKILL.md +452 -0
  172. package/claude/skills/pom-patterns/scripts/generate-pom.py +392 -0
  173. package/claude/skills/rate-limiting/SKILL.md +342 -0
  174. package/claude/skills/react-best-practices/AGENTS.md +2410 -0
  175. package/claude/skills/react-best-practices/README.md +123 -0
  176. package/claude/skills/react-best-practices/SKILL.md +125 -0
  177. package/claude/skills/react-best-practices/metadata.json +15 -0
  178. package/claude/skills/react-best-practices/rules/_sections.md +46 -0
  179. package/claude/skills/react-best-practices/rules/_template.md +28 -0
  180. package/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  181. package/claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  182. package/claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
  183. package/claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
  184. package/claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
  185. package/claude/skills/react-best-practices/rules/async-parallel.md +28 -0
  186. package/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  187. package/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  188. package/claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  189. package/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  190. package/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  191. package/claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
  192. package/claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  193. package/claude/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  194. package/claude/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  195. package/claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  196. package/claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  197. package/claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  198. package/claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  199. package/claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  200. package/claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  201. package/claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
  202. package/claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  203. package/claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
  204. package/claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  205. package/claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  206. package/claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  207. package/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  208. package/claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
  209. package/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  210. package/claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  211. package/claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  212. package/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  213. package/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  214. package/claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  215. package/claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  216. package/claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  217. package/claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  218. package/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  219. package/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  220. package/claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
  221. package/claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  222. package/claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  223. package/claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  224. package/claude/skills/react-best-practices/rules/server-cache-react.md +76 -0
  225. package/claude/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  226. package/claude/skills/react-best-practices/rules/server-serialization.md +38 -0
  227. package/claude/skills/react-patterns/SKILL.md +688 -0
  228. package/claude/skills/registry-system/SKILL.md +331 -0
  229. package/claude/skills/scheduled-actions/SKILL.md +671 -0
  230. package/claude/skills/scope-enforcement/SKILL.md +542 -0
  231. package/claude/skills/scope-enforcement/scripts/validate-scope.py +357 -0
  232. package/claude/skills/server-actions/SKILL.md +493 -0
  233. package/claude/skills/service-layer/SKILL.md +587 -0
  234. package/claude/skills/session-management/SKILL.md +266 -0
  235. package/claude/skills/session-management/scripts/create-session.py +166 -0
  236. package/claude/skills/session-management/scripts/iteration-close.sh +105 -0
  237. package/claude/skills/session-management/scripts/iteration-init.sh +180 -0
  238. package/claude/skills/session-management/scripts/session-archive.sh +87 -0
  239. package/claude/skills/session-management/scripts/session-close.sh +133 -0
  240. package/claude/skills/session-management/scripts/session-init.sh +225 -0
  241. package/claude/skills/session-management/scripts/session-list.sh +163 -0
  242. package/claude/skills/session-management/scripts/split-plan.sh +116 -0
  243. package/claude/skills/shadcn-components/SKILL.md +586 -0
  244. package/claude/skills/shadcn-theming/SKILL.md +446 -0
  245. package/claude/skills/suspense-loading/SKILL.md +280 -0
  246. package/claude/skills/tailwind-theming/SKILL.md +507 -0
  247. package/claude/skills/tanstack-query/SKILL.md +608 -0
  248. package/claude/skills/test-coverage/SKILL.md +239 -0
  249. package/claude/skills/web-design-guidelines/SKILL.md +39 -0
  250. package/claude/skills/zod-validation/SKILL.md +537 -0
  251. package/claude/templates/blocks/progress.md +86 -0
  252. package/claude/templates/iteration/changes.md +61 -0
  253. package/claude/templates/iteration/progress.md +55 -0
  254. package/claude/templates/log.md +31 -0
  255. package/claude/templates/story/context.md +77 -0
  256. package/claude/templates/story/pendings.md +37 -0
  257. package/claude/templates/story/plan.md +299 -0
  258. package/claude/templates/story/requirements.md +109 -0
  259. package/claude/templates/story/scope.json +10 -0
  260. package/claude/templates/story/tests.md +91 -0
  261. package/claude/templates/task/progress.md +58 -0
  262. package/claude/templates/task/requirements.md +54 -0
  263. package/claude/workflows/README.md +154 -0
  264. package/claude/workflows/blocks.md +614 -0
  265. package/claude/workflows/story.md +1207 -0
  266. package/claude/workflows/task.md +927 -0
  267. package/claude/workflows/tweak.md +527 -0
  268. package/cursor/.gitkeep +0 -0
  269. package/package.json +35 -0
  270. package/scripts/postinstall.mjs +198 -0
  271. package/scripts/setup.mjs +282 -0
  272. package/scripts/sync.mjs +209 -0
@@ -0,0 +1,357 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Validate Scope Script
4
+
5
+ Validates file modifications against session scope.json configuration.
6
+ Part of the scope-enforcement skill.
7
+
8
+ Usage:
9
+ python validate-scope.py --session ".claude/sessions/2025-12-30-feature-v1"
10
+ python validate-scope.py -s ".claude/sessions/2025-12-30-feature-v1" --files "core/lib/x.ts,app/api/y/route.ts"
11
+ python validate-scope.py -s ".claude/sessions/2025-12-30-feature-v1" --git # Check git changes
12
+ """
13
+
14
+ import argparse
15
+ import fnmatch
16
+ import json
17
+ import os
18
+ import subprocess
19
+ import sys
20
+ from pathlib import Path
21
+ from typing import List, Dict, Any, Optional
22
+
23
+
24
+ def get_project_root() -> Path:
25
+ """Find the project root by looking for .claude directory."""
26
+ current = Path(__file__).resolve()
27
+
28
+ # Walk up the directory tree
29
+ for parent in current.parents:
30
+ if (parent / ".claude").is_dir():
31
+ return parent
32
+
33
+ # Fallback: check current working directory
34
+ cwd = Path.cwd()
35
+ if (cwd / ".claude").is_dir():
36
+ return cwd
37
+
38
+ print("Error: Could not find project root (.claude directory)")
39
+ sys.exit(1)
40
+
41
+
42
+ def read_scope_config(session_path: Path) -> Dict[str, Any]:
43
+ """Read and parse scope.json from session folder."""
44
+ scope_file = session_path / "scope.json"
45
+
46
+ if not scope_file.exists():
47
+ print(f"Error: scope.json not found in {session_path}")
48
+ sys.exit(1)
49
+
50
+ try:
51
+ with open(scope_file, "r") as f:
52
+ return json.load(f)
53
+ except json.JSONDecodeError as e:
54
+ print(f"Error: Invalid JSON in scope.json: {e}")
55
+ sys.exit(1)
56
+
57
+
58
+ def build_allowed_paths(scope_config: Dict[str, Any]) -> List[str]:
59
+ """Build list of allowed paths from scope configuration."""
60
+ allowed_paths = [".claude/sessions/**/*"]
61
+
62
+ scope = scope_config.get("scope", {})
63
+
64
+ # Core paths
65
+ if scope.get("core", False):
66
+ allowed_paths.extend([
67
+ "core/**/*",
68
+ "app/**/*",
69
+ "scripts/**/*",
70
+ "migrations/**/*",
71
+ "core/migrations/**/*"
72
+ ])
73
+
74
+ # Theme paths
75
+ theme = scope.get("theme")
76
+ if theme and theme != False:
77
+ allowed_paths.append(f"contents/themes/{theme}/**/*")
78
+
79
+ # Plugin paths
80
+ plugins = scope.get("plugins")
81
+ if isinstance(plugins, list):
82
+ for plugin in plugins:
83
+ allowed_paths.append(f"contents/plugins/{plugin}/**/*")
84
+
85
+ # Exceptions
86
+ exceptions = scope_config.get("exceptions", [])
87
+ allowed_paths.extend(exceptions)
88
+
89
+ # Also check allowedPaths if explicitly defined
90
+ explicit_paths = scope_config.get("allowedPaths", [])
91
+ allowed_paths.extend(explicit_paths)
92
+
93
+ return allowed_paths
94
+
95
+
96
+ def matches_pattern(file_path: str, pattern: str) -> bool:
97
+ """Check if file path matches glob pattern."""
98
+ # Normalize paths
99
+ file_path = file_path.replace("\\", "/")
100
+ pattern = pattern.replace("\\", "/")
101
+
102
+ # Handle ** patterns
103
+ if "**" in pattern:
104
+ # Split pattern into parts
105
+ parts = pattern.split("**")
106
+ if len(parts) == 2:
107
+ prefix, suffix = parts
108
+ prefix = prefix.rstrip("/")
109
+ suffix = suffix.lstrip("/")
110
+
111
+ # Check if file starts with prefix
112
+ if prefix and not file_path.startswith(prefix):
113
+ return False
114
+
115
+ # If suffix is "*", match anything after prefix
116
+ if suffix == "*" or suffix == "/*":
117
+ return file_path.startswith(prefix)
118
+
119
+ # Check if file ends with suffix pattern
120
+ if suffix:
121
+ remaining = file_path[len(prefix):].lstrip("/")
122
+ return fnmatch.fnmatch(remaining, f"**/{suffix}") or fnmatch.fnmatch(remaining, suffix)
123
+
124
+ return file_path.startswith(prefix)
125
+
126
+ # Standard glob matching
127
+ return fnmatch.fnmatch(file_path, pattern)
128
+
129
+
130
+ def validate_files(files: List[str], allowed_paths: List[str]) -> Dict[str, List[str]]:
131
+ """Validate files against allowed paths."""
132
+ valid_files = []
133
+ violations = []
134
+
135
+ for file_path in files:
136
+ # Normalize path
137
+ file_path = file_path.strip()
138
+ if not file_path:
139
+ continue
140
+
141
+ # Check against all allowed patterns
142
+ is_allowed = False
143
+ for pattern in allowed_paths:
144
+ if matches_pattern(file_path, pattern):
145
+ is_allowed = True
146
+ break
147
+
148
+ if is_allowed:
149
+ valid_files.append(file_path)
150
+ else:
151
+ violations.append(file_path)
152
+
153
+ return {
154
+ "valid": valid_files,
155
+ "violations": violations
156
+ }
157
+
158
+
159
+ def get_git_changed_files(project_root: Path) -> List[str]:
160
+ """Get list of changed files from git."""
161
+ try:
162
+ # Get staged and unstaged changes
163
+ result = subprocess.run(
164
+ ["git", "diff", "--name-only", "HEAD"],
165
+ cwd=project_root,
166
+ capture_output=True,
167
+ text=True
168
+ )
169
+
170
+ if result.returncode != 0:
171
+ # Try without HEAD (for initial commits)
172
+ result = subprocess.run(
173
+ ["git", "status", "--porcelain"],
174
+ cwd=project_root,
175
+ capture_output=True,
176
+ text=True
177
+ )
178
+
179
+ if result.returncode != 0:
180
+ print("Error: Could not get git changes")
181
+ return []
182
+
183
+ # Parse porcelain output
184
+ files = []
185
+ for line in result.stdout.strip().split("\n"):
186
+ if line:
187
+ # Format: XY filename
188
+ files.append(line[3:].strip())
189
+ return files
190
+
191
+ return [f.strip() for f in result.stdout.strip().split("\n") if f.strip()]
192
+
193
+ except FileNotFoundError:
194
+ print("Error: git not found")
195
+ return []
196
+
197
+
198
+ def print_scope_summary(scope_config: Dict[str, Any]) -> None:
199
+ """Print a summary of the scope configuration."""
200
+ scope = scope_config.get("scope", {})
201
+
202
+ print("\n" + "=" * 60)
203
+ print("SCOPE CONFIGURATION")
204
+ print("=" * 60)
205
+
206
+ print(f"\nSession: {scope_config.get('session', 'Unknown')}")
207
+ print(f"Defined by: {scope_config.get('definedBy', 'Unknown')}")
208
+ print(f"Date: {scope_config.get('date', 'Unknown')}")
209
+
210
+ print("\nScope Settings:")
211
+ print(f" Core: {'ALLOWED' if scope.get('core') else 'DENIED'}")
212
+ print(f" Theme: {scope.get('theme') or 'NONE'}")
213
+ print(f" Plugins: {scope.get('plugins') if isinstance(scope.get('plugins'), list) else 'NONE'}")
214
+
215
+ exceptions = scope_config.get("exceptions", [])
216
+ if exceptions:
217
+ print(f"\nExceptions ({len(exceptions)}):")
218
+ for exc in exceptions:
219
+ print(f" + {exc}")
220
+
221
+
222
+ def print_validation_result(result: Dict[str, List[str]], allowed_paths: List[str]) -> None:
223
+ """Print validation results."""
224
+ violations = result["violations"]
225
+ valid_files = result["valid"]
226
+
227
+ print("\n" + "=" * 60)
228
+ print("VALIDATION RESULT")
229
+ print("=" * 60)
230
+
231
+ if violations:
232
+ print("\n SCOPE VIOLATIONS DETECTED")
233
+ print("-" * 40)
234
+ for file in violations:
235
+ print(f" {file}")
236
+
237
+ print("\nAllowed Paths:")
238
+ for path in allowed_paths:
239
+ print(f" {path}")
240
+
241
+ print("\nRequired Actions:")
242
+ print(" 1. Revert modifications to files outside scope")
243
+ print(" 2. OR request scope expansion via /task:scope-change")
244
+ print(" 3. OR move logic to an allowed path")
245
+ else:
246
+ print("\n All files are within scope")
247
+ print(f"\nValidated {len(valid_files)} file(s)")
248
+
249
+ if valid_files:
250
+ print("\nValid Files:")
251
+ for file in valid_files:
252
+ print(f" {file}")
253
+
254
+
255
+ def main():
256
+ parser = argparse.ArgumentParser(
257
+ description="Validate file modifications against session scope",
258
+ formatter_class=argparse.RawDescriptionHelpFormatter,
259
+ epilog="""
260
+ Examples:
261
+ python validate-scope.py --session ".claude/sessions/2025-12-30-feature-v1"
262
+ python validate-scope.py -s ".claude/sessions/2025-12-30-feature-v1" --files "core/lib/x.ts"
263
+ python validate-scope.py -s ".claude/sessions/2025-12-30-feature-v1" --git
264
+ """
265
+ )
266
+
267
+ parser.add_argument(
268
+ "-s", "--session",
269
+ required=True,
270
+ help="Path to session folder (relative to project root)"
271
+ )
272
+
273
+ parser.add_argument(
274
+ "-f", "--files",
275
+ help="Comma-separated list of files to validate"
276
+ )
277
+
278
+ parser.add_argument(
279
+ "-g", "--git",
280
+ action="store_true",
281
+ help="Validate git changed files instead of explicit list"
282
+ )
283
+
284
+ parser.add_argument(
285
+ "-q", "--quiet",
286
+ action="store_true",
287
+ help="Only output violations (exit code indicates result)"
288
+ )
289
+
290
+ parser.add_argument(
291
+ "--json",
292
+ action="store_true",
293
+ help="Output results as JSON"
294
+ )
295
+
296
+ args = parser.parse_args()
297
+
298
+ project_root = get_project_root()
299
+ session_path = project_root / args.session
300
+
301
+ # Validate session exists
302
+ if not session_path.exists():
303
+ print(f"Error: Session not found: {session_path}")
304
+ sys.exit(1)
305
+
306
+ # Read scope configuration
307
+ scope_config = read_scope_config(session_path)
308
+
309
+ # Build allowed paths
310
+ allowed_paths = build_allowed_paths(scope_config)
311
+
312
+ # Get files to validate
313
+ if args.git:
314
+ files = get_git_changed_files(project_root)
315
+ if not files:
316
+ if not args.quiet:
317
+ print("No git changes detected")
318
+ sys.exit(0)
319
+ elif args.files:
320
+ files = [f.strip() for f in args.files.split(",") if f.strip()]
321
+ else:
322
+ print("Error: Either --files or --git must be specified")
323
+ sys.exit(1)
324
+
325
+ # Validate files
326
+ result = validate_files(files, allowed_paths)
327
+
328
+ # Output results
329
+ if args.json:
330
+ output = {
331
+ "session": str(session_path),
332
+ "scope": scope_config.get("scope", {}),
333
+ "allowedPaths": allowed_paths,
334
+ "result": {
335
+ "valid": len(result["violations"]) == 0,
336
+ "validFiles": result["valid"],
337
+ "violations": result["violations"]
338
+ }
339
+ }
340
+ print(json.dumps(output, indent=2))
341
+ elif args.quiet:
342
+ if result["violations"]:
343
+ for violation in result["violations"]:
344
+ print(violation)
345
+ else:
346
+ print_scope_summary(scope_config)
347
+ print_validation_result(result, allowed_paths)
348
+
349
+ # Exit with appropriate code
350
+ if result["violations"]:
351
+ sys.exit(1) # Violations found
352
+ else:
353
+ sys.exit(0) # All valid
354
+
355
+
356
+ if __name__ == "__main__":
357
+ main()