ninjastack 0.1.0__tar.gz

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 (412) hide show
  1. ninjastack-0.1.0/.githooks/pre-commit +12 -0
  2. ninjastack-0.1.0/.githooks/pre-push +12 -0
  3. ninjastack-0.1.0/.github/pull_request_template.md +16 -0
  4. ninjastack-0.1.0/.github/scripts/planning_generate.py +102 -0
  5. ninjastack-0.1.0/.github/scripts/triage_analyze.py +105 -0
  6. ninjastack-0.1.0/.github/workflows/ci.yml +37 -0
  7. ninjastack-0.1.0/.github/workflows/pages.yml +46 -0
  8. ninjastack-0.1.0/.github/workflows/planning-agent.yml +72 -0
  9. ninjastack-0.1.0/.github/workflows/planning-approve.yml +51 -0
  10. ninjastack-0.1.0/.github/workflows/static.yml +43 -0
  11. ninjastack-0.1.0/.github/workflows/triage-agent.yml +78 -0
  12. ninjastack-0.1.0/.github/workflows/triage.yml +23 -0
  13. ninjastack-0.1.0/.gitignore +43 -0
  14. ninjastack-0.1.0/.nvmrc +1 -0
  15. ninjastack-0.1.0/.python-version +1 -0
  16. ninjastack-0.1.0/CLAUDE.md +116 -0
  17. ninjastack-0.1.0/Makefile +36 -0
  18. ninjastack-0.1.0/PKG-INFO +262 -0
  19. ninjastack-0.1.0/README.md +230 -0
  20. ninjastack-0.1.0/apps/ninja-api/pyproject.toml +17 -0
  21. ninjastack-0.1.0/apps/ninja-api/src/ninja_api/__init__.py +1 -0
  22. ninjastack-0.1.0/apps/ninja-setup-assistant/pyproject.toml +25 -0
  23. ninjastack-0.1.0/apps/ninja-setup-assistant/src/ninja_setup_assistant/__init__.py +6 -0
  24. ninjastack-0.1.0/apps/ninja-setup-assistant/src/ninja_setup_assistant/assistant.py +129 -0
  25. ninjastack-0.1.0/apps/ninja-setup-assistant/src/ninja_setup_assistant/prompts.py +74 -0
  26. ninjastack-0.1.0/apps/ninja-setup-assistant/src/ninja_setup_assistant/runner.py +148 -0
  27. ninjastack-0.1.0/apps/ninja-setup-assistant/src/ninja_setup_assistant/tools.py +338 -0
  28. ninjastack-0.1.0/apps/ninja-setup-assistant/tests/test_assistant.py +118 -0
  29. ninjastack-0.1.0/apps/ninja-setup-assistant/tests/test_prompts.py +38 -0
  30. ninjastack-0.1.0/apps/ninja-setup-assistant/tests/test_runner.py +24 -0
  31. ninjastack-0.1.0/apps/ninja-setup-assistant/tests/test_tools.py +322 -0
  32. ninjastack-0.1.0/apps/ninja-test-app/pyproject.toml +17 -0
  33. ninjastack-0.1.0/apps/ninja-test-app/src/ninja_test_app/__init__.py +1 -0
  34. ninjastack-0.1.0/apps/ninja-test-app/tests/test_ninja_test_app_imports.py +4 -0
  35. ninjastack-0.1.0/docs/api/agents/base.md +10 -0
  36. ninjastack-0.1.0/docs/api/agents/orchestrator.md +1 -0
  37. ninjastack-0.1.0/docs/api/agents/tools.md +1 -0
  38. ninjastack-0.1.0/docs/api/agents/tracing.md +1 -0
  39. ninjastack-0.1.0/docs/api/auth/context.md +1 -0
  40. ninjastack-0.1.0/docs/api/auth/gateway.md +1 -0
  41. ninjastack-0.1.0/docs/api/auth/rbac.md +1 -0
  42. ninjastack-0.1.0/docs/api/auth/strategies.md +13 -0
  43. ninjastack-0.1.0/docs/api/codegen/engine.md +1 -0
  44. ninjastack-0.1.0/docs/api/codegen/generators.md +13 -0
  45. ninjastack-0.1.0/docs/api/core/agent-config.md +1 -0
  46. ninjastack-0.1.0/docs/api/core/domain.md +1 -0
  47. ninjastack-0.1.0/docs/api/core/entity.md +1 -0
  48. ninjastack-0.1.0/docs/api/core/project.md +1 -0
  49. ninjastack-0.1.0/docs/api/core/relationship.md +1 -0
  50. ninjastack-0.1.0/docs/api/graphql/index.md +5 -0
  51. ninjastack-0.1.0/docs/api/index.md +32 -0
  52. ninjastack-0.1.0/docs/api/introspect/index.md +5 -0
  53. ninjastack-0.1.0/docs/api/persistence/index.md +5 -0
  54. ninjastack-0.1.0/docs/architecture/agent-hierarchy.md +94 -0
  55. ninjastack-0.1.0/docs/architecture/asd.md +165 -0
  56. ninjastack-0.1.0/docs/architecture/auth-rbac.md +124 -0
  57. ninjastack-0.1.0/docs/architecture/codegen.md +95 -0
  58. ninjastack-0.1.0/docs/architecture/index.md +71 -0
  59. ninjastack-0.1.0/docs/architecture/persistence.md +69 -0
  60. ninjastack-0.1.0/docs/architecture.md +145 -0
  61. ninjastack-0.1.0/docs/examples/01-schema.md +21 -0
  62. ninjastack-0.1.0/docs/examples/02-codegen.md +13 -0
  63. ninjastack-0.1.0/docs/examples/03-data-agents.md +13 -0
  64. ninjastack-0.1.0/docs/examples/04-domain-agents.md +13 -0
  65. ninjastack-0.1.0/docs/examples/05-auth-rbac.md +13 -0
  66. ninjastack-0.1.0/docs/examples/06-end-to-end.md +13 -0
  67. ninjastack-0.1.0/docs/examples/index.md +25 -0
  68. ninjastack-0.1.0/docs/getting-started/concepts.md +73 -0
  69. ninjastack-0.1.0/docs/getting-started/index.md +15 -0
  70. ninjastack-0.1.0/docs/getting-started/installation.md +48 -0
  71. ninjastack-0.1.0/docs/getting-started/quickstart.md +75 -0
  72. ninjastack-0.1.0/docs/index.md +75 -0
  73. ninjastack-0.1.0/examples/README.md +36 -0
  74. ninjastack-0.1.0/examples/bookstore/01_schema_definition.py +216 -0
  75. ninjastack-0.1.0/examples/bookstore/02_code_generation.py +85 -0
  76. ninjastack-0.1.0/examples/bookstore/03_data_agents.py +99 -0
  77. ninjastack-0.1.0/examples/bookstore/04_domain_agents.py +147 -0
  78. ninjastack-0.1.0/examples/bookstore/05_auth_rbac.py +184 -0
  79. ninjastack-0.1.0/examples/bookstore/06_end_to_end.py +189 -0
  80. ninjastack-0.1.0/examples/bookstore/_bookstore_schema.py +145 -0
  81. ninjastack-0.1.0/implementation_plans/000_setup_assistant.md +44 -0
  82. ninjastack-0.1.0/implementation_plans/001_polyglot_introspection.md +42 -0
  83. ninjastack-0.1.0/implementation_plans/002_asd_core_models.md +59 -0
  84. ninjastack-0.1.0/implementation_plans/003_code_generation_sync_engine.md +57 -0
  85. ninjastack-0.1.0/implementation_plans/004_unified_persistence_layer.md +69 -0
  86. ninjastack-0.1.0/implementation_plans/005_graph_rag_bootstrapper.md +59 -0
  87. ninjastack-0.1.0/implementation_plans/006_data_tolerance_boundary_layer.md +55 -0
  88. ninjastack-0.1.0/implementation_plans/007_auth_gateway.md +66 -0
  89. ninjastack-0.1.0/implementation_plans/008_graphql_layer_generation.md +50 -0
  90. ninjastack-0.1.0/implementation_plans/009_ui_generation.md +57 -0
  91. ninjastack-0.1.0/implementation_plans/010_deployment_k8s_helm.md +48 -0
  92. ninjastack-0.1.0/implementation_plans/011_litellm_model_integration.md +60 -0
  93. ninjastack-0.1.0/implementation_plans/012_monorepo_build_system.md +67 -0
  94. ninjastack-0.1.0/implementation_plans/013_agent_orchestration_adk.md +80 -0
  95. ninjastack-0.1.0/libs/ninja-agents/pyproject.toml +18 -0
  96. ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/__init__.py +23 -0
  97. ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/base.py +288 -0
  98. ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/orchestrator.py +108 -0
  99. ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/templates/__init__.py +11 -0
  100. ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/templates/coordinator_agent.yaml +19 -0
  101. ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/templates/data_agent.yaml +18 -0
  102. ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/templates/domain_agent.yaml +18 -0
  103. ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/tools.py +88 -0
  104. ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/tracing.py +162 -0
  105. ninjastack-0.1.0/libs/ninja-agents/tests/conftest.py +64 -0
  106. ninjastack-0.1.0/libs/ninja-agents/tests/test_agents_base.py +186 -0
  107. ninjastack-0.1.0/libs/ninja-agents/tests/test_agents_imports.py +29 -0
  108. ninjastack-0.1.0/libs/ninja-agents/tests/test_agents_orchestrator.py +91 -0
  109. ninjastack-0.1.0/libs/ninja-agents/tests/test_agents_tools.py +44 -0
  110. ninjastack-0.1.0/libs/ninja-agents/tests/test_agents_tracing.py +119 -0
  111. ninjastack-0.1.0/libs/ninja-auth/pyproject.toml +19 -0
  112. ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/__init__.py +53 -0
  113. ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/agent_context.py +122 -0
  114. ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/config.py +70 -0
  115. ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/context.py +31 -0
  116. ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/gateway.py +104 -0
  117. ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/rbac.py +191 -0
  118. ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/strategies/__init__.py +8 -0
  119. ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/strategies/apikey.py +44 -0
  120. ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/strategies/bearer.py +64 -0
  121. ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/strategies/identity.py +91 -0
  122. ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/strategies/oauth2.py +96 -0
  123. ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_agent_context.py +139 -0
  124. ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_apikey.py +86 -0
  125. ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_bearer.py +118 -0
  126. ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_config.py +65 -0
  127. ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_context.py +41 -0
  128. ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_gateway.py +166 -0
  129. ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_identity.py +91 -0
  130. ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_imports.py +47 -0
  131. ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_oauth2.py +122 -0
  132. ninjastack-0.1.0/libs/ninja-auth/tests/test_rbac.py +254 -0
  133. ninjastack-0.1.0/libs/ninja-auth/tests/test_rbac_agent.py +66 -0
  134. ninjastack-0.1.0/libs/ninja-auth/tests/test_rbac_config.py +74 -0
  135. ninjastack-0.1.0/libs/ninja-auth/tests/test_rbac_gateway.py +126 -0
  136. ninjastack-0.1.0/libs/ninja-boundary/pyproject.toml +16 -0
  137. ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/__init__.py +29 -0
  138. ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/audit.py +99 -0
  139. ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/boundary.py +84 -0
  140. ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/coercion.py +238 -0
  141. ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/defaults.py +89 -0
  142. ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/drift.py +86 -0
  143. ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/tuner.py +72 -0
  144. ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/validators.py +76 -0
  145. ninjastack-0.1.0/libs/ninja-boundary/tests/test_audit.py +55 -0
  146. ninjastack-0.1.0/libs/ninja-boundary/tests/test_boundary.py +159 -0
  147. ninjastack-0.1.0/libs/ninja-boundary/tests/test_coercion.py +179 -0
  148. ninjastack-0.1.0/libs/ninja-boundary/tests/test_defaults.py +87 -0
  149. ninjastack-0.1.0/libs/ninja-boundary/tests/test_drift.py +60 -0
  150. ninjastack-0.1.0/libs/ninja-boundary/tests/test_ninja_boundary_imports.py +4 -0
  151. ninjastack-0.1.0/libs/ninja-boundary/tests/test_tuner.py +59 -0
  152. ninjastack-0.1.0/libs/ninja-boundary/tests/test_validators.py +64 -0
  153. ninjastack-0.1.0/libs/ninja-cli/pyproject.toml +19 -0
  154. ninjastack-0.1.0/libs/ninja-cli/src/ninja_cli/__init__.py +14 -0
  155. ninjastack-0.1.0/libs/ninja-cli/src/ninja_cli/cli.py +105 -0
  156. ninjastack-0.1.0/libs/ninja-cli/src/ninja_cli/config.py +50 -0
  157. ninjastack-0.1.0/libs/ninja-cli/src/ninja_cli/state.py +105 -0
  158. ninjastack-0.1.0/libs/ninja-cli/tests/test_ninja_cli_commands.py +61 -0
  159. ninjastack-0.1.0/libs/ninja-cli/tests/test_ninja_cli_config.py +68 -0
  160. ninjastack-0.1.0/libs/ninja-cli/tests/test_ninja_cli_imports.py +27 -0
  161. ninjastack-0.1.0/libs/ninja-cli/tests/test_ninja_cli_state.py +106 -0
  162. ninjastack-0.1.0/libs/ninja-codegen/pyproject.toml +17 -0
  163. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/__init__.py +13 -0
  164. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/differ.py +116 -0
  165. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/engine.py +111 -0
  166. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/__init__.py +1 -0
  167. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/agents.py +124 -0
  168. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/apps.py +34 -0
  169. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/base.py +100 -0
  170. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/graphql.py +76 -0
  171. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/models.py +77 -0
  172. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/app_shell.py.j2 +30 -0
  173. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/coordinator_agent.py.j2 +34 -0
  174. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/data_agent.py.j2 +53 -0
  175. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/domain_agent.py.j2 +45 -0
  176. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/gql_type.py.j2 +78 -0
  177. ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/model.py.j2 +31 -0
  178. ninjastack-0.1.0/libs/ninja-codegen/tests/conftest.py +99 -0
  179. ninjastack-0.1.0/libs/ninja-codegen/tests/test_codegen_engine.py +142 -0
  180. ninjastack-0.1.0/libs/ninja-codegen/tests/test_differ.py +105 -0
  181. ninjastack-0.1.0/libs/ninja-codegen/tests/test_generators.py +125 -0
  182. ninjastack-0.1.0/libs/ninja-codegen/tests/test_ninja_codegen_imports.py +4 -0
  183. ninjastack-0.1.0/libs/ninja-core/pyproject.toml +13 -0
  184. ninjastack-0.1.0/libs/ninja-core/src/ninja_core/__init__.py +36 -0
  185. ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/__init__.py +30 -0
  186. ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/agent.py +38 -0
  187. ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/domain.py +21 -0
  188. ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/entity.py +92 -0
  189. ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/project.py +25 -0
  190. ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/relationship.py +42 -0
  191. ninjastack-0.1.0/libs/ninja-core/src/ninja_core/serialization/__init__.py +5 -0
  192. ninjastack-0.1.0/libs/ninja-core/src/ninja_core/serialization/io.py +44 -0
  193. ninjastack-0.1.0/libs/ninja-core/tests/test_core_imports.py +4 -0
  194. ninjastack-0.1.0/libs/ninja-core/tests/test_entity.py +126 -0
  195. ninjastack-0.1.0/libs/ninja-core/tests/test_relationship.py +168 -0
  196. ninjastack-0.1.0/libs/ninja-core/tests/test_serialization.py +188 -0
  197. ninjastack-0.1.0/libs/ninja-deploy/pyproject.toml +16 -0
  198. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/__init__.py +13 -0
  199. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/ci_generator.py +66 -0
  200. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/docker_generator.py +70 -0
  201. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/helm_generator.py +150 -0
  202. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/k8s_generator.py +118 -0
  203. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/docker/Dockerfile.j2 +39 -0
  204. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/docker/dockerignore.j2 +18 -0
  205. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/github_actions/deploy.yml.j2 +88 -0
  206. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/github_actions/test.yml.j2 +32 -0
  207. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/helm/Chart.yaml.j2 +15 -0
  208. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/helm/_helpers.tpl.j2 +35 -0
  209. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/helm/deployment.yaml.j2 +39 -0
  210. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/helm/service.yaml.j2 +15 -0
  211. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/helm/values.yaml.j2 +65 -0
  212. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/k8s/configmap.yaml.j2 +26 -0
  213. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/k8s/deployment.yaml.j2 +47 -0
  214. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/k8s/infra.yaml.j2 +39 -0
  215. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/k8s/secret.yaml.j2 +19 -0
  216. ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/k8s/service.yaml.j2 +16 -0
  217. ninjastack-0.1.0/libs/ninja-deploy/tests/conftest.py +105 -0
  218. ninjastack-0.1.0/libs/ninja-deploy/tests/test_deploy_ci.py +136 -0
  219. ninjastack-0.1.0/libs/ninja-deploy/tests/test_deploy_docker.py +110 -0
  220. ninjastack-0.1.0/libs/ninja-deploy/tests/test_deploy_helm.py +189 -0
  221. ninjastack-0.1.0/libs/ninja-deploy/tests/test_deploy_imports.py +30 -0
  222. ninjastack-0.1.0/libs/ninja-deploy/tests/test_deploy_k8s.py +222 -0
  223. ninjastack-0.1.0/libs/ninja-gql/pyproject.toml +17 -0
  224. ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/__init__.py +6 -0
  225. ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/generator.py +174 -0
  226. ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/resolvers/__init__.py +1 -0
  227. ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/resolvers/agent.py +34 -0
  228. ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/resolvers/crud.py +103 -0
  229. ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/resolvers/semantic.py +35 -0
  230. ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/schema.py +114 -0
  231. ninjastack-0.1.0/libs/ninja-gql/tests/conftest.py +85 -0
  232. ninjastack-0.1.0/libs/ninja-gql/tests/test_generator.py +82 -0
  233. ninjastack-0.1.0/libs/ninja-gql/tests/test_ninja_gql_imports.py +6 -0
  234. ninjastack-0.1.0/libs/ninja-gql/tests/test_schema.py +247 -0
  235. ninjastack-0.1.0/libs/ninja-graph/pyproject.toml +19 -0
  236. ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/__init__.py +10 -0
  237. ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/community.py +110 -0
  238. ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/linker.py +67 -0
  239. ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/loader.py +105 -0
  240. ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/mapper.py +69 -0
  241. ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/memory_backend.py +96 -0
  242. ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/protocols.py +36 -0
  243. ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/tools.py +75 -0
  244. ninjastack-0.1.0/libs/ninja-graph/tests/conftest.py +82 -0
  245. ninjastack-0.1.0/libs/ninja-graph/tests/test_community.py +90 -0
  246. ninjastack-0.1.0/libs/ninja-graph/tests/test_graph_tools.py +99 -0
  247. ninjastack-0.1.0/libs/ninja-graph/tests/test_linker.py +117 -0
  248. ninjastack-0.1.0/libs/ninja-graph/tests/test_loader.py +106 -0
  249. ninjastack-0.1.0/libs/ninja-graph/tests/test_mapper.py +91 -0
  250. ninjastack-0.1.0/libs/ninja-graph/tests/test_memory_backend.py +145 -0
  251. ninjastack-0.1.0/libs/ninja-graph/tests/test_ninja_graph_imports.py +15 -0
  252. ninjastack-0.1.0/libs/ninja-introspect/pyproject.toml +21 -0
  253. ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/__init__.py +18 -0
  254. ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/engine.py +103 -0
  255. ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/__init__.py +16 -0
  256. ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/base.py +36 -0
  257. ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/graph.py +151 -0
  258. ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/mongo.py +123 -0
  259. ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/sql.py +136 -0
  260. ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/vector.py +107 -0
  261. ninjastack-0.1.0/libs/ninja-introspect/tests/test_engine.py +154 -0
  262. ninjastack-0.1.0/libs/ninja-introspect/tests/test_graph_provider.py +181 -0
  263. ninjastack-0.1.0/libs/ninja-introspect/tests/test_mongo_provider.py +170 -0
  264. ninjastack-0.1.0/libs/ninja-introspect/tests/test_ninja_introspect_imports.py +27 -0
  265. ninjastack-0.1.0/libs/ninja-introspect/tests/test_sql_provider.py +161 -0
  266. ninjastack-0.1.0/libs/ninja-introspect/tests/test_vector_provider.py +134 -0
  267. ninjastack-0.1.0/libs/ninja-models/pyproject.toml +13 -0
  268. ninjastack-0.1.0/libs/ninja-models/src/ninja_models/__init__.py +19 -0
  269. ninjastack-0.1.0/libs/ninja-models/src/ninja_models/config.py +47 -0
  270. ninjastack-0.1.0/libs/ninja-models/src/ninja_models/cost_tracker.py +100 -0
  271. ninjastack-0.1.0/libs/ninja-models/src/ninja_models/litellm_bridge.py +151 -0
  272. ninjastack-0.1.0/libs/ninja-models/src/ninja_models/resolver.py +51 -0
  273. ninjastack-0.1.0/libs/ninja-models/tests/test_config.py +78 -0
  274. ninjastack-0.1.0/libs/ninja-models/tests/test_cost_tracker.py +77 -0
  275. ninjastack-0.1.0/libs/ninja-models/tests/test_litellm_bridge.py +143 -0
  276. ninjastack-0.1.0/libs/ninja-models/tests/test_ninja_models_imports.py +4 -0
  277. ninjastack-0.1.0/libs/ninja-models/tests/test_resolver.py +71 -0
  278. ninjastack-0.1.0/libs/ninja-persistence/pyproject.toml +24 -0
  279. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/__init__.py +25 -0
  280. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/__init__.py +1 -0
  281. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/chroma.py +112 -0
  282. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/graph.py +43 -0
  283. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/milvus.py +43 -0
  284. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/mongo.py +63 -0
  285. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/sql.py +135 -0
  286. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/connections.py +107 -0
  287. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/embedding/__init__.py +1 -0
  288. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/embedding/strategy.py +56 -0
  289. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/protocols.py +44 -0
  290. ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/registry.py +59 -0
  291. ninjastack-0.1.0/libs/ninja-persistence/tests/test_connections.py +150 -0
  292. ninjastack-0.1.0/libs/ninja-persistence/tests/test_embedding_strategy.py +116 -0
  293. ninjastack-0.1.0/libs/ninja-persistence/tests/test_ninja_persistence_imports.py +37 -0
  294. ninjastack-0.1.0/libs/ninja-persistence/tests/test_protocols.py +44 -0
  295. ninjastack-0.1.0/libs/ninja-persistence/tests/test_registry.py +69 -0
  296. ninjastack-0.1.0/libs/ninja-persistence/tests/test_sql_adapter.py +127 -0
  297. ninjastack-0.1.0/libs/ninja-test-lib/pyproject.toml +13 -0
  298. ninjastack-0.1.0/libs/ninja-test-lib/src/ninja_test_lib/__init__.py +1 -0
  299. ninjastack-0.1.0/libs/ninja-test-lib/tests/test_ninja_test_lib_imports.py +4 -0
  300. ninjastack-0.1.0/libs/ninja-ui/pyproject.toml +16 -0
  301. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/__init__.py +15 -0
  302. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/chat/__init__.py +0 -0
  303. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/chat/generator.py +50 -0
  304. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/crud/__init__.py +0 -0
  305. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/crud/generator.py +142 -0
  306. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/generator.py +59 -0
  307. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/server.py +51 -0
  308. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/shared/__init__.py +0 -0
  309. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/shared/assets.py +28 -0
  310. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/templates/base.html.j2 +50 -0
  311. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/templates/chat.html.j2 +127 -0
  312. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/templates/crud_entity.html.j2 +243 -0
  313. ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/templates/crud_index.html.j2 +16 -0
  314. ninjastack-0.1.0/libs/ninja-ui/tests/conftest.py +110 -0
  315. ninjastack-0.1.0/libs/ninja-ui/tests/test_ui_chat.py +92 -0
  316. ninjastack-0.1.0/libs/ninja-ui/tests/test_ui_crud.py +202 -0
  317. ninjastack-0.1.0/libs/ninja-ui/tests/test_ui_generator.py +60 -0
  318. ninjastack-0.1.0/libs/ninja-ui/tests/test_ui_server.py +76 -0
  319. ninjastack-0.1.0/libs/ninja-ui/tests/test_ui_shared.py +66 -0
  320. ninjastack-0.1.0/mkdocs.yml +151 -0
  321. ninjastack-0.1.0/package.json +12 -0
  322. ninjastack-0.1.0/pyproject.toml +110 -0
  323. ninjastack-0.1.0/scripts/new_app.sh +62 -0
  324. ninjastack-0.1.0/scripts/new_lib.sh +56 -0
  325. ninjastack-0.1.0/site/404.html +1892 -0
  326. ninjastack-0.1.0/site/api/agents/base/index.html +2726 -0
  327. ninjastack-0.1.0/site/api/agents/orchestrator/index.html +2528 -0
  328. ninjastack-0.1.0/site/api/agents/tools/index.html +2252 -0
  329. ninjastack-0.1.0/site/api/agents/tracing/index.html +2408 -0
  330. ninjastack-0.1.0/site/api/auth/context/index.html +2136 -0
  331. ninjastack-0.1.0/site/api/auth/gateway/index.html +2240 -0
  332. ninjastack-0.1.0/site/api/auth/rbac/index.html +2826 -0
  333. ninjastack-0.1.0/site/api/auth/strategies/index.html +3759 -0
  334. ninjastack-0.1.0/site/api/codegen/engine/index.html +2529 -0
  335. ninjastack-0.1.0/site/api/codegen/generators/index.html +3944 -0
  336. ninjastack-0.1.0/site/api/core/agent-config/index.html +2206 -0
  337. ninjastack-0.1.0/site/api/core/domain/index.html +2136 -0
  338. ninjastack-0.1.0/site/api/core/entity/index.html +2360 -0
  339. ninjastack-0.1.0/site/api/core/project/index.html +2137 -0
  340. ninjastack-0.1.0/site/api/core/relationship/index.html +2276 -0
  341. ninjastack-0.1.0/site/api/graphql/index.html +2773 -0
  342. ninjastack-0.1.0/site/api/index.html +2039 -0
  343. ninjastack-0.1.0/site/api/introspect/index.html +3617 -0
  344. ninjastack-0.1.0/site/api/persistence/index.html +6537 -0
  345. ninjastack-0.1.0/site/architecture/agent-hierarchy/index.html +2191 -0
  346. ninjastack-0.1.0/site/architecture/asd/index.html +2344 -0
  347. ninjastack-0.1.0/site/architecture/auth-rbac/index.html +2364 -0
  348. ninjastack-0.1.0/site/architecture/codegen/index.html +2271 -0
  349. ninjastack-0.1.0/site/architecture/index.html +2102 -0
  350. ninjastack-0.1.0/site/architecture/persistence/index.html +2149 -0
  351. ninjastack-0.1.0/site/assets/_mkdocstrings.css +237 -0
  352. ninjastack-0.1.0/site/assets/images/favicon.png +0 -0
  353. ninjastack-0.1.0/site/assets/javascripts/bundle.79ae519e.min.js +16 -0
  354. ninjastack-0.1.0/site/assets/javascripts/bundle.79ae519e.min.js.map +7 -0
  355. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ar.min.js +1 -0
  356. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.da.min.js +18 -0
  357. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.de.min.js +18 -0
  358. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.du.min.js +18 -0
  359. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.el.min.js +1 -0
  360. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.es.min.js +18 -0
  361. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.fi.min.js +18 -0
  362. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.fr.min.js +18 -0
  363. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.he.min.js +1 -0
  364. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.hi.min.js +1 -0
  365. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.hu.min.js +18 -0
  366. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.hy.min.js +1 -0
  367. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.it.min.js +18 -0
  368. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ja.min.js +1 -0
  369. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.jp.min.js +1 -0
  370. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.kn.min.js +1 -0
  371. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ko.min.js +1 -0
  372. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.multi.min.js +1 -0
  373. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.nl.min.js +18 -0
  374. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.no.min.js +18 -0
  375. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.pt.min.js +18 -0
  376. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ro.min.js +18 -0
  377. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ru.min.js +18 -0
  378. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.sa.min.js +1 -0
  379. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +1 -0
  380. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.sv.min.js +18 -0
  381. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ta.min.js +1 -0
  382. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.te.min.js +1 -0
  383. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.th.min.js +1 -0
  384. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.tr.min.js +18 -0
  385. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.vi.min.js +1 -0
  386. ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.zh.min.js +1 -0
  387. ninjastack-0.1.0/site/assets/javascripts/lunr/tinyseg.js +206 -0
  388. ninjastack-0.1.0/site/assets/javascripts/lunr/wordcut.js +6708 -0
  389. ninjastack-0.1.0/site/assets/javascripts/workers/search.2c215733.min.js +42 -0
  390. ninjastack-0.1.0/site/assets/javascripts/workers/search.2c215733.min.js.map +7 -0
  391. ninjastack-0.1.0/site/assets/stylesheets/main.484c7ddc.min.css +1 -0
  392. ninjastack-0.1.0/site/assets/stylesheets/main.484c7ddc.min.css.map +1 -0
  393. ninjastack-0.1.0/site/assets/stylesheets/palette.ab4e12ef.min.css +1 -0
  394. ninjastack-0.1.0/site/assets/stylesheets/palette.ab4e12ef.min.css.map +1 -0
  395. ninjastack-0.1.0/site/examples/01-schema/index.html +2257 -0
  396. ninjastack-0.1.0/site/examples/02-codegen/index.html +2096 -0
  397. ninjastack-0.1.0/site/examples/03-data-agents/index.html +2110 -0
  398. ninjastack-0.1.0/site/examples/04-domain-agents/index.html +2158 -0
  399. ninjastack-0.1.0/site/examples/05-auth-rbac/index.html +2195 -0
  400. ninjastack-0.1.0/site/examples/06-end-to-end/index.html +2198 -0
  401. ninjastack-0.1.0/site/examples/index.html +2008 -0
  402. ninjastack-0.1.0/site/getting-started/concepts/index.html +2282 -0
  403. ninjastack-0.1.0/site/getting-started/index.html +1972 -0
  404. ninjastack-0.1.0/site/getting-started/installation/index.html +2126 -0
  405. ninjastack-0.1.0/site/getting-started/quickstart/index.html +2175 -0
  406. ninjastack-0.1.0/site/index.html +577 -0
  407. ninjastack-0.1.0/site/objects.inv +0 -0
  408. ninjastack-0.1.0/site/search/search_index.json +1 -0
  409. ninjastack-0.1.0/site/sitemap.xml +155 -0
  410. ninjastack-0.1.0/site/sitemap.xml.gz +0 -0
  411. ninjastack-0.1.0/tools/review_pr.sh +25 -0
  412. ninjastack-0.1.0/uv.lock +4942 -0
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ # Get staged .py files
5
+ STAGED=$(git diff --cached --name-only --diff-filter=ACM | grep '\.py$' || true)
6
+
7
+ if [ -n "$STAGED" ]; then
8
+ echo "🔧 Running ruff fix + format on staged Python files..."
9
+ echo "$STAGED" | xargs uv run ruff check --fix --quiet
10
+ echo "$STAGED" | xargs uv run ruff format --quiet
11
+ echo "$STAGED" | xargs git add
12
+ fi
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ echo "🧪 Running tests before push..."
5
+ make test
6
+
7
+ if [ $? -ne 0 ]; then
8
+ echo "❌ Tests failed. Push blocked."
9
+ exit 1
10
+ fi
11
+
12
+ echo "✅ All tests passed."
@@ -0,0 +1,16 @@
1
+ ## What
2
+ Closes #
3
+
4
+ ## Changes
5
+ -
6
+
7
+ ## Testing
8
+ - [ ] All existing tests pass (`make test`)
9
+ - [ ] New tests added for new functionality
10
+ - [ ] Coverage maintained above 85%
11
+
12
+ ## Checklist
13
+ - [ ] Branch based on latest `main`
14
+ - [ ] Conventional commit messages
15
+ - [ ] No new linting warnings (`make lint`)
16
+ - [ ] No business logic in `apps/` — all logic in `libs/`
@@ -0,0 +1,102 @@
1
+ """Planning Agent — generates implementation plans for GitHub issues."""
2
+
3
+ import json
4
+ import os
5
+ import urllib.request
6
+
7
+
8
+ def main():
9
+ issue_title = os.environ.get("ISSUE_TITLE", "")
10
+ issue_body = os.environ.get("ISSUE_BODY", "")
11
+
12
+ with open("/tmp/repo_files.txt") as f:
13
+ repo_structure = f.read()
14
+ with open("/tmp/relevant_code.md") as f:
15
+ relevant_code = f.read()[:40000]
16
+ with open("/tmp/triage_comment.txt") as f:
17
+ triage_analysis = f.read()
18
+
19
+ prompt = f"""You are a principal software engineer creating an implementation plan for a GitHub issue in the NinjaStack monorepo — a schema-first agentic backend framework (Python, Google ADK, Pydantic, pytest).
20
+
21
+ ## Issue
22
+ **Title:** {issue_title}
23
+ **Body:** {issue_body}
24
+
25
+ ## Prior Triage Analysis
26
+ {triage_analysis}
27
+
28
+ ## Repo Structure
29
+ {repo_structure}
30
+
31
+ ## Relevant Source Code
32
+ {relevant_code}
33
+
34
+ ## Your Task
35
+ Create a detailed, actionable implementation plan. Be specific about file paths, function signatures, and test cases.
36
+
37
+ Respond in this exact markdown format:
38
+
39
+ ### 📋 Implementation Plan
40
+
41
+ #### Objective
42
+ (what this change accomplishes)
43
+
44
+ #### Approach
45
+ (high-level strategy — 2-3 sentences)
46
+
47
+ #### Changes
48
+
49
+ **1. `path/to/file.py`**
50
+ - What to change and why
51
+ - Specific functions/classes affected
52
+
53
+ **2. `path/to/another.py`**
54
+ - ...
55
+
56
+ #### New Files (if any)
57
+ - `path/to/new_file.py` — purpose
58
+
59
+ #### Test Plan
60
+ - [ ] Test case 1 — description
61
+ - [ ] Test case 2 — description
62
+ - Where tests should live: `libs/xxx/tests/test_xxx.py`
63
+
64
+ #### Acceptance Criteria
65
+ - [ ] Criterion 1
66
+ - [ ] Criterion 2
67
+ - [ ] All existing tests pass
68
+ - [ ] New tests added and passing
69
+
70
+ #### Risk Assessment
71
+ **Risk:** Low / Medium / High
72
+ **Breaking changes:** Yes / No
73
+ **Migration needed:** Yes / No
74
+ """
75
+
76
+ body = json.dumps({
77
+ "model": "gpt-5.2",
78
+ "messages": [{"role": "user", "content": prompt}],
79
+ "max_completion_tokens": 3000,
80
+ "temperature": 0.2,
81
+ }).encode()
82
+
83
+ req = urllib.request.Request(
84
+ "https://api.openai.com/v1/chat/completions",
85
+ data=body,
86
+ headers={
87
+ "Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}",
88
+ "Content-Type": "application/json",
89
+ },
90
+ )
91
+ resp = urllib.request.urlopen(req)
92
+ result = json.loads(resp.read())
93
+ plan = result["choices"][0]["message"]["content"]
94
+
95
+ with open("/tmp/plan.md", "w") as f:
96
+ f.write(plan)
97
+
98
+ print("Plan generated.")
99
+
100
+
101
+ if __name__ == "__main__":
102
+ main()
@@ -0,0 +1,105 @@
1
+ """Triage Agent — analyzes GitHub issues against the codebase."""
2
+
3
+ import json
4
+ import os
5
+ import sys
6
+ import urllib.request
7
+
8
+
9
+ def main():
10
+ issue_title = os.environ.get("ISSUE_TITLE", "")
11
+ issue_body = os.environ.get("ISSUE_BODY", "")
12
+ labels = os.environ.get("ISSUE_LABELS", "")
13
+
14
+ with open("/tmp/context.md") as f:
15
+ repo_structure = f.read()
16
+ with open("/tmp/relevant_code.md") as f:
17
+ relevant_code = f.read()[:30000]
18
+ with open("/tmp/test_output.txt") as f:
19
+ test_output = f.read()
20
+
21
+ is_bug = "bug" in labels.lower()
22
+
23
+ task = (
24
+ "This is a BUG report. Identify the likely root cause, affected files, and whether existing tests cover this area."
25
+ if is_bug
26
+ else "This is a FEATURE/ENHANCEMENT request. Assess feasibility, identify affected components, and flag any architectural conflicts."
27
+ )
28
+
29
+ rc_or_feasibility = "Root Cause" if is_bug else "Feasibility Assessment"
30
+
31
+ prompt = f"""You are a senior software engineer triaging a GitHub issue for the NinjaStack monorepo — a schema-first agentic backend framework.
32
+
33
+ ## Issue
34
+ **Title:** {issue_title}
35
+ **Body:** {issue_body}
36
+ **Labels:** {labels}
37
+
38
+ ## Repo Structure
39
+ {repo_structure}
40
+
41
+ ## Relevant Code
42
+ {relevant_code}
43
+
44
+ ## Test Results
45
+ {test_output}
46
+
47
+ ## Your Task
48
+ {task}
49
+
50
+ Respond in this exact markdown format:
51
+
52
+ ### 🔍 Triage Analysis
53
+
54
+ **Type:** Bug / Feature / Question / Invalid
55
+ **Confidence:** High / Medium / Low
56
+ **Recommendation:** `planning` or `wontfix`
57
+
58
+ #### Summary
59
+ (1-2 sentence summary of your findings)
60
+
61
+ #### {rc_or_feasibility}
62
+ (detailed analysis)
63
+
64
+ #### Affected Files
65
+ - `path/to/file.py` — reason
66
+
67
+ #### Test Coverage
68
+ (are there existing tests? what gaps exist?)
69
+
70
+ #### Suggested Approach
71
+ (brief implementation direction if recommending `planning`)
72
+ """
73
+
74
+ body = json.dumps({
75
+ "model": "gpt-5.2",
76
+ "messages": [{"role": "user", "content": prompt}],
77
+ "max_completion_tokens": 2000,
78
+ "temperature": 0.2,
79
+ }).encode()
80
+
81
+ req = urllib.request.Request(
82
+ "https://api.openai.com/v1/chat/completions",
83
+ data=body,
84
+ headers={
85
+ "Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}",
86
+ "Content-Type": "application/json",
87
+ },
88
+ )
89
+ try:
90
+ resp = urllib.request.urlopen(req)
91
+ except urllib.request.HTTPError as e:
92
+ error_body = e.read().decode()
93
+ print(f"OpenAI API error {e.code}: {error_body}", file=sys.stderr)
94
+ sys.exit(1)
95
+ result = json.loads(resp.read())
96
+ analysis = result["choices"][0]["message"]["content"]
97
+
98
+ with open("/tmp/analysis.md", "w") as f:
99
+ f.write(analysis)
100
+
101
+ print("Analysis complete.")
102
+
103
+
104
+ if __name__ == "__main__":
105
+ main()
@@ -0,0 +1,37 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ lint-and-test:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.12"
21
+
22
+ - uses: astral-sh/setup-uv@v6
23
+ with:
24
+ enable-cache: true
25
+ cache-dependency-glob: uv.lock
26
+
27
+ - name: Install dependencies
28
+ run: uv sync
29
+
30
+ - name: Lint
31
+ run: uv run ruff check .
32
+
33
+ - name: Format check
34
+ run: uv run ruff format --check .
35
+
36
+ - name: Test
37
+ run: uv run pytest libs/ apps/ -v --tb=short --cov --cov-report=term-missing
@@ -0,0 +1,46 @@
1
+ name: Deploy Site & Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths: ['site/**', 'docs/**', 'mkdocs.yml']
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+ pages: write
12
+ id-token: write
13
+
14
+ concurrency:
15
+ group: pages
16
+ cancel-in-progress: false
17
+
18
+ jobs:
19
+ deploy:
20
+ environment:
21
+ name: github-pages
22
+ url: ${{ steps.deployment.outputs.page_url }}
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+
27
+ - name: Setup Python
28
+ uses: actions/setup-python@v5
29
+ with:
30
+ python-version: '3.12'
31
+
32
+ - name: Install uv
33
+ uses: astral-sh/setup-uv@v5
34
+
35
+ - name: Install dependencies
36
+ run: uv sync --frozen
37
+
38
+ - name: Build docs
39
+ run: uv run mkdocs build
40
+
41
+ - uses: actions/configure-pages@v5
42
+ - uses: actions/upload-pages-artifact@v3
43
+ with:
44
+ path: site
45
+ - id: deployment
46
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,72 @@
1
+ name: Planning Agent
2
+
3
+ on:
4
+ issues:
5
+ types: [labeled]
6
+
7
+ jobs:
8
+ plan:
9
+ if: github.event.label.name == 'planning'
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ issues: write
13
+ contents: read
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Gather context
19
+ env:
20
+ ISSUE_TITLE: ${{ github.event.issue.title }}
21
+ ISSUE_BODY: ${{ github.event.issue.body }}
22
+ run: |
23
+ find libs apps -type f -name "*.py" | head -200 > /tmp/repo_files.txt
24
+ echo "" > /tmp/relevant_code.md
25
+ keywords=$(echo "$ISSUE_TITLE $ISSUE_BODY" | tr '[:upper:]' '[:lower:]' | grep -oE '[a-z_]{4,}' | sort -u | head -15)
26
+ for kw in $keywords; do
27
+ matches=$(grep -rl --include="*.py" "$kw" libs/ apps/ 2>/dev/null | head -3)
28
+ for f in $matches; do
29
+ echo "" >> /tmp/relevant_code.md
30
+ echo "### $f" >> /tmp/relevant_code.md
31
+ cat "$f" >> /tmp/relevant_code.md
32
+ done
33
+ done
34
+ head -c 40000 /tmp/relevant_code.md > /tmp/rc_trimmed.md
35
+ mv /tmp/rc_trimmed.md /tmp/relevant_code.md
36
+ echo "" > /tmp/triage_comment.txt
37
+
38
+ - name: Fetch triage analysis comment
39
+ uses: actions/github-script@v7
40
+ with:
41
+ script: |
42
+ const fs = require('fs');
43
+ const comments = await github.rest.issues.listComments({
44
+ owner: context.repo.owner,
45
+ repo: context.repo.repo,
46
+ issue_number: context.issue.number
47
+ });
48
+ const triageComment = comments.data.find(c => c.body.includes('Triage Agent'));
49
+ if (triageComment) {
50
+ fs.writeFileSync('/tmp/triage_comment.txt', triageComment.body);
51
+ }
52
+
53
+ - name: Generate plan with GPT 5.2
54
+ env:
55
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
56
+ ISSUE_TITLE: ${{ github.event.issue.title }}
57
+ ISSUE_BODY: ${{ github.event.issue.body }}
58
+ run: python .github/scripts/planning_generate.py
59
+
60
+ - name: Post plan comment
61
+ uses: actions/github-script@v7
62
+ with:
63
+ script: |
64
+ const fs = require('fs');
65
+ const plan = fs.readFileSync('/tmp/plan.md', 'utf8');
66
+ const body = `## 🤖 Planning Agent\n\n${plan}\n\n---\n_React with 👍 to approve, or comment \`/approve\` to move to \`todo\`._`;
67
+ await github.rest.issues.createComment({
68
+ owner: context.repo.owner,
69
+ repo: context.repo.repo,
70
+ issue_number: context.issue.number,
71
+ body
72
+ });
@@ -0,0 +1,51 @@
1
+ name: Planning Approval
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+
7
+ jobs:
8
+ check-reaction:
9
+ # Only trigger on reactions to planning agent comments
10
+ # We use a polling approach since GitHub doesn't have a native reaction event for issue comments
11
+ if: false # Disabled — using workflow_dispatch polling instead
12
+ runs-on: ubuntu-latest
13
+ steps: []
14
+
15
+ # Alternative: maintainer comments /approve
16
+ approve:
17
+ if: >-
18
+ github.event.comment.body == '/approve' &&
19
+ (github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'MEMBER')
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ issues: write
23
+ steps:
24
+ - name: Move to todo
25
+ uses: actions/github-script@v7
26
+ with:
27
+ script: |
28
+ const issue = context.issue.number;
29
+ const owner = context.repo.owner;
30
+ const repo = context.repo.repo;
31
+
32
+ // Remove planning label
33
+ try {
34
+ await github.rest.issues.removeLabel({ owner, repo, issue_number: issue, name: 'planning' });
35
+ } catch (e) {}
36
+
37
+ // Add todo label
38
+ await github.rest.issues.addLabels({ owner, repo, issue_number: issue, labels: ['todo'] });
39
+
40
+ // Acknowledge
41
+ await github.rest.reactions.createForIssueComment({
42
+ owner, repo,
43
+ comment_id: context.payload.comment.id,
44
+ content: '+1'
45
+ });
46
+
47
+ await github.rest.issues.createComment({
48
+ owner, repo,
49
+ issue_number: issue,
50
+ body: '✅ Plan approved. Issue moved to `todo` — ready for implementation.'
51
+ });
@@ -0,0 +1,43 @@
1
+ # Simple workflow for deploying static content to GitHub Pages
2
+ name: Deploy static content to Pages
3
+
4
+ on:
5
+ # Runs on pushes targeting the default branch
6
+ push:
7
+ branches: ["main"]
8
+
9
+ # Allows you to run this workflow manually from the Actions tab
10
+ workflow_dispatch:
11
+
12
+ # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13
+ permissions:
14
+ contents: read
15
+ pages: write
16
+ id-token: write
17
+
18
+ # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
19
+ # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
20
+ concurrency:
21
+ group: "pages"
22
+ cancel-in-progress: false
23
+
24
+ jobs:
25
+ # Single deploy job since we're just deploying
26
+ deploy:
27
+ environment:
28
+ name: github-pages
29
+ url: ${{ steps.deployment.outputs.page_url }}
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - name: Checkout
33
+ uses: actions/checkout@v4
34
+ - name: Setup Pages
35
+ uses: actions/configure-pages@v5
36
+ - name: Upload artifact
37
+ uses: actions/upload-pages-artifact@v3
38
+ with:
39
+ # Upload entire repository
40
+ path: './site'
41
+ - name: Deploy to GitHub Pages
42
+ id: deployment
43
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,78 @@
1
+ name: Triage Agent
2
+
3
+ on:
4
+ issues:
5
+ types: [labeled]
6
+
7
+ jobs:
8
+ analyze:
9
+ if: github.event.label.name == 'triage'
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ issues: write
13
+ contents: read
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.12"
22
+
23
+ - name: Install dependencies
24
+ run: |
25
+ pip install uv
26
+ uv sync
27
+
28
+ - name: Generate repo structure
29
+ run: |
30
+ find libs apps -type f -name "*.py" | head -200 > /tmp/repo_files.txt
31
+ echo "## Repo Structure" > /tmp/context.md
32
+ cat /tmp/repo_files.txt >> /tmp/context.md
33
+
34
+ - name: Search codebase for relevant files
35
+ env:
36
+ ISSUE_TITLE: ${{ github.event.issue.title }}
37
+ ISSUE_BODY: ${{ github.event.issue.body }}
38
+ run: |
39
+ echo "## Relevant Code Snippets" > /tmp/relevant_code.md
40
+ keywords=$(echo "$ISSUE_TITLE $ISSUE_BODY" | tr '[:upper:]' '[:lower:]' | grep -oE '[a-z_]{4,}' | sort -u | head -15)
41
+ for kw in $keywords; do
42
+ matches=$(grep -rl --include="*.py" "$kw" libs/ apps/ 2>/dev/null | head -5)
43
+ for f in $matches; do
44
+ echo "" >> /tmp/relevant_code.md
45
+ echo "### $f" >> /tmp/relevant_code.md
46
+ head -100 "$f" >> /tmp/relevant_code.md
47
+ done
48
+ done
49
+ head -c 30000 /tmp/relevant_code.md > /tmp/rc_trimmed.md
50
+ mv /tmp/rc_trimmed.md /tmp/relevant_code.md
51
+
52
+ - name: Run tests
53
+ continue-on-error: true
54
+ run: |
55
+ source .venv/bin/activate
56
+ python -m pytest --tb=short 2>&1 | tail -50 > /tmp/test_output.txt
57
+
58
+ - name: Analyze with GPT 5.2
59
+ env:
60
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
61
+ ISSUE_TITLE: ${{ github.event.issue.title }}
62
+ ISSUE_BODY: ${{ github.event.issue.body }}
63
+ ISSUE_LABELS: ${{ join(github.event.issue.labels.*.name, ', ') }}
64
+ run: python .github/scripts/triage_analyze.py
65
+
66
+ - name: Post analysis comment
67
+ uses: actions/github-script@v7
68
+ with:
69
+ script: |
70
+ const fs = require('fs');
71
+ const analysis = fs.readFileSync('/tmp/analysis.md', 'utf8');
72
+ const body = `## 🤖 Triage Agent\n\n${analysis}\n\n---\n_Automated analysis by NinjaStack Triage Agent. A maintainer will review and label accordingly._`;
73
+ await github.rest.issues.createComment({
74
+ owner: context.repo.owner,
75
+ repo: context.repo.repo,
76
+ issue_number: context.issue.number,
77
+ body
78
+ });
@@ -0,0 +1,23 @@
1
+ name: Issue Triage
2
+
3
+ on:
4
+ issues:
5
+ types: [opened]
6
+
7
+ jobs:
8
+ triage:
9
+ if: github.actor != 'codeninja'
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ issues: write
13
+ steps:
14
+ - name: Add triage label
15
+ uses: actions/github-script@v7
16
+ with:
17
+ script: |
18
+ await github.rest.issues.addLabels({
19
+ owner: context.repo.owner,
20
+ repo: context.repo.repo,
21
+ issue_number: context.issue.number,
22
+ labels: ['triage']
23
+ });
@@ -0,0 +1,43 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ *.egg
7
+ dist/
8
+ build/
9
+ .venv/
10
+ .eggs/
11
+
12
+ # Testing / Coverage
13
+ .coverage
14
+ htmlcov/
15
+ .pytest_cache/
16
+ .mypy_cache/
17
+
18
+ # Node
19
+ node_modules/
20
+
21
+ # Environment
22
+ .env
23
+ .env.local
24
+ .env.*.local
25
+
26
+ # IDE
27
+ .vscode/
28
+ .idea/
29
+ *.swp
30
+ *.swo
31
+ *~
32
+
33
+ # OS
34
+ .DS_Store
35
+ Thumbs.db
36
+
37
+ # Ninja Stack (secrets in state)
38
+ .ninjastack/connections.json
39
+ .ninjastack/auth.json
40
+
41
+ # Build artifacts
42
+ *.whl
43
+ site/docs/
@@ -0,0 +1 @@
1
+ v22
@@ -0,0 +1 @@
1
+ 3.12