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.
- ninjastack-0.1.0/.githooks/pre-commit +12 -0
- ninjastack-0.1.0/.githooks/pre-push +12 -0
- ninjastack-0.1.0/.github/pull_request_template.md +16 -0
- ninjastack-0.1.0/.github/scripts/planning_generate.py +102 -0
- ninjastack-0.1.0/.github/scripts/triage_analyze.py +105 -0
- ninjastack-0.1.0/.github/workflows/ci.yml +37 -0
- ninjastack-0.1.0/.github/workflows/pages.yml +46 -0
- ninjastack-0.1.0/.github/workflows/planning-agent.yml +72 -0
- ninjastack-0.1.0/.github/workflows/planning-approve.yml +51 -0
- ninjastack-0.1.0/.github/workflows/static.yml +43 -0
- ninjastack-0.1.0/.github/workflows/triage-agent.yml +78 -0
- ninjastack-0.1.0/.github/workflows/triage.yml +23 -0
- ninjastack-0.1.0/.gitignore +43 -0
- ninjastack-0.1.0/.nvmrc +1 -0
- ninjastack-0.1.0/.python-version +1 -0
- ninjastack-0.1.0/CLAUDE.md +116 -0
- ninjastack-0.1.0/Makefile +36 -0
- ninjastack-0.1.0/PKG-INFO +262 -0
- ninjastack-0.1.0/README.md +230 -0
- ninjastack-0.1.0/apps/ninja-api/pyproject.toml +17 -0
- ninjastack-0.1.0/apps/ninja-api/src/ninja_api/__init__.py +1 -0
- ninjastack-0.1.0/apps/ninja-setup-assistant/pyproject.toml +25 -0
- ninjastack-0.1.0/apps/ninja-setup-assistant/src/ninja_setup_assistant/__init__.py +6 -0
- ninjastack-0.1.0/apps/ninja-setup-assistant/src/ninja_setup_assistant/assistant.py +129 -0
- ninjastack-0.1.0/apps/ninja-setup-assistant/src/ninja_setup_assistant/prompts.py +74 -0
- ninjastack-0.1.0/apps/ninja-setup-assistant/src/ninja_setup_assistant/runner.py +148 -0
- ninjastack-0.1.0/apps/ninja-setup-assistant/src/ninja_setup_assistant/tools.py +338 -0
- ninjastack-0.1.0/apps/ninja-setup-assistant/tests/test_assistant.py +118 -0
- ninjastack-0.1.0/apps/ninja-setup-assistant/tests/test_prompts.py +38 -0
- ninjastack-0.1.0/apps/ninja-setup-assistant/tests/test_runner.py +24 -0
- ninjastack-0.1.0/apps/ninja-setup-assistant/tests/test_tools.py +322 -0
- ninjastack-0.1.0/apps/ninja-test-app/pyproject.toml +17 -0
- ninjastack-0.1.0/apps/ninja-test-app/src/ninja_test_app/__init__.py +1 -0
- ninjastack-0.1.0/apps/ninja-test-app/tests/test_ninja_test_app_imports.py +4 -0
- ninjastack-0.1.0/docs/api/agents/base.md +10 -0
- ninjastack-0.1.0/docs/api/agents/orchestrator.md +1 -0
- ninjastack-0.1.0/docs/api/agents/tools.md +1 -0
- ninjastack-0.1.0/docs/api/agents/tracing.md +1 -0
- ninjastack-0.1.0/docs/api/auth/context.md +1 -0
- ninjastack-0.1.0/docs/api/auth/gateway.md +1 -0
- ninjastack-0.1.0/docs/api/auth/rbac.md +1 -0
- ninjastack-0.1.0/docs/api/auth/strategies.md +13 -0
- ninjastack-0.1.0/docs/api/codegen/engine.md +1 -0
- ninjastack-0.1.0/docs/api/codegen/generators.md +13 -0
- ninjastack-0.1.0/docs/api/core/agent-config.md +1 -0
- ninjastack-0.1.0/docs/api/core/domain.md +1 -0
- ninjastack-0.1.0/docs/api/core/entity.md +1 -0
- ninjastack-0.1.0/docs/api/core/project.md +1 -0
- ninjastack-0.1.0/docs/api/core/relationship.md +1 -0
- ninjastack-0.1.0/docs/api/graphql/index.md +5 -0
- ninjastack-0.1.0/docs/api/index.md +32 -0
- ninjastack-0.1.0/docs/api/introspect/index.md +5 -0
- ninjastack-0.1.0/docs/api/persistence/index.md +5 -0
- ninjastack-0.1.0/docs/architecture/agent-hierarchy.md +94 -0
- ninjastack-0.1.0/docs/architecture/asd.md +165 -0
- ninjastack-0.1.0/docs/architecture/auth-rbac.md +124 -0
- ninjastack-0.1.0/docs/architecture/codegen.md +95 -0
- ninjastack-0.1.0/docs/architecture/index.md +71 -0
- ninjastack-0.1.0/docs/architecture/persistence.md +69 -0
- ninjastack-0.1.0/docs/architecture.md +145 -0
- ninjastack-0.1.0/docs/examples/01-schema.md +21 -0
- ninjastack-0.1.0/docs/examples/02-codegen.md +13 -0
- ninjastack-0.1.0/docs/examples/03-data-agents.md +13 -0
- ninjastack-0.1.0/docs/examples/04-domain-agents.md +13 -0
- ninjastack-0.1.0/docs/examples/05-auth-rbac.md +13 -0
- ninjastack-0.1.0/docs/examples/06-end-to-end.md +13 -0
- ninjastack-0.1.0/docs/examples/index.md +25 -0
- ninjastack-0.1.0/docs/getting-started/concepts.md +73 -0
- ninjastack-0.1.0/docs/getting-started/index.md +15 -0
- ninjastack-0.1.0/docs/getting-started/installation.md +48 -0
- ninjastack-0.1.0/docs/getting-started/quickstart.md +75 -0
- ninjastack-0.1.0/docs/index.md +75 -0
- ninjastack-0.1.0/examples/README.md +36 -0
- ninjastack-0.1.0/examples/bookstore/01_schema_definition.py +216 -0
- ninjastack-0.1.0/examples/bookstore/02_code_generation.py +85 -0
- ninjastack-0.1.0/examples/bookstore/03_data_agents.py +99 -0
- ninjastack-0.1.0/examples/bookstore/04_domain_agents.py +147 -0
- ninjastack-0.1.0/examples/bookstore/05_auth_rbac.py +184 -0
- ninjastack-0.1.0/examples/bookstore/06_end_to_end.py +189 -0
- ninjastack-0.1.0/examples/bookstore/_bookstore_schema.py +145 -0
- ninjastack-0.1.0/implementation_plans/000_setup_assistant.md +44 -0
- ninjastack-0.1.0/implementation_plans/001_polyglot_introspection.md +42 -0
- ninjastack-0.1.0/implementation_plans/002_asd_core_models.md +59 -0
- ninjastack-0.1.0/implementation_plans/003_code_generation_sync_engine.md +57 -0
- ninjastack-0.1.0/implementation_plans/004_unified_persistence_layer.md +69 -0
- ninjastack-0.1.0/implementation_plans/005_graph_rag_bootstrapper.md +59 -0
- ninjastack-0.1.0/implementation_plans/006_data_tolerance_boundary_layer.md +55 -0
- ninjastack-0.1.0/implementation_plans/007_auth_gateway.md +66 -0
- ninjastack-0.1.0/implementation_plans/008_graphql_layer_generation.md +50 -0
- ninjastack-0.1.0/implementation_plans/009_ui_generation.md +57 -0
- ninjastack-0.1.0/implementation_plans/010_deployment_k8s_helm.md +48 -0
- ninjastack-0.1.0/implementation_plans/011_litellm_model_integration.md +60 -0
- ninjastack-0.1.0/implementation_plans/012_monorepo_build_system.md +67 -0
- ninjastack-0.1.0/implementation_plans/013_agent_orchestration_adk.md +80 -0
- ninjastack-0.1.0/libs/ninja-agents/pyproject.toml +18 -0
- ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/__init__.py +23 -0
- ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/base.py +288 -0
- ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/orchestrator.py +108 -0
- ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/templates/__init__.py +11 -0
- ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/templates/coordinator_agent.yaml +19 -0
- ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/templates/data_agent.yaml +18 -0
- ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/templates/domain_agent.yaml +18 -0
- ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/tools.py +88 -0
- ninjastack-0.1.0/libs/ninja-agents/src/ninja_agents/tracing.py +162 -0
- ninjastack-0.1.0/libs/ninja-agents/tests/conftest.py +64 -0
- ninjastack-0.1.0/libs/ninja-agents/tests/test_agents_base.py +186 -0
- ninjastack-0.1.0/libs/ninja-agents/tests/test_agents_imports.py +29 -0
- ninjastack-0.1.0/libs/ninja-agents/tests/test_agents_orchestrator.py +91 -0
- ninjastack-0.1.0/libs/ninja-agents/tests/test_agents_tools.py +44 -0
- ninjastack-0.1.0/libs/ninja-agents/tests/test_agents_tracing.py +119 -0
- ninjastack-0.1.0/libs/ninja-auth/pyproject.toml +19 -0
- ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/__init__.py +53 -0
- ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/agent_context.py +122 -0
- ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/config.py +70 -0
- ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/context.py +31 -0
- ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/gateway.py +104 -0
- ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/rbac.py +191 -0
- ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/strategies/__init__.py +8 -0
- ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/strategies/apikey.py +44 -0
- ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/strategies/bearer.py +64 -0
- ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/strategies/identity.py +91 -0
- ninjastack-0.1.0/libs/ninja-auth/src/ninja_auth/strategies/oauth2.py +96 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_agent_context.py +139 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_apikey.py +86 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_bearer.py +118 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_config.py +65 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_context.py +41 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_gateway.py +166 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_identity.py +91 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_imports.py +47 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_auth_oauth2.py +122 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_rbac.py +254 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_rbac_agent.py +66 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_rbac_config.py +74 -0
- ninjastack-0.1.0/libs/ninja-auth/tests/test_rbac_gateway.py +126 -0
- ninjastack-0.1.0/libs/ninja-boundary/pyproject.toml +16 -0
- ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/__init__.py +29 -0
- ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/audit.py +99 -0
- ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/boundary.py +84 -0
- ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/coercion.py +238 -0
- ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/defaults.py +89 -0
- ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/drift.py +86 -0
- ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/tuner.py +72 -0
- ninjastack-0.1.0/libs/ninja-boundary/src/ninja_boundary/validators.py +76 -0
- ninjastack-0.1.0/libs/ninja-boundary/tests/test_audit.py +55 -0
- ninjastack-0.1.0/libs/ninja-boundary/tests/test_boundary.py +159 -0
- ninjastack-0.1.0/libs/ninja-boundary/tests/test_coercion.py +179 -0
- ninjastack-0.1.0/libs/ninja-boundary/tests/test_defaults.py +87 -0
- ninjastack-0.1.0/libs/ninja-boundary/tests/test_drift.py +60 -0
- ninjastack-0.1.0/libs/ninja-boundary/tests/test_ninja_boundary_imports.py +4 -0
- ninjastack-0.1.0/libs/ninja-boundary/tests/test_tuner.py +59 -0
- ninjastack-0.1.0/libs/ninja-boundary/tests/test_validators.py +64 -0
- ninjastack-0.1.0/libs/ninja-cli/pyproject.toml +19 -0
- ninjastack-0.1.0/libs/ninja-cli/src/ninja_cli/__init__.py +14 -0
- ninjastack-0.1.0/libs/ninja-cli/src/ninja_cli/cli.py +105 -0
- ninjastack-0.1.0/libs/ninja-cli/src/ninja_cli/config.py +50 -0
- ninjastack-0.1.0/libs/ninja-cli/src/ninja_cli/state.py +105 -0
- ninjastack-0.1.0/libs/ninja-cli/tests/test_ninja_cli_commands.py +61 -0
- ninjastack-0.1.0/libs/ninja-cli/tests/test_ninja_cli_config.py +68 -0
- ninjastack-0.1.0/libs/ninja-cli/tests/test_ninja_cli_imports.py +27 -0
- ninjastack-0.1.0/libs/ninja-cli/tests/test_ninja_cli_state.py +106 -0
- ninjastack-0.1.0/libs/ninja-codegen/pyproject.toml +17 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/__init__.py +13 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/differ.py +116 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/engine.py +111 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/__init__.py +1 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/agents.py +124 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/apps.py +34 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/base.py +100 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/graphql.py +76 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/generators/models.py +77 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/app_shell.py.j2 +30 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/coordinator_agent.py.j2 +34 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/data_agent.py.j2 +53 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/domain_agent.py.j2 +45 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/gql_type.py.j2 +78 -0
- ninjastack-0.1.0/libs/ninja-codegen/src/ninja_codegen/templates/model.py.j2 +31 -0
- ninjastack-0.1.0/libs/ninja-codegen/tests/conftest.py +99 -0
- ninjastack-0.1.0/libs/ninja-codegen/tests/test_codegen_engine.py +142 -0
- ninjastack-0.1.0/libs/ninja-codegen/tests/test_differ.py +105 -0
- ninjastack-0.1.0/libs/ninja-codegen/tests/test_generators.py +125 -0
- ninjastack-0.1.0/libs/ninja-codegen/tests/test_ninja_codegen_imports.py +4 -0
- ninjastack-0.1.0/libs/ninja-core/pyproject.toml +13 -0
- ninjastack-0.1.0/libs/ninja-core/src/ninja_core/__init__.py +36 -0
- ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/__init__.py +30 -0
- ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/agent.py +38 -0
- ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/domain.py +21 -0
- ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/entity.py +92 -0
- ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/project.py +25 -0
- ninjastack-0.1.0/libs/ninja-core/src/ninja_core/schema/relationship.py +42 -0
- ninjastack-0.1.0/libs/ninja-core/src/ninja_core/serialization/__init__.py +5 -0
- ninjastack-0.1.0/libs/ninja-core/src/ninja_core/serialization/io.py +44 -0
- ninjastack-0.1.0/libs/ninja-core/tests/test_core_imports.py +4 -0
- ninjastack-0.1.0/libs/ninja-core/tests/test_entity.py +126 -0
- ninjastack-0.1.0/libs/ninja-core/tests/test_relationship.py +168 -0
- ninjastack-0.1.0/libs/ninja-core/tests/test_serialization.py +188 -0
- ninjastack-0.1.0/libs/ninja-deploy/pyproject.toml +16 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/__init__.py +13 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/ci_generator.py +66 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/docker_generator.py +70 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/helm_generator.py +150 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/k8s_generator.py +118 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/docker/Dockerfile.j2 +39 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/docker/dockerignore.j2 +18 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/github_actions/deploy.yml.j2 +88 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/github_actions/test.yml.j2 +32 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/helm/Chart.yaml.j2 +15 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/helm/_helpers.tpl.j2 +35 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/helm/deployment.yaml.j2 +39 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/helm/service.yaml.j2 +15 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/helm/values.yaml.j2 +65 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/k8s/configmap.yaml.j2 +26 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/k8s/deployment.yaml.j2 +47 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/k8s/infra.yaml.j2 +39 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/k8s/secret.yaml.j2 +19 -0
- ninjastack-0.1.0/libs/ninja-deploy/src/ninja_deploy/templates/k8s/service.yaml.j2 +16 -0
- ninjastack-0.1.0/libs/ninja-deploy/tests/conftest.py +105 -0
- ninjastack-0.1.0/libs/ninja-deploy/tests/test_deploy_ci.py +136 -0
- ninjastack-0.1.0/libs/ninja-deploy/tests/test_deploy_docker.py +110 -0
- ninjastack-0.1.0/libs/ninja-deploy/tests/test_deploy_helm.py +189 -0
- ninjastack-0.1.0/libs/ninja-deploy/tests/test_deploy_imports.py +30 -0
- ninjastack-0.1.0/libs/ninja-deploy/tests/test_deploy_k8s.py +222 -0
- ninjastack-0.1.0/libs/ninja-gql/pyproject.toml +17 -0
- ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/__init__.py +6 -0
- ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/generator.py +174 -0
- ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/resolvers/__init__.py +1 -0
- ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/resolvers/agent.py +34 -0
- ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/resolvers/crud.py +103 -0
- ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/resolvers/semantic.py +35 -0
- ninjastack-0.1.0/libs/ninja-gql/src/ninja_gql/schema.py +114 -0
- ninjastack-0.1.0/libs/ninja-gql/tests/conftest.py +85 -0
- ninjastack-0.1.0/libs/ninja-gql/tests/test_generator.py +82 -0
- ninjastack-0.1.0/libs/ninja-gql/tests/test_ninja_gql_imports.py +6 -0
- ninjastack-0.1.0/libs/ninja-gql/tests/test_schema.py +247 -0
- ninjastack-0.1.0/libs/ninja-graph/pyproject.toml +19 -0
- ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/__init__.py +10 -0
- ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/community.py +110 -0
- ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/linker.py +67 -0
- ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/loader.py +105 -0
- ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/mapper.py +69 -0
- ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/memory_backend.py +96 -0
- ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/protocols.py +36 -0
- ninjastack-0.1.0/libs/ninja-graph/src/ninja_graph/tools.py +75 -0
- ninjastack-0.1.0/libs/ninja-graph/tests/conftest.py +82 -0
- ninjastack-0.1.0/libs/ninja-graph/tests/test_community.py +90 -0
- ninjastack-0.1.0/libs/ninja-graph/tests/test_graph_tools.py +99 -0
- ninjastack-0.1.0/libs/ninja-graph/tests/test_linker.py +117 -0
- ninjastack-0.1.0/libs/ninja-graph/tests/test_loader.py +106 -0
- ninjastack-0.1.0/libs/ninja-graph/tests/test_mapper.py +91 -0
- ninjastack-0.1.0/libs/ninja-graph/tests/test_memory_backend.py +145 -0
- ninjastack-0.1.0/libs/ninja-graph/tests/test_ninja_graph_imports.py +15 -0
- ninjastack-0.1.0/libs/ninja-introspect/pyproject.toml +21 -0
- ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/__init__.py +18 -0
- ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/engine.py +103 -0
- ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/__init__.py +16 -0
- ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/base.py +36 -0
- ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/graph.py +151 -0
- ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/mongo.py +123 -0
- ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/sql.py +136 -0
- ninjastack-0.1.0/libs/ninja-introspect/src/ninja_introspect/providers/vector.py +107 -0
- ninjastack-0.1.0/libs/ninja-introspect/tests/test_engine.py +154 -0
- ninjastack-0.1.0/libs/ninja-introspect/tests/test_graph_provider.py +181 -0
- ninjastack-0.1.0/libs/ninja-introspect/tests/test_mongo_provider.py +170 -0
- ninjastack-0.1.0/libs/ninja-introspect/tests/test_ninja_introspect_imports.py +27 -0
- ninjastack-0.1.0/libs/ninja-introspect/tests/test_sql_provider.py +161 -0
- ninjastack-0.1.0/libs/ninja-introspect/tests/test_vector_provider.py +134 -0
- ninjastack-0.1.0/libs/ninja-models/pyproject.toml +13 -0
- ninjastack-0.1.0/libs/ninja-models/src/ninja_models/__init__.py +19 -0
- ninjastack-0.1.0/libs/ninja-models/src/ninja_models/config.py +47 -0
- ninjastack-0.1.0/libs/ninja-models/src/ninja_models/cost_tracker.py +100 -0
- ninjastack-0.1.0/libs/ninja-models/src/ninja_models/litellm_bridge.py +151 -0
- ninjastack-0.1.0/libs/ninja-models/src/ninja_models/resolver.py +51 -0
- ninjastack-0.1.0/libs/ninja-models/tests/test_config.py +78 -0
- ninjastack-0.1.0/libs/ninja-models/tests/test_cost_tracker.py +77 -0
- ninjastack-0.1.0/libs/ninja-models/tests/test_litellm_bridge.py +143 -0
- ninjastack-0.1.0/libs/ninja-models/tests/test_ninja_models_imports.py +4 -0
- ninjastack-0.1.0/libs/ninja-models/tests/test_resolver.py +71 -0
- ninjastack-0.1.0/libs/ninja-persistence/pyproject.toml +24 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/__init__.py +25 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/__init__.py +1 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/chroma.py +112 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/graph.py +43 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/milvus.py +43 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/mongo.py +63 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/adapters/sql.py +135 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/connections.py +107 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/embedding/__init__.py +1 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/embedding/strategy.py +56 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/protocols.py +44 -0
- ninjastack-0.1.0/libs/ninja-persistence/src/ninja_persistence/registry.py +59 -0
- ninjastack-0.1.0/libs/ninja-persistence/tests/test_connections.py +150 -0
- ninjastack-0.1.0/libs/ninja-persistence/tests/test_embedding_strategy.py +116 -0
- ninjastack-0.1.0/libs/ninja-persistence/tests/test_ninja_persistence_imports.py +37 -0
- ninjastack-0.1.0/libs/ninja-persistence/tests/test_protocols.py +44 -0
- ninjastack-0.1.0/libs/ninja-persistence/tests/test_registry.py +69 -0
- ninjastack-0.1.0/libs/ninja-persistence/tests/test_sql_adapter.py +127 -0
- ninjastack-0.1.0/libs/ninja-test-lib/pyproject.toml +13 -0
- ninjastack-0.1.0/libs/ninja-test-lib/src/ninja_test_lib/__init__.py +1 -0
- ninjastack-0.1.0/libs/ninja-test-lib/tests/test_ninja_test_lib_imports.py +4 -0
- ninjastack-0.1.0/libs/ninja-ui/pyproject.toml +16 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/__init__.py +15 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/chat/__init__.py +0 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/chat/generator.py +50 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/crud/__init__.py +0 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/crud/generator.py +142 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/generator.py +59 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/server.py +51 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/shared/__init__.py +0 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/shared/assets.py +28 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/templates/base.html.j2 +50 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/templates/chat.html.j2 +127 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/templates/crud_entity.html.j2 +243 -0
- ninjastack-0.1.0/libs/ninja-ui/src/ninja_ui/templates/crud_index.html.j2 +16 -0
- ninjastack-0.1.0/libs/ninja-ui/tests/conftest.py +110 -0
- ninjastack-0.1.0/libs/ninja-ui/tests/test_ui_chat.py +92 -0
- ninjastack-0.1.0/libs/ninja-ui/tests/test_ui_crud.py +202 -0
- ninjastack-0.1.0/libs/ninja-ui/tests/test_ui_generator.py +60 -0
- ninjastack-0.1.0/libs/ninja-ui/tests/test_ui_server.py +76 -0
- ninjastack-0.1.0/libs/ninja-ui/tests/test_ui_shared.py +66 -0
- ninjastack-0.1.0/mkdocs.yml +151 -0
- ninjastack-0.1.0/package.json +12 -0
- ninjastack-0.1.0/pyproject.toml +110 -0
- ninjastack-0.1.0/scripts/new_app.sh +62 -0
- ninjastack-0.1.0/scripts/new_lib.sh +56 -0
- ninjastack-0.1.0/site/404.html +1892 -0
- ninjastack-0.1.0/site/api/agents/base/index.html +2726 -0
- ninjastack-0.1.0/site/api/agents/orchestrator/index.html +2528 -0
- ninjastack-0.1.0/site/api/agents/tools/index.html +2252 -0
- ninjastack-0.1.0/site/api/agents/tracing/index.html +2408 -0
- ninjastack-0.1.0/site/api/auth/context/index.html +2136 -0
- ninjastack-0.1.0/site/api/auth/gateway/index.html +2240 -0
- ninjastack-0.1.0/site/api/auth/rbac/index.html +2826 -0
- ninjastack-0.1.0/site/api/auth/strategies/index.html +3759 -0
- ninjastack-0.1.0/site/api/codegen/engine/index.html +2529 -0
- ninjastack-0.1.0/site/api/codegen/generators/index.html +3944 -0
- ninjastack-0.1.0/site/api/core/agent-config/index.html +2206 -0
- ninjastack-0.1.0/site/api/core/domain/index.html +2136 -0
- ninjastack-0.1.0/site/api/core/entity/index.html +2360 -0
- ninjastack-0.1.0/site/api/core/project/index.html +2137 -0
- ninjastack-0.1.0/site/api/core/relationship/index.html +2276 -0
- ninjastack-0.1.0/site/api/graphql/index.html +2773 -0
- ninjastack-0.1.0/site/api/index.html +2039 -0
- ninjastack-0.1.0/site/api/introspect/index.html +3617 -0
- ninjastack-0.1.0/site/api/persistence/index.html +6537 -0
- ninjastack-0.1.0/site/architecture/agent-hierarchy/index.html +2191 -0
- ninjastack-0.1.0/site/architecture/asd/index.html +2344 -0
- ninjastack-0.1.0/site/architecture/auth-rbac/index.html +2364 -0
- ninjastack-0.1.0/site/architecture/codegen/index.html +2271 -0
- ninjastack-0.1.0/site/architecture/index.html +2102 -0
- ninjastack-0.1.0/site/architecture/persistence/index.html +2149 -0
- ninjastack-0.1.0/site/assets/_mkdocstrings.css +237 -0
- ninjastack-0.1.0/site/assets/images/favicon.png +0 -0
- ninjastack-0.1.0/site/assets/javascripts/bundle.79ae519e.min.js +16 -0
- ninjastack-0.1.0/site/assets/javascripts/bundle.79ae519e.min.js.map +7 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ar.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.da.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.de.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.du.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.el.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.es.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.fi.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.fr.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.he.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.hi.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.hu.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.hy.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.it.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ja.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.jp.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.kn.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ko.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.multi.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.nl.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.no.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.pt.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ro.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ru.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.sa.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.sv.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.ta.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.te.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.th.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.tr.min.js +18 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.vi.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/min/lunr.zh.min.js +1 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/tinyseg.js +206 -0
- ninjastack-0.1.0/site/assets/javascripts/lunr/wordcut.js +6708 -0
- ninjastack-0.1.0/site/assets/javascripts/workers/search.2c215733.min.js +42 -0
- ninjastack-0.1.0/site/assets/javascripts/workers/search.2c215733.min.js.map +7 -0
- ninjastack-0.1.0/site/assets/stylesheets/main.484c7ddc.min.css +1 -0
- ninjastack-0.1.0/site/assets/stylesheets/main.484c7ddc.min.css.map +1 -0
- ninjastack-0.1.0/site/assets/stylesheets/palette.ab4e12ef.min.css +1 -0
- ninjastack-0.1.0/site/assets/stylesheets/palette.ab4e12ef.min.css.map +1 -0
- ninjastack-0.1.0/site/examples/01-schema/index.html +2257 -0
- ninjastack-0.1.0/site/examples/02-codegen/index.html +2096 -0
- ninjastack-0.1.0/site/examples/03-data-agents/index.html +2110 -0
- ninjastack-0.1.0/site/examples/04-domain-agents/index.html +2158 -0
- ninjastack-0.1.0/site/examples/05-auth-rbac/index.html +2195 -0
- ninjastack-0.1.0/site/examples/06-end-to-end/index.html +2198 -0
- ninjastack-0.1.0/site/examples/index.html +2008 -0
- ninjastack-0.1.0/site/getting-started/concepts/index.html +2282 -0
- ninjastack-0.1.0/site/getting-started/index.html +1972 -0
- ninjastack-0.1.0/site/getting-started/installation/index.html +2126 -0
- ninjastack-0.1.0/site/getting-started/quickstart/index.html +2175 -0
- ninjastack-0.1.0/site/index.html +577 -0
- ninjastack-0.1.0/site/objects.inv +0 -0
- ninjastack-0.1.0/site/search/search_index.json +1 -0
- ninjastack-0.1.0/site/sitemap.xml +155 -0
- ninjastack-0.1.0/site/sitemap.xml.gz +0 -0
- ninjastack-0.1.0/tools/review_pr.sh +25 -0
- 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,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/
|
ninjastack-0.1.0/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
v22
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|