ecoportal-api-graphql 1.3.5 → 1.3.9
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.
- checksums.yaml +4 -4
- data/.ai-assistance/bridge/CLAUDE.md +338 -0
- data/.ai-assistance/bridge/archive/.gitkeep +0 -0
- data/.ai-assistance/bridge/archive/oscar-a1b2c3d-gitlab-mcp-doc-update.inbox.md +29 -0
- data/.ai-assistance/bridge/archive/oscar-a1b2c3d-gitlab-mcp-doc-update.outbox.md +18 -0
- data/.ai-assistance/bridge/archive/oscar-c912c25-gemini-design-review.inbox.md +42 -0
- data/.ai-assistance/bridge/archive/oscar-c912c25-gemini-design-review.outbox.md +115 -0
- data/.ai-assistance/bridge/context/gemini-review-prompt.txt +48 -0
- data/.ai-assistance/bridge/context/gemini-review-response.md +104 -0
- data/.ai-assistance/bridge/context/project.md +42 -0
- data/.ai-assistance/bridge/inbox/.gitkeep +0 -0
- data/.ai-assistance/bridge/outbox/.gitkeep +0 -0
- data/.ai-assistance/bridge/outbox/request-for-standards-discovery.md +48 -0
- data/.ai-assistance/bridge/queue/.gitkeep +1 -0
- data/.ai-assistance/capabilities/CLAUDE.md +27 -0
- data/.ai-assistance/capabilities/assumptions-log.md +80 -0
- data/.ai-assistance/capabilities/code.md +47 -0
- data/.ai-assistance/capabilities/connectors.md +37 -0
- data/.ai-assistance/capabilities/cowork.md +55 -0
- data/.ai-assistance/code/OVERVIEW.md +155 -0
- data/.ai-assistance/code/data_fields.md +242 -0
- data/.ai-assistance/code/dependencies.md +151 -0
- data/.ai-assistance/code/diff_as_input.md +234 -0
- data/.ai-assistance/code/diff_service_deep_dive.md +192 -0
- data/.ai-assistance/code/ecoPortal_architecture/00_overview_and_index.md +55 -0
- data/.ai-assistance/code/ecoPortal_architecture/01_terminology_dictionary.md +181 -0
- data/.ai-assistance/code/ecoPortal_architecture/02_data_model.md +192 -0
- data/.ai-assistance/code/ecoPortal_architecture/03_api_layers.md +147 -0
- data/.ai-assistance/code/ecoPortal_architecture/04_graphql_queries_mutations.md +277 -0
- data/.ai-assistance/code/ecoPortal_architecture/05_page_workflows.md +200 -0
- data/.ai-assistance/code/ecoPortal_architecture/06_search_and_filters.md +228 -0
- data/.ai-assistance/code/ecoPortal_architecture/07_data_fields.md +197 -0
- data/.ai-assistance/code/ecoPortal_architecture/08_stages_sections.md +243 -0
- data/.ai-assistance/code/ecoPortal_architecture/09_people_contractors_locations.md +196 -0
- data/.ai-assistance/code/ecoPortal_architecture/10_forces_workflow_builder.md +132 -0
- data/.ai-assistance/code/ecoPortal_architecture/11_integration_gems.md +187 -0
- data/.ai-assistance/code/ecoPortal_architecture/12_ai_documentation_sources_gaps.md +236 -0
- data/.ai-assistance/code/ecoPortal_architecture/13_ai_infrastructure.md +183 -0
- data/.ai-assistance/code/ecoportal_schema_reference.md +240 -0
- data/.ai-assistance/code/graphql_domain_knowledge.md +230 -0
- data/.ai-assistance/code/refactoring/datafield-readwrite-shape-asymmetry.md +71 -0
- data/.ai-assistance/code/refactoring/opportunities.md +251 -0
- data/.ai-assistance/code/schema_analysis.md +321 -0
- data/.ai-assistance/code/search_filters.md +868 -0
- data/.ai-assistance/code/spec_coverage.md +73 -0
- data/.ai-assistance/code/workflow-command-guide.md +438 -0
- data/.ai-assistance/code/workflow-space.md +353 -0
- data/.ai-assistance/conventions/CLAUDE.md +30 -0
- data/.ai-assistance/conventions/code-working-tree-protocol.md +199 -0
- data/.ai-assistance/conventions/gitignore-rules.md +42 -0
- data/.ai-assistance/conventions/permission-guidance.md +120 -0
- data/.ai-assistance/integrations/README.md +70 -0
- data/.ai-assistance/integrations/gitkraken-mcp.md +107 -0
- data/.ai-assistance/integrations/gitlab-mcp.md +123 -0
- data/.ai-assistance/integrations/local-git.md +60 -0
- data/.ai-assistance/local_paths.example.md +17 -0
- data/.ai-assistance/projects/TODO.md +97 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/DECISIONS.md +168 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/INTENT.md +60 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/TODO.md +267 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/UPSTREAM.md +53 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/notes/csv-template-pipeline-design.md +102 -0
- data/.ai-assistance/projects/api-v2-to-graphql-migration/notes/cutover-usecase-gap-audit.md +139 -0
- data/.ai-assistance/projects/dynamic-model-generation/INTENT.md +93 -0
- data/.ai-assistance/projects/eco-helpers-compat/INTENT.md +244 -0
- data/.ai-assistance/projects/eco-helpers-compat/MIGRATION_GUIDE.md +266 -0
- data/.ai-assistance/projects/eco-helpers-compat/TODO.md +86 -0
- data/.ai-assistance/projects/ecoportal-api-v2-doublemodel-review/INTENT.md +101 -0
- data/.ai-assistance/projects/graphql-agent/GAP_ANALYSIS.md +177 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/DECISIONS.md +161 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/INTENT.md +125 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/RISKS.md +126 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/TODO.md +256 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-06-30-cutover-workflow-deep-review.md +122 -0
- data/.ai-assistance/projects/ooze-graphql-native-migration/analysis/2026-07-01-forces-via-workflow-commands-miss-rca.md +148 -0
- data/.ai-assistance/projects/page-model/DECISIONS.md +245 -0
- data/.ai-assistance/projects/page-model/TODO.md +190 -0
- data/.ai-assistance/projects/search-filter-builder/INTENT.md +107 -0
- data/.ai-assistance/projects/search-filter-builder/TODO.md +131 -0
- data/.ai-assistance/projects/template-maintenance/DESIGN.md +134 -0
- data/.ai-assistance/projects/workflow-space/TODO.md +213 -0
- data/.ai-assistance/reinstall-claude-desktop-windows.md +136 -0
- data/.ai-assistance/scripts/CLAUDE.md +150 -0
- data/.ai-assistance/scripts/bridge-init.sh +86 -0
- data/.ai-assistance/scripts/bridge-status.sh +44 -0
- data/.ai-assistance/scripts/capabilities-check.ts +104 -0
- data/.ai-assistance/scripts/check-outbox.sh +43 -0
- data/.ai-assistance/scripts/dep_graph.rb +91 -0
- data/.ai-assistance/scripts/lock-acquire.sh +103 -0
- data/.ai-assistance/scripts/lock-multi.sh +124 -0
- data/.ai-assistance/scripts/lock-queue.sh +94 -0
- data/.ai-assistance/scripts/setup-mcps.test.ts +188 -0
- data/.ai-assistance/scripts/setup-mcps.ts +234 -0
- data/.ai-assistance/scripts/task-complete.ts +74 -0
- data/.ai-assistance/scripts/task-create.ts +75 -0
- data/.ai-assistance/scripts/task-read.ts +125 -0
- data/.ai-assistance/scripts/token-logger.js +220 -0
- data/.ai-assistance/scripts/token-report.ts +158 -0
- data/.ai-assistance/scripts/token-session-start.js +66 -0
- data/.ai-assistance/skills/ai-instructions/SKILL.md +48 -0
- data/.ai-assistance/skills/code-specs/SKILL.md +69 -0
- data/.ai-assistance/skills/corporate-policies/SKILL.md +201 -0
- data/.ai-assistance/skills/dep-graph/SKILL.md +139 -0
- data/.ai-assistance/skills/ep-ai-manager/SKILL.md +417 -0
- data/.ai-assistance/skills/gemini-assist/SKILL.md +63 -0
- data/.ai-assistance/skills/gemini-assist/gemini-mcp-server.js +205 -0
- data/.ai-assistance/skills/gemini-assist/gemini_ask.py +1 -0
- data/.ai-assistance/skills/gemini-assist/gemini_ask.rb +240 -0
- data/.ai-assistance/skills/gemini-assist/prompts/cycle_end_review.txt +25 -0
- data/.ai-assistance/skills/graphql-schema-analysis/SKILL.md +261 -0
- data/.ai-assistance/skills/project-cycle/SKILL.md +177 -0
- data/.ai-assistance/skills/refactor/SKILL.md +62 -0
- data/.ai-assistance/skills/rubocop/SKILL.md +93 -0
- data/.ai-assistance/skills/ruby-scripting/SKILL.md +215 -0
- data/.ai-assistance/skills/spec-generation/SKILL.md +72 -0
- data/.ai-assistance/standards-version.json +21 -0
- data/.ai-assistance/token-budget.json +32 -0
- data/.ai-assistance/version.json +39 -0
- data/.claude/settings.json +146 -0
- data/.env.example +18 -0
- data/.gitattributes +15 -0
- data/.gitignore +13 -0
- data/.rubocop.yml +121 -97
- data/CHANGELOG.md +673 -477
- data/CLAUDE.md +232 -0
- data/Gemfile +30 -6
- data/Rakefile +90 -38
- data/docs/worklog.md +574 -0
- data/ecoportal-api-graphql.gemspec +40 -40
- data/lib/ecoportal/api/common/graphql/CLAUDE.md +36 -0
- data/lib/ecoportal/api/common/graphql/client.rb +1 -1
- data/lib/ecoportal/api/common/graphql/http_client.rb +35 -3
- data/lib/ecoportal/api/common/graphql/model/CLAUDE.md +28 -0
- data/lib/ecoportal/api/common/graphql/model/as_input.rb +8 -5
- data/lib/ecoportal/api/common/graphql/model/diffable/classic_diff_service.rb +3 -1
- data/lib/ecoportal/api/common/graphql/model/diffable/diff_service.rb +31 -23
- data/lib/ecoportal/api/common/graphql/model/diffable/hash_diff_nesting.rb +54 -1
- data/lib/ecoportal/api/graphql/CLAUDE.md +37 -0
- data/lib/ecoportal/api/graphql/base/CLAUDE.md +50 -0
- data/lib/ecoportal/api/graphql/base/ai_summary_version.rb +17 -0
- data/lib/ecoportal/api/graphql/base/delta_result.rb +16 -0
- data/lib/ecoportal/api/graphql/base/force/binding.rb +19 -0
- data/lib/ecoportal/api/graphql/base/force/binding_collection.rb +62 -0
- data/lib/ecoportal/api/graphql/base/force/collection.rb +47 -0
- data/lib/ecoportal/api/graphql/base/force.rb +65 -0
- data/lib/ecoportal/api/graphql/base/kickstand/job.rb +17 -0
- data/lib/ecoportal/api/graphql/base/kickstand/workflow.rb +18 -0
- data/lib/ecoportal/api/graphql/base/kickstand.rb +13 -0
- data/lib/ecoportal/api/graphql/base/page/basic.rb +38 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/actions_list.rb +9 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/ai_summary.rb +18 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/checklist.rb +29 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/collection.rb +112 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/contractor_entities.rb +28 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/cross_reference.rb +54 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/date_field.rb +23 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/file_field.rb +25 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/gauge.rb +19 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/geo.rb +24 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/image_gallery.rb +24 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/law.rb +8 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/mailbox.rb +9 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/number.rb +20 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/people.rb +35 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/plain_text.rb +17 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/rich_text.rb +26 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/select.rb +41 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/signature.rb +9 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/smart_fill.rb +17 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/table.rb +9 -0
- data/lib/ecoportal/api/graphql/base/page/data_field/tag_field.rb +21 -0
- data/lib/ecoportal/api/graphql/base/page/data_field.rb +137 -12
- data/lib/ecoportal/api/graphql/base/page/phased/stage.rb +68 -14
- data/lib/ecoportal/api/graphql/base/page/phased.rb +1 -0
- data/lib/ecoportal/api/graphql/base/page/section.rb +36 -0
- data/lib/ecoportal/api/graphql/base/page/section_collection.rb +79 -0
- data/lib/ecoportal/api/graphql/base/page.rb +2 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/action_type_selection.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/callback_type.rb +28 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/command_change.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/command_change_message.rb +15 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/command_es_change.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/command_interface.rb +36 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/email_config.rb +18 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/escalation_level.rb +19 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/in_system_config.rb +16 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/mailbox_field_selection.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/operation_interface.rb +39 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/operations/assign_to.rb +27 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/operations/create_page.rb +21 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/operations/send_notification.rb +30 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/people_field_selection.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/recipient_config.rb +34 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/register_field.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/task_config_selection.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/time_delay_config.rb +16 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/trigger_interface.rb +26 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/triggers/conditional_logic.rb +17 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow/user_selection.rb +16 -0
- data/lib/ecoportal/api/graphql/base/pages_workflow.rb +35 -0
- data/lib/ecoportal/api/graphql/base/preset_view.rb +17 -0
- data/lib/ecoportal/api/graphql/base/preview_page.rb +23 -0
- data/lib/ecoportal/api/graphql/base/register.rb +18 -0
- data/lib/ecoportal/api/graphql/base.rb +11 -0
- data/lib/ecoportal/api/graphql/builder/CLAUDE.md +65 -0
- data/lib/ecoportal/api/graphql/builder/kickstand.rb +73 -0
- data/lib/ecoportal/api/graphql/builder/page.rb +210 -41
- data/lib/ecoportal/api/graphql/builder/register/preset_view.rb +84 -0
- data/lib/ecoportal/api/graphql/builder/register.rb +27 -19
- data/lib/ecoportal/api/graphql/builder/template.rb +80 -0
- data/lib/ecoportal/api/graphql/builder.rb +2 -0
- data/lib/ecoportal/api/graphql/compat/filter_translator.rb +107 -0
- data/lib/ecoportal/api/graphql/compat/page_reference.rb +23 -0
- data/lib/ecoportal/api/graphql/compat/pages.rb +212 -0
- data/lib/ecoportal/api/graphql/compat/registers.rb +84 -0
- data/lib/ecoportal/api/graphql/compat/response.rb +35 -0
- data/lib/ecoportal/api/graphql/compat/search_results.rb +33 -0
- data/lib/ecoportal/api/graphql/compat/stage_collection.rb +70 -0
- data/lib/ecoportal/api/graphql/compat/stage_view.rb +76 -0
- data/lib/ecoportal/api/graphql/compat.rb +17 -0
- data/lib/ecoportal/api/graphql/concerns/data_field_access.rb +71 -0
- data/lib/ecoportal/api/graphql/concerns/deprecation.rb +20 -0
- data/lib/ecoportal/api/graphql/concerns/fragment_definitions.rb +21 -28
- data/lib/ecoportal/api/graphql/concerns/page_compat.rb +51 -0
- data/lib/ecoportal/api/graphql/concerns/snake_camel_access.rb +60 -0
- data/lib/ecoportal/api/graphql/concerns.rb +4 -0
- data/lib/ecoportal/api/graphql/connection/page.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/pages_workflow_command.rb +13 -0
- data/lib/ecoportal/api/graphql/connection/preset_view.rb +11 -0
- data/lib/ecoportal/api/graphql/connection/preview_page.rb +11 -0
- data/lib/ecoportal/api/graphql/connection.rb +4 -0
- data/lib/ecoportal/api/graphql/file_upload/client.rb +181 -0
- data/lib/ecoportal/api/graphql/file_upload.rb +10 -0
- data/lib/ecoportal/api/graphql/fragment/action.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment/action_category.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment/contractor_entity.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment/force.rb +30 -0
- data/lib/ecoportal/api/graphql/fragment/location_draft.rb +2 -2
- data/lib/ecoportal/api/graphql/fragment/location_node.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment/locations_error.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment/page.rb +85 -0
- data/lib/ecoportal/api/graphql/fragment/pages/common_page_union.rb +395 -0
- data/lib/ecoportal/api/graphql/fragment/pages.rb +15 -0
- data/lib/ecoportal/api/graphql/fragment/pages_workflow.rb +172 -0
- data/lib/ecoportal/api/graphql/fragment/pagination.rb +1 -1
- data/lib/ecoportal/api/graphql/fragment.rb +37 -27
- data/lib/ecoportal/api/graphql/input/contractor_entity/update.rb +25 -0
- data/lib/ecoportal/api/graphql/input/delta_input.rb +16 -0
- data/lib/ecoportal/api/graphql/input/page/archive.rb +14 -0
- data/lib/ecoportal/api/graphql/input/page/build_from_template.rb +13 -0
- data/lib/ecoportal/api/graphql/input/page/create_draft.rb +13 -0
- data/lib/ecoportal/api/graphql/input/page/create_from_template.rb +18 -0
- data/lib/ecoportal/api/graphql/input/page/delete_draft.rb +13 -0
- data/lib/ecoportal/api/graphql/input/page/publish_draft.rb +13 -0
- data/lib/ecoportal/api/graphql/input/page/review_task.rb +14 -0
- data/lib/ecoportal/api/graphql/input/page/unarchive.rb +14 -0
- data/lib/ecoportal/api/graphql/input/page/update.rb +140 -0
- data/lib/ecoportal/api/graphql/input/page.rb +26 -0
- data/lib/ecoportal/api/graphql/input/preset_view/create.rb +18 -0
- data/lib/ecoportal/api/graphql/input/preset_view/permission.rb +16 -0
- data/lib/ecoportal/api/graphql/input/preset_view/update.rb +16 -0
- data/lib/ecoportal/api/graphql/input/preset_view.rb +14 -0
- data/lib/ecoportal/api/graphql/input/register/create.rb +18 -0
- data/lib/ecoportal/api/graphql/input/register/update.rb +15 -0
- data/lib/ecoportal/api/graphql/input/register.rb +13 -0
- data/lib/ecoportal/api/graphql/input/search_conf/ai_generator.rb +234 -0
- data/lib/ecoportal/api/graphql/input/search_conf.rb +367 -0
- data/lib/ecoportal/api/graphql/input/variable_binding.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_action_tag.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_binding.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_comment_tagging_user_group.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_default_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_default_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_field.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_force.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_gauge_field_stop.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_field_config.rb +23 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_helper.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_operation.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_action_type.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_filter.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_people_field.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_task_config.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback.rb +23 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback_action.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_select_field_option.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_stage.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_tag.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_task.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_task_assignment_user_group.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/add_workflow_callback.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/collapse_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_binding.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_creator_permissions.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_default_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_field_configuration.rb +21 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_force.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_gauge_field_stop.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_field_config.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_helper.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_page.rb +28 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_page_creator_permissions.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_reminder.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_required_sign_offs.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_comment_tagging.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_task_assignment.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_scheduled_callback.rb +22 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_section_header.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_select_field_option.rb +19 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_stage.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_task_due.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/edit_trigger.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/expand_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/contractor_entities.rb +24 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/cross_reference.rb +23 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/date.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/gauge.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/image_gallery.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/location_field.rb +24 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/people.rb +24 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/plain_text.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/rich_text.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/select.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/signature.rb +20 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/field_config/table.rb +25 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/move_field.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/move_stage.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_action_tag.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_binding.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_callback.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_comment_tagging_user_group.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_field.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_force.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_gauge_field_stop.rb +17 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_linked_field_config.rb +17 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_linked_helper.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_direct_strategy_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_action_type.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_filter.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_people_field.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_task_config.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_user.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_scheduled_callback.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_select_field_option.rb +17 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_tag.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_strategy.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_assignment_user_group.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_due.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_priority_level.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/reorder_forces.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command/reorder_section.rb +18 -0
- data/lib/ecoportal/api/graphql/input/workflow_command.rb +251 -0
- data/lib/ecoportal/api/graphql/input.rb +8 -0
- data/lib/ecoportal/api/graphql/interface/base_page.rb +100 -58
- data/lib/ecoportal/api/graphql/interface/location_structure/nodes.rb +27 -28
- data/lib/ecoportal/api/graphql/logic/base_model.rb +2 -0
- data/lib/ecoportal/api/graphql/logic/base_query.rb +45 -2
- data/lib/ecoportal/api/graphql/logic/input.rb +15 -0
- data/lib/ecoportal/api/graphql/model/ai_summary_version.rb +10 -0
- data/lib/ecoportal/api/graphql/model/organization.rb +65 -55
- data/lib/ecoportal/api/graphql/model/page/basic.rb +14 -0
- data/lib/ecoportal/api/graphql/model/page/phased.rb +82 -20
- data/lib/ecoportal/api/graphql/model/page.rb +1 -0
- data/lib/ecoportal/api/graphql/model/page_union.rb +21 -0
- data/lib/ecoportal/api/graphql/model/pages_workflow.rb +20 -0
- data/lib/ecoportal/api/graphql/model/preset_view.rb +10 -0
- data/lib/ecoportal/api/graphql/model/preview_page.rb +10 -0
- data/lib/ecoportal/api/graphql/model/register.rb +10 -0
- data/lib/ecoportal/api/graphql/model.rb +8 -0
- data/lib/ecoportal/api/graphql/mutation/ai_summary/generate.rb +45 -0
- data/lib/ecoportal/api/graphql/mutation/ai_summary/submit_feedback.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/ai_summary.rb +13 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/bulk_update_jobs.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/bulk_update_workflows.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/fail_job.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/fail_workflow.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/start_job.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/start_workflow.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand/stop_workflow.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/kickstand.rb +18 -0
- data/lib/ecoportal/api/graphql/mutation/location_structure/apply_commands.rb +3 -3
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/add_commands.rb +2 -2
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/create.rb +2 -2
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/drop_bad_commands.rb +3 -3
- data/lib/ecoportal/api/graphql/mutation/location_structure/draft/publish.rb +3 -3
- data/lib/ecoportal/api/graphql/mutation/page/approve_review_task.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/archive.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/batch_update_review_task.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/build_from_template.rb +50 -0
- data/lib/ecoportal/api/graphql/mutation/page/create_draft.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/create_from_template.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/page/delete_draft.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/execute_force_commands.rb +69 -0
- data/lib/ecoportal/api/graphql/mutation/page/execute_workflow_commands.rb +51 -0
- data/lib/ecoportal/api/graphql/mutation/page/publish_draft.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/reject_review_task.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/restart_review_task.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/unarchive.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/undo_review_task.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/update.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/page/update_variable_bindings.rb +44 -0
- data/lib/ecoportal/api/graphql/mutation/page.rb +28 -0
- data/lib/ecoportal/api/graphql/mutation/preset_view/create.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/preset_view/destroy.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/preset_view/permission.rb +37 -0
- data/lib/ecoportal/api/graphql/mutation/preset_view/update.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/preset_view.rb +15 -0
- data/lib/ecoportal/api/graphql/mutation/register/create.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/register/destroy.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/register/update.rb +35 -0
- data/lib/ecoportal/api/graphql/mutation/register.rb +14 -0
- data/lib/ecoportal/api/graphql/mutation/smart_fill/generate.rb +36 -0
- data/lib/ecoportal/api/graphql/mutation/smart_fill/submit_feedback.rb +40 -0
- data/lib/ecoportal/api/graphql/mutation/smart_fill.rb +13 -0
- data/lib/ecoportal/api/graphql/mutation/template/create.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/template/create_related_page.rb +46 -0
- data/lib/ecoportal/api/graphql/mutation/template/destroy_related_page.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/template/publish.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/template/unpublish.rb +39 -0
- data/lib/ecoportal/api/graphql/mutation/template/update.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/template/update_information.rb +43 -0
- data/lib/ecoportal/api/graphql/mutation/template.rb +18 -0
- data/lib/ecoportal/api/graphql/mutation.rb +8 -0
- data/lib/ecoportal/api/graphql/payload/ai_summary_generate.rb +12 -0
- data/lib/ecoportal/api/graphql/payload/execute_workflow_commands.rb +36 -0
- data/lib/ecoportal/api/graphql/payload/force_commands.rb +31 -0
- data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_jobs.rb +36 -0
- data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_workflows.rb +36 -0
- data/lib/ecoportal/api/graphql/payload/kickstand/job.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/kickstand/workflow.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/kickstand.rb +15 -0
- data/lib/ecoportal/api/graphql/payload/location_structure/draft/create.rb +33 -34
- data/lib/ecoportal/api/graphql/payload/ok_payload.rb +21 -0
- data/lib/ecoportal/api/graphql/payload/page/archive.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/build_from_template.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/create_from_template.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/draft.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/review_task.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/unarchive.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/update.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page/update_variable_bindings.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/page.rb +19 -0
- data/lib/ecoportal/api/graphql/payload/preset_view.rb +11 -0
- data/lib/ecoportal/api/graphql/payload/register.rb +11 -0
- data/lib/ecoportal/api/graphql/payload/template/create.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/create_related_page.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/destroy_related_page.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/publish.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/unpublish.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/update.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template/update_information.rb +13 -0
- data/lib/ecoportal/api/graphql/payload/template.rb +18 -0
- data/lib/ecoportal/api/graphql/payload.rb +11 -0
- data/lib/ecoportal/api/graphql/query/action.rb +1 -1
- data/lib/ecoportal/api/graphql/query/action_categories.rb +1 -1
- data/lib/ecoportal/api/graphql/query/actions.rb +2 -2
- data/lib/ecoportal/api/graphql/query/contractor_entities.rb +1 -1
- data/lib/ecoportal/api/graphql/query/file_upload_signature.rb +76 -0
- data/lib/ecoportal/api/graphql/query/location_structure/draft.rb +2 -2
- data/lib/ecoportal/api/graphql/query/location_structure.rb +1 -1
- data/lib/ecoportal/api/graphql/query/location_structures.rb +1 -1
- data/lib/ecoportal/api/graphql/query/page.rb +45 -0
- data/lib/ecoportal/api/graphql/query/page_delta.rb +47 -0
- data/lib/ecoportal/api/graphql/query/page_with_forces.rb +43 -0
- data/lib/ecoportal/api/graphql/query/pages.rb +59 -0
- data/lib/ecoportal/api/graphql/query/pages_workflow_commands.rb +59 -0
- data/lib/ecoportal/api/graphql/query/register_preset_views.rb +78 -0
- data/lib/ecoportal/api/graphql/query/register_preview_pages.rb +83 -0
- data/lib/ecoportal/api/graphql/query/templates.rb +53 -0
- data/lib/ecoportal/api/graphql/query.rb +11 -0
- data/lib/ecoportal/api/graphql.rb +60 -2
- data/lib/ecoportal/api/graphql_version.rb +5 -5
- data/scripts/auto-worker-scheduler.sh +386 -0
- data/tests/contractor_entity_create.rb +19 -19
- data/tests/contractor_entity_udpate.rb +20 -20
- data/tests/dump_page_model.rb +74 -0
- data/tests/loc_structure_get.rb +1 -2
- data/tests/loc_structure_update.rb +51 -51
- data/tests/loc_structures_get.rb +15 -15
- metadata +436 -5
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ep-ai-manager
|
|
3
|
+
version: 2.2.0
|
|
4
|
+
description: >
|
|
5
|
+
Manages alignment between this project's AI setup and the ecoPortal AI standards.
|
|
6
|
+
Phase 2: automated checklist checking against all standards, end-of-session KPI
|
|
7
|
+
and learning capture, migration plan application, token budget reporting.
|
|
8
|
+
Invoke at: session start, session end, or when you suspect drift.
|
|
9
|
+
triggers:
|
|
10
|
+
- check AI standards
|
|
11
|
+
- AI alignment
|
|
12
|
+
- standards update
|
|
13
|
+
- eP_AI_Manager
|
|
14
|
+
- is my AI setup current
|
|
15
|
+
- apply migration
|
|
16
|
+
- end of session
|
|
17
|
+
- session wrap-up
|
|
18
|
+
- capture learnings
|
|
19
|
+
- token report
|
|
20
|
+
- file standards request
|
|
21
|
+
- report gap
|
|
22
|
+
- standards gap
|
|
23
|
+
- report to ep-ai-standards
|
|
24
|
+
- request standard
|
|
25
|
+
standards_gitlab: "https://gitlab.ecoportal.co.nz/oscar/ep-ai-standards"
|
|
26
|
+
standards_version_file: ".ai-assistance/standards-version.json"
|
|
27
|
+
applicable_to:
|
|
28
|
+
- any
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
# ep-ai-manager
|
|
32
|
+
|
|
33
|
+
## Path resolution — always do this first
|
|
34
|
+
|
|
35
|
+
Before any file access, resolve the ep-ai-standards path:
|
|
36
|
+
|
|
37
|
+
1. Read `.ai-assistance/local/paths.json` in the current repo
|
|
38
|
+
2. Find the entry with key `ep-standards` → use its `local_path` value as `<EP_STANDARDS>`
|
|
39
|
+
3. If `paths.json` is missing or has no `ep-standards` entry:
|
|
40
|
+
```
|
|
41
|
+
[ep-ai-manager] Cannot locate ep-ai-standards on this machine.
|
|
42
|
+
Fix: bash <ep-ai-standards>/scripts/install.sh --target . --mode retrofit
|
|
43
|
+
```
|
|
44
|
+
Then stop — do not proceed with relative-path guesses.
|
|
45
|
+
|
|
46
|
+
All file paths in these instructions that reference `<EP_STANDARDS>` mean this resolved value.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Role
|
|
51
|
+
|
|
52
|
+
You are the AI standards alignment manager for this project. You run automated
|
|
53
|
+
checks, capture session metrics, surface drift, and apply migration plans.
|
|
54
|
+
You do not make changes without explicit developer confirmation.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## On SESSION START — run automatically
|
|
59
|
+
|
|
60
|
+
### 1. Token budget status
|
|
61
|
+
|
|
62
|
+
Read `.ai-assistance/local/kpi/weekly-<YYYY-WNN>.json` (current ISO week).
|
|
63
|
+
Report in one line:
|
|
64
|
+
```
|
|
65
|
+
[token-budget] Week YYYY-WNN: N tokens used across M sessions this project | budget: X% of allocation
|
|
66
|
+
```
|
|
67
|
+
If `.ai-assistance/token-budget.json` has `total_tokens: null`, report actuals only.
|
|
68
|
+
If usage ≥ 80% of the project's priority allocation: warn in bold.
|
|
69
|
+
|
|
70
|
+
### 2. Overdue deferral check
|
|
71
|
+
|
|
72
|
+
Read `.ai-assistance/standards-version.json` → `deferred` array.
|
|
73
|
+
For each deferred item, compare `deferred-at` + allowed window (60 days medium,
|
|
74
|
+
14 days high, 0 days critical) to today.
|
|
75
|
+
Report any overdue deferrals as: `[OVERDUE] <standard> deferred since <date> — must action now`
|
|
76
|
+
|
|
77
|
+
### 3. Component version drift
|
|
78
|
+
|
|
79
|
+
Read `.ai-assistance/standards-version.json` → `installed-components` map.
|
|
80
|
+
Read `<EP_STANDARDS>/component-manifest.json` → `components` map.
|
|
81
|
+
|
|
82
|
+
For each skill key in `installed-components`:
|
|
83
|
+
- Look up the same key in the manifest
|
|
84
|
+
- If not found in manifest: skip (local skill, not tracked)
|
|
85
|
+
- Compare versions using semver. If local is `0.0.0` or `unknown`: treat as outdated (pre-versioning install)
|
|
86
|
+
- If outdated: check `migration_required_from` — does any semver range key cover the local version?
|
|
87
|
+
- No match → classify **auto-apply** (file copy only)
|
|
88
|
+
- Match found → classify **migration-required** (note the migration folder ID)
|
|
89
|
+
|
|
90
|
+
Report only when outdated components exist:
|
|
91
|
+
```
|
|
92
|
+
[standards-sync] N component(s) outdated — say "sync standards" to auto-apply:
|
|
93
|
+
|
|
94
|
+
skills/ep-ai-manager 2.0.0 → 2.1.0 auto-apply (CHANGELOG 1.4.0)
|
|
95
|
+
skills/code-specs 0.0.0 → 1.0.0 auto-apply (pre-versioning install)
|
|
96
|
+
skills/ruby-scripting 0.0.0 → 0.1.0 migration run "apply migration 0002-slug"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If all components current:
|
|
100
|
+
`[standards] All skills up to date — ep-ai-standards v{manifest.standards_release}`
|
|
101
|
+
|
|
102
|
+
If `installed-components` key is missing from `standards-version.json` entirely:
|
|
103
|
+
`[standards] installed-components not yet recorded — run "sync standards" to initialise`
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## On SESSION END / when explicitly invoked for wrap-up
|
|
108
|
+
|
|
109
|
+
### 4. KPI capture prompt
|
|
110
|
+
|
|
111
|
+
Ask the developer:
|
|
112
|
+
```
|
|
113
|
+
Session wrap-up — quick capture (skip any with 's'):
|
|
114
|
+
|
|
115
|
+
1. Main task category today?
|
|
116
|
+
coding / bug_fixing / bug_prevention / documentation / communication /
|
|
117
|
+
post_release / troubleshooting / integration_delivery / skills_development
|
|
118
|
+
|
|
119
|
+
2. Rough minutes saved by AI? (e.g. 60, or 's' to skip)
|
|
120
|
+
|
|
121
|
+
3. Any skills developed? (e.g. ai-platform-architecture, s to skip)
|
|
122
|
+
|
|
123
|
+
4. Any learnings worth capturing for the EPAI knowledge base?
|
|
124
|
+
Type a brief description, or 's' to skip.
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
On answers received:
|
|
128
|
+
- Create/update `.ai-assistance/local/kpi/sessions-<YYYY-WNN>.jsonl` with a record
|
|
129
|
+
matching the schema in `<EP_STANDARDS>/kpi/schema.json`
|
|
130
|
+
- If a learning was described: create a draft at
|
|
131
|
+
`.ai-assistance/local/epai-drafts/EPAI-<date>-<slug>.md` using the format from
|
|
132
|
+
`<EP_STANDARDS>/standards/agents/corpus-source-taxonomy.md` → "Page template"
|
|
133
|
+
|
|
134
|
+
### 5. Policy compliance reminder (if working on AI-related files)
|
|
135
|
+
|
|
136
|
+
If the session involved changes to `agents/`, `iam/`, `lambdas/`, `config/`, or
|
|
137
|
+
`.ai-assistance/skills/`:
|
|
138
|
+
```
|
|
139
|
+
[policy-check] Run before pushing: python3 scripts/policy-check.py --changed-only
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 6. LEARNING capture
|
|
143
|
+
|
|
144
|
+
After the KPI prompt, ask:
|
|
145
|
+
```
|
|
146
|
+
Any learnings worth capturing? (one per line, or 's' to skip)
|
|
147
|
+
Format: [type] description
|
|
148
|
+
Types: gotcha | pattern | gap | lesson | correction
|
|
149
|
+
|
|
150
|
+
Example: gotcha bash here-docs with unicode fail on Windows cp1252
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
For each learning provided:
|
|
154
|
+
- Write a `<!-- LEARNING: type -->` block to the current worklog entry (append to the
|
|
155
|
+
current session's Done section)
|
|
156
|
+
- Create a draft file at `.ai-assistance/local/epai-drafts/EPAI-<YYYY-MM-DD>-<slug>.md`
|
|
157
|
+
using this template:
|
|
158
|
+
```markdown
|
|
159
|
+
---
|
|
160
|
+
type: <type>
|
|
161
|
+
project_origin: <project slug>
|
|
162
|
+
contributor_email: <developer email from KPI record>
|
|
163
|
+
date: <today>
|
|
164
|
+
status: draft
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
# <one-line title>
|
|
168
|
+
|
|
169
|
+
<full description — self-contained, no assumed context>
|
|
170
|
+
|
|
171
|
+
## Where it applies
|
|
172
|
+
<which agents/projects/patterns this affects>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Phase 1 note: once the EPAI Confluence space is created, this step will also create a
|
|
176
|
+
Confluence page draft via Rovo MCP. Until then, drafts accumulate in local/epai-drafts/.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## On-demand: FULL ALIGNMENT CHECK
|
|
181
|
+
|
|
182
|
+
Run when explicitly invoked with "check alignment" or "check AI standards".
|
|
183
|
+
|
|
184
|
+
For each standard in `<EP_STANDARDS>/standards/`:
|
|
185
|
+
|
|
186
|
+
### standards/agents/skill-schema.md
|
|
187
|
+
- [ ] Every directory in `agents/` has either `SKILL.md` or `system_prompt_file` in `agent.yaml`
|
|
188
|
+
- [ ] SKILL.md frontmatter contains `name:`, `description:`, `triggers:`
|
|
189
|
+
- [ ] `name:` follows `<team>-<agent>` format (grep: `^name: [a-z]+-[a-z]`)
|
|
190
|
+
- [ ] Customer-facing SKILL.md has `<!-- BEGIN privacy_directive` marker
|
|
191
|
+
|
|
192
|
+
### standards/agents/agent-manifest.md
|
|
193
|
+
- [ ] Every `agents/` subdirectory that has a SKILL.md also has an `agent.yaml`
|
|
194
|
+
- [ ] Every `agent.yaml` has: `name`, `team`, `role`, `status`, `owner`
|
|
195
|
+
- [ ] Specialist agents have `corpus_prefix:`
|
|
196
|
+
- [ ] Customer-facing agents have `automatic_learning_guard: true`
|
|
197
|
+
- [ ] Operator agents have `escalation:` and `access_restriction:` blocks
|
|
198
|
+
- [ ] No agent has `status: published` without being in the activation checklist
|
|
199
|
+
|
|
200
|
+
### standards/agents/role-taxonomy.md
|
|
201
|
+
- [ ] No operator agent appears in any orchestrator's `triggers:` or skill list
|
|
202
|
+
- [ ] Operator agents have `escalation:` → `required: true`
|
|
203
|
+
|
|
204
|
+
### standards/workflows/session-handoff.md
|
|
205
|
+
- [ ] `docs/worklog.md` exists
|
|
206
|
+
- [ ] `CLAUDE.md` contains the string "worklog"
|
|
207
|
+
- [ ] Worklog has an entry within the last 5 working sessions (check for dated `## ` headings)
|
|
208
|
+
|
|
209
|
+
### standards/security/pii-handling.md
|
|
210
|
+
- [ ] No `real_value` field in any DynamoDB table definition or Lambda code
|
|
211
|
+
- [ ] Customer-facing SKILL.md has complete `BEGIN/END privacy_directive` block
|
|
212
|
+
- [ ] PII scrubber exists if corpus pipeline is used (check lambdas/)
|
|
213
|
+
|
|
214
|
+
### standards/tooling/token-budget-management.md
|
|
215
|
+
- [ ] `.ai-assistance/token-budget.json` exists
|
|
216
|
+
- [ ] `project.name` and `project.priority` are filled in (not `{{PLACEHOLDER}}`)
|
|
217
|
+
- [ ] `.claude/settings.json` has `Stop` and `SessionStart` hooks with `token-logger.js`
|
|
218
|
+
- [ ] `.ai-assistance/local/` is in `.gitignore`
|
|
219
|
+
|
|
220
|
+
### standards/tooling/cross-platform-ai-guidelines.md
|
|
221
|
+
- [ ] No bash scripts in the repo exceed ~200 lines (check with `wc -l`)
|
|
222
|
+
- [ ] No hardcoded `api.anthropic.com` (use AWS endpoint)
|
|
223
|
+
|
|
224
|
+
### standards/kpi/schema.md
|
|
225
|
+
- [ ] `kpi/records/` or `.ai-assistance/local/` is in `.gitignore`
|
|
226
|
+
- [ ] At least one KPI session record exists (if AI has been used in the project)
|
|
227
|
+
|
|
228
|
+
**For each check:**
|
|
229
|
+
- PASS: note briefly
|
|
230
|
+
- FAIL: give the specific file, what's wrong, what to do
|
|
231
|
+
- WARN: note for awareness
|
|
232
|
+
|
|
233
|
+
After all checks: `[alignment] N pass, N warn, N fail — project at ep-ai-standards vX.Y.Z`
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## On-demand: SYNC STANDARDS
|
|
238
|
+
|
|
239
|
+
When the developer says "sync standards", "sync skills", or "apply auto updates":
|
|
240
|
+
|
|
241
|
+
1. Re-read `installed-components` from `standards-version.json` and `component-manifest.json`.
|
|
242
|
+
2. Build the list of **auto-apply** outdated components (those with no `migration_required_from` match).
|
|
243
|
+
3. For each auto-apply component:
|
|
244
|
+
- Copy `<EP_STANDARDS>/{source}` to `.ai-assistance/skills/{skill-name}/SKILL.md`
|
|
245
|
+
- Update `installed-components["skills/{skill-name}"]` to the new version in `standards-version.json`
|
|
246
|
+
- Report: `[sync] Updated skills/ep-ai-manager 2.0.0 → 2.1.0`
|
|
247
|
+
4. If `installed-components` was missing entirely, scan `.ai-assistance/skills/*/SKILL.md` now,
|
|
248
|
+
read each version, and write the full `installed-components` map before syncing.
|
|
249
|
+
5. Update `ep-ai-standards-version` to `manifest.standards_release` and `applied-at` to today.
|
|
250
|
+
6. Final summary: `[sync] N skill(s) updated. Run "check AI standards" to verify alignment.`
|
|
251
|
+
7. If migration-required items remain: list them.
|
|
252
|
+
`[sync] N item(s) need migration — run "apply migration <id>" for each.`
|
|
253
|
+
|
|
254
|
+
Never auto-apply a migration-required component without explicit "apply migration <id>" confirmation.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## On-demand: APPLY MIGRATION PLAN
|
|
259
|
+
|
|
260
|
+
When the developer says "apply migration" or "update standards":
|
|
261
|
+
|
|
262
|
+
1. Read `.ai-assistance/standards-version.json` → current version
|
|
263
|
+
2. Check if `<EP_STANDARDS>/migration/v{current}-to-v{target}/` exists
|
|
264
|
+
3. Read `MIGRATION.md` — show the developer what will change and effort estimate
|
|
265
|
+
4. **Ask for explicit confirmation before proceeding**
|
|
266
|
+
5. If automated steps exist: `bash <EP_STANDARDS>/migration/.../automated/apply.sh --target .`
|
|
267
|
+
6. Run verify.sh — show results
|
|
268
|
+
7. Update `.ai-assistance/standards-version.json` → new version + `applied-at: today`
|
|
269
|
+
|
|
270
|
+
Never run apply.sh without showing the developer its contents first.
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## On-demand: FILE STANDARDS REQUEST
|
|
275
|
+
|
|
276
|
+
When the developer says "file a standards request", "report a gap", "standards gap",
|
|
277
|
+
"report to ep-ai-standards", "request standard", or similar:
|
|
278
|
+
|
|
279
|
+
1. Resolve `<EP_STANDARDS>` path (see Path resolution above).
|
|
280
|
+
|
|
281
|
+
2. Prompt the developer (one message, all fields):
|
|
282
|
+
```
|
|
283
|
+
Standards request — quick capture (press Enter to skip optional fields):
|
|
284
|
+
|
|
285
|
+
1. Type? gap / inconsistency / improvement / error
|
|
286
|
+
2. Area? skill / standard / template / convention / script
|
|
287
|
+
3. Affected? e.g. skills-library/ep-ai-manager/SKILL.md
|
|
288
|
+
4. Title? brief description (e.g. "ep-ai-manager trigger wording unclear")
|
|
289
|
+
5. Description? what's wrong — be specific
|
|
290
|
+
6. Suggested fix? (optional)
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
3. Build the request file:
|
|
294
|
+
- **repo-slug**: current repo's folder name, lowercased, spaces→hyphens
|
|
295
|
+
(e.g. `ecoportal-api-graphql` or `eco-extension`)
|
|
296
|
+
- **id**: 7 lowercase hex characters derived from the title (e.g. `a3f2b1c`)
|
|
297
|
+
- **slug**: title lowercased, spaces→hyphens, non-alphanumeric stripped, max 40 chars
|
|
298
|
+
- **filename**: `{repo-slug}-{id}-{slug}.md`
|
|
299
|
+
|
|
300
|
+
4. Write to `<EP_STANDARDS>/.ai-assistance/local/standards-requests/{filename}`:
|
|
301
|
+
|
|
302
|
+
```markdown
|
|
303
|
+
# STANDARDS REQUEST: {title}
|
|
304
|
+
|
|
305
|
+
STATUS: PENDING
|
|
306
|
+
FILED: {ISO 8601 timestamp}
|
|
307
|
+
FROM_REPO: {repo-slug}
|
|
308
|
+
TYPE: {type}
|
|
309
|
+
AREA: {area}
|
|
310
|
+
AFFECTED: {affected}
|
|
311
|
+
|
|
312
|
+
## Description
|
|
313
|
+
{description}
|
|
314
|
+
|
|
315
|
+
## Context
|
|
316
|
+
Filed during a {repo-slug} AI session.
|
|
317
|
+
|
|
318
|
+
## Suggested fix
|
|
319
|
+
{suggested fix, or "None provided."}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
5. Confirm to the developer:
|
|
323
|
+
```
|
|
324
|
+
[standards-request] Filed: {filename}
|
|
325
|
+
Will be reviewed in the next ep-ai-standards session.
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## On-demand: STANDARDS VERSION UPDATE
|
|
331
|
+
|
|
332
|
+
When the developer says "update standards version" after manually applying changes:
|
|
333
|
+
|
|
334
|
+
1. Ask: "Which version are you updating to? (e.g. 1.1.0)"
|
|
335
|
+
2. Read `<EP_STANDARDS>/CHANGELOG.md` to confirm the version exists
|
|
336
|
+
3. Update `.ai-assistance/standards-version.json` → `ep-ai-standards-version` and `applied-at`
|
|
337
|
+
4. Confirm: "Updated to v{version}. Run full alignment check to verify?"
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Deferral recording
|
|
342
|
+
|
|
343
|
+
When a developer chooses to defer a finding:
|
|
344
|
+
|
|
345
|
+
```json
|
|
346
|
+
// Add to .ai-assistance/standards-version.json → deferred array:
|
|
347
|
+
{
|
|
348
|
+
"standard": "tooling/claude-code",
|
|
349
|
+
"from-version": "1.0.0",
|
|
350
|
+
"severity": "medium",
|
|
351
|
+
"deferred-by": "oscar@ecoportal.co.nz",
|
|
352
|
+
"deferred-at": "2026-06-10",
|
|
353
|
+
"reason": "Bridge refactor planned for Q3",
|
|
354
|
+
"review-by": "2026-09-10"
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
Calculate `review-by` automatically: medium = +60 days, high = +14 days.
|
|
359
|
+
Critical deferrals are not recorded — escalate to Oscar immediately.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Severity handling
|
|
364
|
+
|
|
365
|
+
| Severity | Deferral | At session start |
|
|
366
|
+
|---|---|---|
|
|
367
|
+
| `low` | Unlimited | Mention only if asked |
|
|
368
|
+
| `medium` | 60 days | Warn after 30 days |
|
|
369
|
+
| `high` | 14 days | Warn every session after 7 days |
|
|
370
|
+
| `critical` | None | Block — escalate to Oscar |
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## EPAI draft format
|
|
375
|
+
|
|
376
|
+
When capturing a learning, write to `.ai-assistance/local/epai-drafts/EPAI-<date>-<slug>.md`:
|
|
377
|
+
|
|
378
|
+
```markdown
|
|
379
|
+
# [<TYPE>] <Brief title>
|
|
380
|
+
|
|
381
|
+
<!-- PAGE PROPERTIES -->
|
|
382
|
+
contributor_email: <developer email>
|
|
383
|
+
project_origin: <project name>
|
|
384
|
+
consent_timestamp: <today>
|
|
385
|
+
usage_scope: agent-corpus-eligible
|
|
386
|
+
evidence_link: <link to worklog session, commit, or MR>
|
|
387
|
+
last_verified: <today>
|
|
388
|
+
source_type: primary
|
|
389
|
+
<!-- END PAGE PROPERTIES -->
|
|
390
|
+
|
|
391
|
+
**Labels:** `epai-type:<type>` `epai-area:<area>` `epai-status:needs-review`
|
|
392
|
+
|
|
393
|
+
## Observed Behaviour
|
|
394
|
+
<What actually happened — factual, specific>
|
|
395
|
+
|
|
396
|
+
## Why it matters
|
|
397
|
+
<Impact if you don't know this>
|
|
398
|
+
|
|
399
|
+
## Fix / Pattern
|
|
400
|
+
<What to do>
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
*Curator: verify evidence link before promoting to Consolidated*
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Valid types: `gotcha`, `pattern`, `anti-pattern`, `gap`, `lesson`, `correction`,
|
|
407
|
+
`environment-quirk`, `prompt-trigger`.
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## What this skill does NOT do
|
|
412
|
+
|
|
413
|
+
- Does not make file changes without explicit developer confirmation
|
|
414
|
+
- Does not apply migration scripts without showing contents first
|
|
415
|
+
- Does not defer `critical` findings
|
|
416
|
+
- Does not mark a check as PASS without verifying the actual file
|
|
417
|
+
- Does not create EPAI drafts without the developer providing the learning
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# SKILL: Gemini Assist
|
|
2
|
+
|
|
3
|
+
**Purpose:** Offload large-context tasks to Gemini to save Claude token quota, speed up development, and leverage Gemini's wide context window.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## When to Use
|
|
8
|
+
|
|
9
|
+
- The task requires reading many files at once (e.g. whole-gem analysis, cross-cutting refactor planning).
|
|
10
|
+
- A task is mostly "read and summarise / read and advise" rather than "write code" — Gemini handles these cheaply.
|
|
11
|
+
- You're doing a cycle-end review and want a second pass over a large diff or many changed files.
|
|
12
|
+
- Token budget is running low and the task doesn't require Claude's nuanced judgement for the current step.
|
|
13
|
+
|
|
14
|
+
## When NOT to Use
|
|
15
|
+
|
|
16
|
+
- Tasks that require writing or editing actual code (Claude applies changes; Gemini only advises).
|
|
17
|
+
- Tasks where hallucination risk is high and verification would cost more time than doing it directly.
|
|
18
|
+
- Short tasks that fit comfortably in Claude's context — the overhead isn't worth it.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## How to Invoke
|
|
23
|
+
|
|
24
|
+
Run from the repo root:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
ruby .ai-assistance/skills/gemini-assist/gemini_ask.rb \
|
|
28
|
+
--prompt "Your question or instruction here" \
|
|
29
|
+
--files path/to/file1.rb path/to/file2.rb \
|
|
30
|
+
[--model gemini-1.5-pro]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or pass a prompt file:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
ruby .ai-assistance/skills/gemini-assist/gemini_ask.rb \
|
|
37
|
+
--prompt-file .ai-assistance/skills/gemini-assist/prompts/cycle_end_review.txt \
|
|
38
|
+
--files "lib/ecoportal/api/graphql/**/*.rb"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Environment variable required:** `GEMINI_API_KEY` — set in `.env` at repo root (git-ignored).
|
|
42
|
+
**Optional:** `GEMINI_MODEL` — defaults to `gemini-1.5-pro`. Override in `.env` or via `--model`.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Output Handling (IMPORTANT)
|
|
47
|
+
|
|
48
|
+
Gemini responses **must always be reviewed** before acting on them:
|
|
49
|
+
|
|
50
|
+
1. Read the response carefully.
|
|
51
|
+
2. Cross-check any specific claims (method names, class hierarchies, argument counts) against the actual code.
|
|
52
|
+
3. Where Gemini proposes code changes, treat them as a draft — apply only after verifying correctness.
|
|
53
|
+
4. Where Gemini flags issues in a cycle-end review, confirm each issue is real before proposing a fix to the developer.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Prompting Tips for Best Results
|
|
58
|
+
|
|
59
|
+
- Give Gemini explicit instructions: what to look for, what to ignore, what format to respond in.
|
|
60
|
+
- Tell it the role: "You are reviewing a Ruby gem. Focus on X. Do not suggest Y."
|
|
61
|
+
- Ask for a structured output (e.g. "Respond with a numbered list of concerns, each with: file, line range, issue, suggested fix").
|
|
62
|
+
- For large reviews, ask it to triage by severity first.
|
|
63
|
+
- Use the pre-built prompt in `prompts/cycle_end_review.txt` for end-of-cycle reviews.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Gemini MCP Server
|
|
4
|
+
* Exposes ask_gemini and list_gemini_models as MCP tools over stdio.
|
|
5
|
+
* Add to ~/.claude/settings.json under mcpServers.
|
|
6
|
+
*
|
|
7
|
+
* Env vars (loaded from .env in cwd, or set in settings.json env block):
|
|
8
|
+
* GEMINI_API_KEY — required
|
|
9
|
+
* GEMINI_MODEL — optional, default: gemini-2.5-pro
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const https = require("https");
|
|
13
|
+
const fs = require("fs");
|
|
14
|
+
const path = require("path");
|
|
15
|
+
const rl = require("readline").createInterface({ input: process.stdin });
|
|
16
|
+
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Config
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
const API_BASE = "https://generativelanguage.googleapis.com/v1beta/models";
|
|
22
|
+
const DEFAULT_MODEL = process.env.GEMINI_MODEL || "gemini-2.5-pro";
|
|
23
|
+
|
|
24
|
+
const SYSTEM_PREAMBLE = `You are an expert Ruby developer reviewing code for the ecoportal-api-graphql gem.
|
|
25
|
+
This gem provides a GraphQL client layer. It uses graphql-ruby, graphlient, and graphql-client upstream,
|
|
26
|
+
and is consumed by eco-helpers downstream. Backwards compatibility matters.
|
|
27
|
+
When you identify issues, be specific: file name, approximate line reference, concrete suggestion.
|
|
28
|
+
Flag hallucination risk: if unsure, say so rather than guessing.`;
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// .env loader
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
function loadDotenv(dotenvPath = ".env") {
|
|
35
|
+
if (!fs.existsSync(dotenvPath)) return;
|
|
36
|
+
fs.readFileSync(dotenvPath, "utf8").split("\n").forEach(raw => {
|
|
37
|
+
const line = raw.trim();
|
|
38
|
+
if (!line || line.startsWith("#") || !line.includes("=")) return;
|
|
39
|
+
const [key, ...rest] = line.split("=");
|
|
40
|
+
const value = rest.join("=").trim().replace(/^["']|["']$/g, "");
|
|
41
|
+
if (key.trim() && !process.env[key.trim()]) process.env[key.trim()] = value;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Gemini API helpers
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
function geminiPost(model, payload) {
|
|
50
|
+
const apiKey = process.env.GEMINI_API_KEY;
|
|
51
|
+
if (!apiKey) throw new Error("GEMINI_API_KEY is not set");
|
|
52
|
+
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
const body = JSON.stringify(payload);
|
|
55
|
+
const url = new URL(`${API_BASE}/${model}:generateContent?key=${apiKey}`);
|
|
56
|
+
const req = https.request({
|
|
57
|
+
hostname: url.hostname, path: url.pathname + url.search,
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) }
|
|
60
|
+
}, res => {
|
|
61
|
+
let data = "";
|
|
62
|
+
res.on("data", c => data += c);
|
|
63
|
+
res.on("end", () => {
|
|
64
|
+
if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}: ${data}`));
|
|
65
|
+
resolve(JSON.parse(data));
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
req.on("error", reject);
|
|
69
|
+
req.write(body);
|
|
70
|
+
req.end();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function geminiGet(path_) {
|
|
75
|
+
const apiKey = process.env.GEMINI_API_KEY;
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
const url = new URL(`https://generativelanguage.googleapis.com/v1beta/${path_}?key=${apiKey}&pageSize=50`);
|
|
78
|
+
https.get(url.toString(), res => {
|
|
79
|
+
let data = "";
|
|
80
|
+
res.on("data", c => data += c);
|
|
81
|
+
res.on("end", () => resolve(JSON.parse(data)));
|
|
82
|
+
}).on("error", reject);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function askGemini({ prompt, model, files = [] }) {
|
|
87
|
+
const usedModel = model || DEFAULT_MODEL;
|
|
88
|
+
|
|
89
|
+
const fileParts = files.map(f => {
|
|
90
|
+
try {
|
|
91
|
+
const text = fs.readFileSync(f, "utf8");
|
|
92
|
+
return `### FILE: ${f}\n\`\`\`ruby\n${text}\n\`\`\``;
|
|
93
|
+
} catch {
|
|
94
|
+
return `### FILE: ${f}\n(could not read file)`;
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const parts = [SYSTEM_PREAMBLE, ""];
|
|
99
|
+
if (fileParts.length) { parts.push("## Files provided for context\n"); parts.push(...fileParts, ""); }
|
|
100
|
+
parts.push("## Task\n", prompt.trim());
|
|
101
|
+
const fullPrompt = parts.join("\n");
|
|
102
|
+
|
|
103
|
+
const result = await geminiPost(usedModel, {
|
|
104
|
+
contents: [{ parts: [{ text: fullPrompt }] }],
|
|
105
|
+
generationConfig: { temperature: 0.2, maxOutputTokens: 8192 }
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const text = result?.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
109
|
+
if (!text) throw new Error(`Unexpected response: ${JSON.stringify(result)}`);
|
|
110
|
+
return `${text}\n\n---\n*Model: ${usedModel} | Files: ${files.length}*\n⚠️ Always verify Gemini's claims against actual code.`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function listModels() {
|
|
114
|
+
const result = await geminiGet("models");
|
|
115
|
+
const models = (result.models || [])
|
|
116
|
+
.filter(m => m.name?.includes("gemini") && m.supportedGenerationMethods?.includes("generateContent"))
|
|
117
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
118
|
+
.map(m => `• ${m.name.replace("models/", "").padEnd(42)} ${m.displayName || ""}`)
|
|
119
|
+
.join("\n");
|
|
120
|
+
return `Available Gemini models:\n\n${models}`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// MCP protocol (JSON-RPC 2.0 over stdio)
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
const TOOLS = [
|
|
128
|
+
{
|
|
129
|
+
name: "ask_gemini",
|
|
130
|
+
description: "Send a prompt (optionally with file context) to Gemini and get a response. Use for large-context analysis, code review, refactoring advice, and cycle-end reviews.",
|
|
131
|
+
inputSchema: {
|
|
132
|
+
type: "object",
|
|
133
|
+
properties: {
|
|
134
|
+
prompt: { type: "string", description: "The question or instruction for Gemini" },
|
|
135
|
+
files: { type: "array", items: { type: "string" }, description: "Optional file paths to include as context" },
|
|
136
|
+
model: { type: "string", description: `Gemini model to use (default: ${DEFAULT_MODEL})` }
|
|
137
|
+
},
|
|
138
|
+
required: ["prompt"]
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "list_gemini_models",
|
|
143
|
+
description: "List all Gemini models available for your API key.",
|
|
144
|
+
inputSchema: { type: "object", properties: {} }
|
|
145
|
+
}
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
function send(obj) {
|
|
149
|
+
process.stdout.write(JSON.stringify(obj) + "\n");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function respond(id, result) {
|
|
153
|
+
send({ jsonrpc: "2.0", id, result });
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function respondError(id, code, message) {
|
|
157
|
+
send({ jsonrpc: "2.0", id, error: { code, message } });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function handle(msg) {
|
|
161
|
+
const { id, method, params } = msg;
|
|
162
|
+
|
|
163
|
+
if (method === "initialize") {
|
|
164
|
+
return respond(id, {
|
|
165
|
+
protocolVersion: "2024-11-05",
|
|
166
|
+
serverInfo: { name: "gemini-mcp", version: "1.0.0" },
|
|
167
|
+
capabilities: { tools: {} }
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (method === "tools/list") {
|
|
172
|
+
return respond(id, { tools: TOOLS });
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (method === "tools/call") {
|
|
176
|
+
const { name, arguments: args = {} } = params;
|
|
177
|
+
try {
|
|
178
|
+
let text;
|
|
179
|
+
if (name === "ask_gemini") text = await askGemini(args);
|
|
180
|
+
else if (name === "list_gemini_models") text = await listModels();
|
|
181
|
+
else return respondError(id, -32601, `Unknown tool: ${name}`);
|
|
182
|
+
respond(id, { content: [{ type: "text", text }] });
|
|
183
|
+
} catch (err) {
|
|
184
|
+
respondError(id, -32000, err.message);
|
|
185
|
+
}
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (method === "notifications/initialized") return; // no response needed
|
|
190
|
+
if (id != null) respondError(id, -32601, `Method not found: ${method}`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
194
|
+
// Main
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
|
|
197
|
+
loadDotenv(path.join(process.cwd(), ".env"));
|
|
198
|
+
|
|
199
|
+
rl.on("line", line => {
|
|
200
|
+
if (!line.trim()) return;
|
|
201
|
+
try { handle(JSON.parse(line)); }
|
|
202
|
+
catch { /* ignore parse errors */ }
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
process.stderr.write(`[gemini-mcp] ready (model: ${DEFAULT_MODEL})\n`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Superseded by gemini_ask.rb — please use that instead.
|