switchroom 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +447 -0
- package/bin/autoaccept.exp +81 -0
- package/bin/boot-self-test.sh +149 -0
- package/bin/bridge-watchdog.sh +967 -0
- package/bin/handoff-briefing.sh +206 -0
- package/bin/run-hook.sh +228 -0
- package/bin/switchroom.ts +4 -0
- package/bin/timezone-hook.sh +67 -0
- package/bin/user-profile-refresh-hook.sh +38 -0
- package/bin/workspace-dynamic-hook.sh +142 -0
- package/bin/workspace-stable-hook.sh +57 -0
- package/dist/cli/autoaccept-poll.js +118 -0
- package/dist/cli/switchroom.js +48557 -0
- package/package.json +95 -0
- package/profiles/_base/settings.json.hbs +15 -0
- package/profiles/_base/start.sh.hbs +383 -0
- package/profiles/_shared/telegram-style.md.hbs +140 -0
- package/profiles/coding/CLAUDE.md.hbs +57 -0
- package/profiles/coding/skills/architecture/SKILL.md +70 -0
- package/profiles/coding/skills/code-review/SKILL.md +58 -0
- package/profiles/coding/workspace/SOUL.md.hbs +25 -0
- package/profiles/default/CLAUDE.md +238 -0
- package/profiles/default/CLAUDE.md.hbs +113 -0
- package/profiles/default/workspace/CLAUDE.md.hbs +126 -0
- package/profiles/default/workspace/HEARTBEAT.md.hbs +40 -0
- package/profiles/default/workspace/IDENTITY.md.hbs +32 -0
- package/profiles/default/workspace/MEMORY.md.hbs +29 -0
- package/profiles/default/workspace/SOUL.md.hbs +61 -0
- package/profiles/default/workspace/TOOLS.md.hbs +29 -0
- package/profiles/default/workspace/USER.md.hbs +52 -0
- package/profiles/default/workspace/memory/.gitkeep +0 -0
- package/profiles/executive-assistant/CLAUDE.md.hbs +51 -0
- package/profiles/executive-assistant/skills/daily-briefing/SKILL.md +55 -0
- package/profiles/executive-assistant/skills/meeting-prep/SKILL.md +58 -0
- package/profiles/executive-assistant/workspace/SOUL.md.hbs +25 -0
- package/profiles/health-coach/CLAUDE.md.hbs +45 -0
- package/profiles/health-coach/skills/check-in/SKILL.md +41 -0
- package/profiles/health-coach/skills/weekly-review/SKILL.md +53 -0
- package/profiles/health-coach/workspace/SOUL.md.hbs +25 -0
- package/skills/buildkite-agent-infrastructure/SKILL.md +302 -0
- package/skills/buildkite-agent-infrastructure/agents/openai.yaml +6 -0
- package/skills/buildkite-agent-infrastructure/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-agent-infrastructure/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-agent-infrastructure/references/audit-logging.md +87 -0
- package/skills/buildkite-agent-infrastructure/references/graphql-mutations.md +690 -0
- package/skills/buildkite-agent-infrastructure/references/instance-shapes.md +38 -0
- package/skills/buildkite-agent-infrastructure/references/pipeline-templates.md +73 -0
- package/skills/buildkite-agent-infrastructure/references/self-hosted-agents.md +137 -0
- package/skills/buildkite-agent-infrastructure/references/sso-saml.md +92 -0
- package/skills/buildkite-agent-runtime/SKILL.md +476 -0
- package/skills/buildkite-agent-runtime/agents/openai.yaml +6 -0
- package/skills/buildkite-agent-runtime/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-agent-runtime/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-agent-runtime/references/flag-reference.md +417 -0
- package/skills/buildkite-agent-runtime/references/patterns-and-recipes.md +555 -0
- package/skills/buildkite-api/SKILL.md +285 -0
- package/skills/buildkite-api/agents/openai.yaml +6 -0
- package/skills/buildkite-api/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-api/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-api/references/graphql-reference.md +195 -0
- package/skills/buildkite-api/references/patterns.md +44 -0
- package/skills/buildkite-api/references/webhooks.md +161 -0
- package/skills/buildkite-cli/SKILL.md +379 -0
- package/skills/buildkite-cli/agents/openai.yaml +6 -0
- package/skills/buildkite-cli/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-cli/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-cli/references/command-reference.md +181 -0
- package/skills/buildkite-migration/SKILL.md +182 -0
- package/skills/buildkite-pipelines/SKILL.md +464 -0
- package/skills/buildkite-pipelines/agents/openai.yaml +6 -0
- package/skills/buildkite-pipelines/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-pipelines/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-pipelines/examples/basic-pipeline.yml +24 -0
- package/skills/buildkite-pipelines/examples/optimized-pipeline.yml +100 -0
- package/skills/buildkite-pipelines/references/advanced-patterns.md +286 -0
- package/skills/buildkite-pipelines/references/retry-and-error-codes.md +131 -0
- package/skills/buildkite-pipelines/references/step-types-reference.md +225 -0
- package/skills/buildkite-secure-delivery/SKILL.md +168 -0
- package/skills/buildkite-secure-delivery/agents/openai.yaml +6 -0
- package/skills/buildkite-secure-delivery/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-secure-delivery/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-secure-delivery/references/oidc-cloud-providers.md +83 -0
- package/skills/buildkite-secure-delivery/references/package-publishing.md +100 -0
- package/skills/buildkite-test-engine/SKILL.md +239 -0
- package/skills/buildkite-test-engine/agents/openai.yaml +6 -0
- package/skills/buildkite-test-engine/assets/buildkite-icon-large.png +0 -0
- package/skills/buildkite-test-engine/assets/buildkite-icon-small.png +0 -0
- package/skills/buildkite-test-engine/examples/bktec-splitting.yml +16 -0
- package/skills/buildkite-test-engine/examples/collector-pipeline.yml +11 -0
- package/skills/buildkite-test-engine/references/collectors.md +198 -0
- package/skills/buildkite-test-engine/references/splitting-examples.md +93 -0
- package/skills/docx/LICENSE.txt +30 -0
- package/skills/docx/SKILL.md +590 -0
- package/skills/docx/VENDORED.md +32 -0
- package/skills/docx/scripts/__init__.py +1 -0
- package/skills/docx/scripts/accept_changes.py +135 -0
- package/skills/docx/scripts/comment.py +318 -0
- package/skills/docx/scripts/office/helpers/__init__.py +0 -0
- package/skills/docx/scripts/office/helpers/merge_runs.py +199 -0
- package/skills/docx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills/docx/scripts/office/pack.py +159 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/docx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/docx/scripts/office/soffice.py +183 -0
- package/skills/docx/scripts/office/unpack.py +132 -0
- package/skills/docx/scripts/office/validate.py +111 -0
- package/skills/docx/scripts/office/validators/__init__.py +15 -0
- package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-313.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/base.cpython-313.pyc +0 -0
- package/skills/docx/scripts/office/validators/base.py +847 -0
- package/skills/docx/scripts/office/validators/docx.py +446 -0
- package/skills/docx/scripts/office/validators/pptx.py +275 -0
- package/skills/docx/scripts/office/validators/redlining.py +247 -0
- package/skills/docx/scripts/templates/comments.xml +3 -0
- package/skills/docx/scripts/templates/commentsExtended.xml +3 -0
- package/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/skills/docx/scripts/templates/commentsIds.xml +3 -0
- package/skills/docx/scripts/templates/people.xml +3 -0
- package/skills/file-bug/SKILL.md +129 -0
- package/skills/humanizer/LICENSE +21 -0
- package/skills/humanizer/SKILL.md +559 -0
- package/skills/humanizer/VENDORED.md +38 -0
- package/skills/humanizer-calibrate/SKILL.md +144 -0
- package/skills/mcp-builder/LICENSE.txt +202 -0
- package/skills/mcp-builder/SKILL.md +236 -0
- package/skills/mcp-builder/VENDORED.md +32 -0
- package/skills/mcp-builder/reference/evaluation.md +602 -0
- package/skills/mcp-builder/reference/mcp_best_practices.md +249 -0
- package/skills/mcp-builder/reference/node_mcp_server.md +970 -0
- package/skills/mcp-builder/reference/python_mcp_server.md +719 -0
- package/skills/mcp-builder/scripts/connections.py +151 -0
- package/skills/mcp-builder/scripts/evaluation.py +373 -0
- package/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/skills/mcp-builder/scripts/requirements.txt +2 -0
- package/skills/pdf/LICENSE.txt +30 -0
- package/skills/pdf/SKILL.md +314 -0
- package/skills/pdf/VENDORED.md +32 -0
- package/skills/pdf/forms.md +294 -0
- package/skills/pdf/reference.md +612 -0
- package/skills/pdf/scripts/check_bounding_boxes.py +65 -0
- package/skills/pdf/scripts/check_fillable_fields.py +11 -0
- package/skills/pdf/scripts/convert_pdf_to_images.py +33 -0
- package/skills/pdf/scripts/create_validation_image.py +37 -0
- package/skills/pdf/scripts/extract_form_field_info.py +122 -0
- package/skills/pdf/scripts/extract_form_structure.py +115 -0
- package/skills/pdf/scripts/fill_fillable_fields.py +98 -0
- package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
- package/skills/pptx/LICENSE.txt +30 -0
- package/skills/pptx/SKILL.md +232 -0
- package/skills/pptx/VENDORED.md +32 -0
- package/skills/pptx/editing.md +205 -0
- package/skills/pptx/pptxgenjs.md +420 -0
- package/skills/pptx/scripts/__init__.py +0 -0
- package/skills/pptx/scripts/add_slide.py +195 -0
- package/skills/pptx/scripts/clean.py +286 -0
- package/skills/pptx/scripts/office/helpers/__init__.py +0 -0
- package/skills/pptx/scripts/office/helpers/merge_runs.py +199 -0
- package/skills/pptx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills/pptx/scripts/office/pack.py +159 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/pptx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/pptx/scripts/office/soffice.py +183 -0
- package/skills/pptx/scripts/office/unpack.py +132 -0
- package/skills/pptx/scripts/office/validate.py +111 -0
- package/skills/pptx/scripts/office/validators/__init__.py +15 -0
- package/skills/pptx/scripts/office/validators/base.py +847 -0
- package/skills/pptx/scripts/office/validators/docx.py +446 -0
- package/skills/pptx/scripts/office/validators/pptx.py +275 -0
- package/skills/pptx/scripts/office/validators/redlining.py +247 -0
- package/skills/pptx/scripts/thumbnail.py +289 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/SKILL.md +485 -0
- package/skills/skill-creator/VENDORED.md +32 -0
- package/skills/skill-creator/agents/analyzer.md +274 -0
- package/skills/skill-creator/agents/comparator.md +202 -0
- package/skills/skill-creator/agents/grader.md +223 -0
- package/skills/skill-creator/assets/eval_review.html +146 -0
- package/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/skills/skill-creator/references/schemas.md +430 -0
- package/skills/skill-creator/scripts/__init__.py +0 -0
- package/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/skills/skill-creator/scripts/generate_report.py +326 -0
- package/skills/skill-creator/scripts/improve_description.py +247 -0
- package/skills/skill-creator/scripts/package_skill.py +136 -0
- package/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/skills/skill-creator/scripts/run_eval.py +310 -0
- package/skills/skill-creator/scripts/run_loop.py +328 -0
- package/skills/skill-creator/scripts/utils.py +47 -0
- package/skills/switchroom-architecture/SKILL.md +60 -0
- package/skills/switchroom-architecture/cascade.md +112 -0
- package/skills/switchroom-architecture/sub-agents.md +87 -0
- package/skills/switchroom-architecture/telegram.md +94 -0
- package/skills/switchroom-cli/SKILL.md +274 -0
- package/skills/switchroom-health/SKILL.md +101 -0
- package/skills/switchroom-install/SKILL.md +116 -0
- package/skills/switchroom-manage/SKILL.md +90 -0
- package/skills/switchroom-status/SKILL.md +69 -0
- package/skills/switchroom-status/scripts/status.sh +69 -0
- package/skills/telegram-test-harness/SKILL.md +191 -0
- package/skills/token-helpers/SKILL.md +73 -0
- package/skills/token-helpers/scripts/google-cal-token.sh +62 -0
- package/skills/token-helpers/scripts/ms-graph-token.sh +70 -0
- package/skills/webapp-testing/LICENSE.txt +202 -0
- package/skills/webapp-testing/SKILL.md +96 -0
- package/skills/webapp-testing/VENDORED.md +32 -0
- package/skills/webapp-testing/examples/console_logging.py +35 -0
- package/skills/webapp-testing/examples/element_discovery.py +40 -0
- package/skills/webapp-testing/examples/static_html_automation.py +33 -0
- package/skills/webapp-testing/scripts/with_server.py +106 -0
- package/skills/xlsx/LICENSE.txt +30 -0
- package/skills/xlsx/SKILL.md +292 -0
- package/skills/xlsx/VENDORED.md +32 -0
- package/skills/xlsx/scripts/office/helpers/__init__.py +0 -0
- package/skills/xlsx/scripts/office/helpers/merge_runs.py +199 -0
- package/skills/xlsx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills/xlsx/scripts/office/pack.py +159 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/xlsx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/xlsx/scripts/office/soffice.py +183 -0
- package/skills/xlsx/scripts/office/unpack.py +132 -0
- package/skills/xlsx/scripts/office/validate.py +111 -0
- package/skills/xlsx/scripts/office/validators/__init__.py +15 -0
- package/skills/xlsx/scripts/office/validators/base.py +847 -0
- package/skills/xlsx/scripts/office/validators/docx.py +446 -0
- package/skills/xlsx/scripts/office/validators/pptx.py +275 -0
- package/skills/xlsx/scripts/office/validators/redlining.py +247 -0
- package/skills/xlsx/scripts/recalc.py +184 -0
- package/telegram-plugin/.claude-plugin/plugin.json +20 -0
- package/telegram-plugin/.mcp.json +14 -0
- package/telegram-plugin/LICENSE +21 -0
- package/telegram-plugin/README.md +352 -0
- package/telegram-plugin/active-pins-sweep.ts +204 -0
- package/telegram-plugin/active-pins.ts +146 -0
- package/telegram-plugin/active-reactions-sweep.ts +79 -0
- package/telegram-plugin/active-reactions.ts +134 -0
- package/telegram-plugin/admin-commands/dispatch.test.ts +149 -0
- package/telegram-plugin/admin-commands/index.ts +106 -0
- package/telegram-plugin/answer-stream.ts +565 -0
- package/telegram-plugin/ask-user.ts +179 -0
- package/telegram-plugin/attachment-path.ts +80 -0
- package/telegram-plugin/auth-code-redact.ts +83 -0
- package/telegram-plugin/auth-dashboard.ts +1104 -0
- package/telegram-plugin/auth-slot-parser.ts +497 -0
- package/telegram-plugin/auto-fallback-dispatcher.ts +68 -0
- package/telegram-plugin/auto-fallback.ts +348 -0
- package/telegram-plugin/bridge/bridge.ts +687 -0
- package/telegram-plugin/bridge/ipc-client.ts +326 -0
- package/telegram-plugin/bun.lock +218 -0
- package/telegram-plugin/card-format.ts +62 -0
- package/telegram-plugin/channel-envelope-safety.test.ts +56 -0
- package/telegram-plugin/channel-envelope-safety.ts +56 -0
- package/telegram-plugin/chat-lock.ts +65 -0
- package/telegram-plugin/context-exhaustion.ts +38 -0
- package/telegram-plugin/credits-watch.ts +220 -0
- package/telegram-plugin/dist/bridge/bridge.js +24758 -0
- package/telegram-plugin/dist/foreman/foreman.js +30723 -0
- package/telegram-plugin/dist/gateway/gateway.js +46497 -0
- package/telegram-plugin/dist/server.js +24551 -0
- package/telegram-plugin/dm-command-gate.ts +56 -0
- package/telegram-plugin/docs/gateway-server-split.md +133 -0
- package/telegram-plugin/docs/multi-agent-card-design.md +847 -0
- package/telegram-plugin/docs/pinned-progress-card-reliability.md +144 -0
- package/telegram-plugin/docs/stream-json-daemon-mode.md +477 -0
- package/telegram-plugin/docs/waiting-ux-spec.md +233 -0
- package/telegram-plugin/draft-stream.ts +442 -0
- package/telegram-plugin/draft-transport.ts +72 -0
- package/telegram-plugin/first-paint.ts +246 -0
- package/telegram-plugin/fleet-state.ts +246 -0
- package/telegram-plugin/foreman/foreman-create-flow.ts +202 -0
- package/telegram-plugin/foreman/foreman-handlers.ts +493 -0
- package/telegram-plugin/foreman/foreman.ts +1130 -0
- package/telegram-plugin/foreman/setup-flow.ts +345 -0
- package/telegram-plugin/foreman/setup-state.ts +239 -0
- package/telegram-plugin/foreman/state.ts +203 -0
- package/telegram-plugin/format.ts +685 -0
- package/telegram-plugin/gateway/access-validator.test.ts +95 -0
- package/telegram-plugin/gateway/access-validator.ts +37 -0
- package/telegram-plugin/gateway/boot-card.ts +582 -0
- package/telegram-plugin/gateway/boot-probes.ts +863 -0
- package/telegram-plugin/gateway/boot-reason.ts +51 -0
- package/telegram-plugin/gateway/boot-sweep-filter.test.ts +54 -0
- package/telegram-plugin/gateway/boot-sweep-filter.ts +32 -0
- package/telegram-plugin/gateway/clean-shutdown-marker.ts +183 -0
- package/telegram-plugin/gateway/disconnect-flush.ts +109 -0
- package/telegram-plugin/gateway/gateway.ts +10202 -0
- package/telegram-plugin/gateway/inbound-coalesce.ts +147 -0
- package/telegram-plugin/gateway/inject-handler.test.ts +221 -0
- package/telegram-plugin/gateway/inject-handler.ts +190 -0
- package/telegram-plugin/gateway/ipc-protocol.ts +151 -0
- package/telegram-plugin/gateway/ipc-server.ts +494 -0
- package/telegram-plugin/gateway/pid-file.ts +103 -0
- package/telegram-plugin/gateway/poll-health.ts +156 -0
- package/telegram-plugin/gateway/preamble-suppressor.ts +154 -0
- package/telegram-plugin/gateway/quota-cache.ts +125 -0
- package/telegram-plugin/gateway/resolve-calling-subagent.ts +78 -0
- package/telegram-plugin/gateway/restart-watchdog.ts +200 -0
- package/telegram-plugin/gateway/session-marker.ts +83 -0
- package/telegram-plugin/gateway/shutdown-drain.ts +162 -0
- package/telegram-plugin/gateway/startup-mutex.ts +285 -0
- package/telegram-plugin/gateway/startup-network-retry.ts +142 -0
- package/telegram-plugin/gateway/turn-active-marker.ts +176 -0
- package/telegram-plugin/gateway/unhandled-rejection-policy.ts +78 -0
- package/telegram-plugin/handoff-continuity.ts +200 -0
- package/telegram-plugin/history.ts +468 -0
- package/telegram-plugin/hooks/hooks.json +58 -0
- package/telegram-plugin/hooks/secret-guard-pretool.mjs +208 -0
- package/telegram-plugin/hooks/secret-scrub-stop.mjs +98 -0
- package/telegram-plugin/hooks/silent-end-interrupt-stop.mjs +111 -0
- package/telegram-plugin/hooks/subagent-tracker-posttool.mjs +296 -0
- package/telegram-plugin/hooks/subagent-tracker-pretool.mjs +261 -0
- package/telegram-plugin/html-sanitize.ts +244 -0
- package/telegram-plugin/idle-footer.ts +65 -0
- package/telegram-plugin/inline-keyboard-callbacks.ts +166 -0
- package/telegram-plugin/interrupt-marker.ts +66 -0
- package/telegram-plugin/issues-card.ts +371 -0
- package/telegram-plugin/issues-watcher.ts +125 -0
- package/telegram-plugin/model-unavailable.ts +325 -0
- package/telegram-plugin/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/telegram-plugin/operator-events-history.ts +94 -0
- package/telegram-plugin/operator-events.fixtures.json +161 -0
- package/telegram-plugin/operator-events.ts +421 -0
- package/telegram-plugin/package.json +55 -0
- package/telegram-plugin/permission-rule.ts +133 -0
- package/telegram-plugin/permission-title.ts +117 -0
- package/telegram-plugin/pin-event-log.ts +76 -0
- package/telegram-plugin/plugin-logger.ts +136 -0
- package/telegram-plugin/progress-card-driver.ts +2697 -0
- package/telegram-plugin/progress-card-pin-manager.ts +589 -0
- package/telegram-plugin/progress-card-pin-watchdog.ts +98 -0
- package/telegram-plugin/progress-card.ts +1409 -0
- package/telegram-plugin/pty-partial-handler.ts +247 -0
- package/telegram-plugin/pty-tail.ts +730 -0
- package/telegram-plugin/quota-check.ts +474 -0
- package/telegram-plugin/recent-outbound-dedup.ts +169 -0
- package/telegram-plugin/registry/api-registry.test.ts +201 -0
- package/telegram-plugin/registry/subagents-bugs.test.ts +454 -0
- package/telegram-plugin/registry/subagents-schema.ts +509 -0
- package/telegram-plugin/registry/subagents.test.ts +476 -0
- package/telegram-plugin/registry/turns-schema.test.ts +101 -0
- package/telegram-plugin/registry/turns-schema.ts +417 -0
- package/telegram-plugin/retry-api-call.ts +172 -0
- package/telegram-plugin/scripts/build.mjs +78 -0
- package/telegram-plugin/secret-detect/audit.ts +66 -0
- package/telegram-plugin/secret-detect/chunker.ts +37 -0
- package/telegram-plugin/secret-detect/entropy.ts +20 -0
- package/telegram-plugin/secret-detect/gitleaks-loader.ts +74 -0
- package/telegram-plugin/secret-detect/gitleaks.toml +27 -0
- package/telegram-plugin/secret-detect/index.ts +218 -0
- package/telegram-plugin/secret-detect/kv-scanner.ts +60 -0
- package/telegram-plugin/secret-detect/mask.ts +13 -0
- package/telegram-plugin/secret-detect/patterns.ts +115 -0
- package/telegram-plugin/secret-detect/pipeline.ts +144 -0
- package/telegram-plugin/secret-detect/rewrite.ts +26 -0
- package/telegram-plugin/secret-detect/secretlint-source.ts +95 -0
- package/telegram-plugin/secret-detect/slug.ts +44 -0
- package/telegram-plugin/secret-detect/staging.ts +85 -0
- package/telegram-plugin/secret-detect/suppressor.ts +34 -0
- package/telegram-plugin/secret-detect/url-redact.ts +60 -0
- package/telegram-plugin/secret-detect/vault-write.ts +56 -0
- package/telegram-plugin/server.js +41795 -0
- package/telegram-plugin/server.ts +171 -0
- package/telegram-plugin/session-tail.ts +884 -0
- package/telegram-plugin/shared/bot-runtime.ts +324 -0
- package/telegram-plugin/silent-reply.ts +58 -0
- package/telegram-plugin/slot-banner-driver.ts +147 -0
- package/telegram-plugin/slot-banner.ts +86 -0
- package/telegram-plugin/start.js +26 -0
- package/telegram-plugin/startup-reset.ts +45 -0
- package/telegram-plugin/status-reactions.ts +332 -0
- package/telegram-plugin/steering.ts +155 -0
- package/telegram-plugin/sticker-aliases.ts +249 -0
- package/telegram-plugin/stream-controller.ts +311 -0
- package/telegram-plugin/stream-reply-handler.ts +664 -0
- package/telegram-plugin/streaming-metrics.ts +134 -0
- package/telegram-plugin/streaming-report.ts +204 -0
- package/telegram-plugin/subagent-watcher.ts +880 -0
- package/telegram-plugin/telegram-button-constraints.ts +191 -0
- package/telegram-plugin/telegraph.ts +381 -0
- package/telegram-plugin/tests/HARNESS.md +340 -0
- package/telegram-plugin/tests/_progress-card-harness.ts +105 -0
- package/telegram-plugin/tests/active-pins-boot-reaper.test.ts +211 -0
- package/telegram-plugin/tests/active-pins-sweep.test.ts +309 -0
- package/telegram-plugin/tests/active-pins.test.ts +187 -0
- package/telegram-plugin/tests/active-reactions-sweep.test.ts +116 -0
- package/telegram-plugin/tests/active-reactions.test.ts +198 -0
- package/telegram-plugin/tests/answer-stream-dedup.test.ts +352 -0
- package/telegram-plugin/tests/answer-stream-silent-markers.test.ts +236 -0
- package/telegram-plugin/tests/answer-stream.test.ts +878 -0
- package/telegram-plugin/tests/ask-user.test.ts +203 -0
- package/telegram-plugin/tests/attachment-path.test.ts +199 -0
- package/telegram-plugin/tests/auth-account-identity-surface.test.ts +118 -0
- package/telegram-plugin/tests/auth-code-auto-capture.test.ts +144 -0
- package/telegram-plugin/tests/auth-code-redact.test.ts +248 -0
- package/telegram-plugin/tests/auth-dashboard-edge-cases.test.ts +260 -0
- package/telegram-plugin/tests/auth-dashboard-restart-flow.test.ts +140 -0
- package/telegram-plugin/tests/auth-dashboard-v3b.test.ts +559 -0
- package/telegram-plugin/tests/auth-dashboard.test.ts +1045 -0
- package/telegram-plugin/tests/auth-login-url-button.test.ts +122 -0
- package/telegram-plugin/tests/auth-slot-commands.test.ts +640 -0
- package/telegram-plugin/tests/auto-fallback-dispatcher.e2e.test.ts +183 -0
- package/telegram-plugin/tests/auto-fallback.test.ts +381 -0
- package/telegram-plugin/tests/boot-card-account-quota.test.ts +137 -0
- package/telegram-plugin/tests/boot-card-dedupe.test.ts +154 -0
- package/telegram-plugin/tests/boot-card-probe-target.test.ts +194 -0
- package/telegram-plugin/tests/boot-card-reason.test.ts +103 -0
- package/telegram-plugin/tests/boot-card-render.test.ts +219 -0
- package/telegram-plugin/tests/boot-probes.test.ts +451 -0
- package/telegram-plugin/tests/bot-api.harness.ts +116 -0
- package/telegram-plugin/tests/bot-runtime.test.ts +190 -0
- package/telegram-plugin/tests/bridge-anonymous-refuse.test.ts +60 -0
- package/telegram-plugin/tests/context-exhaustion.test.ts +114 -0
- package/telegram-plugin/tests/credits-watch.test.ts +221 -0
- package/telegram-plugin/tests/dm-command-gate.test.ts +176 -0
- package/telegram-plugin/tests/draft-stream.test.ts +752 -0
- package/telegram-plugin/tests/draft-transport.test.ts +141 -0
- package/telegram-plugin/tests/e2e.test.ts +436 -0
- package/telegram-plugin/tests/fake-bot-api.test.ts +213 -0
- package/telegram-plugin/tests/fake-bot-api.ts +617 -0
- package/telegram-plugin/tests/false-restart-banner.test.ts +253 -0
- package/telegram-plugin/tests/first-paint.test.ts +257 -0
- package/telegram-plugin/tests/fixtures/pty-tail-tmux-fragment.bin +6 -0
- package/telegram-plugin/tests/fixtures/service-log-current-claude-code.bin +3624 -0
- package/telegram-plugin/tests/fleet-state-watcher.test.ts +101 -0
- package/telegram-plugin/tests/fleet-state.test.ts +185 -0
- package/telegram-plugin/tests/foreman-create-flow.test.ts +359 -0
- package/telegram-plugin/tests/foreman-handlers.test.ts +347 -0
- package/telegram-plugin/tests/foreman-state.test.ts +164 -0
- package/telegram-plugin/tests/foreman-write-ops.test.ts +214 -0
- package/telegram-plugin/tests/gateway-409-retry-banner.test.ts +173 -0
- package/telegram-plugin/tests/gateway-boot-marker-clear.test.ts +72 -0
- package/telegram-plugin/tests/gateway-bridge.test.ts +811 -0
- package/telegram-plugin/tests/gateway-clean-shutdown-marker.test.ts +414 -0
- package/telegram-plugin/tests/gateway-disconnect-flush.test.ts +144 -0
- package/telegram-plugin/tests/gateway-message-validator.test.ts +133 -0
- package/telegram-plugin/tests/gateway-no-reply-single-emit.test.ts +103 -0
- package/telegram-plugin/tests/gateway-secret-detect.test.ts +127 -0
- package/telegram-plugin/tests/gateway-startup-mutex.test.ts +284 -0
- package/telegram-plugin/tests/gateway-startup-network-retry.test.ts +185 -0
- package/telegram-plugin/tests/gateway-startup-reset.test.ts +72 -0
- package/telegram-plugin/tests/gateway-update-placeholder-dispatch.test.ts +125 -0
- package/telegram-plugin/tests/handoff-continuity.test.ts +249 -0
- package/telegram-plugin/tests/harness-ordering-invariants.test.ts +243 -0
- package/telegram-plugin/tests/harness-parse-mode-validation.test.ts +114 -0
- package/telegram-plugin/tests/history.test.ts +364 -0
- package/telegram-plugin/tests/html-balanced.ts +63 -0
- package/telegram-plugin/tests/html-sanitize.test.ts +146 -0
- package/telegram-plugin/tests/idle-footer-wiring.test.ts +88 -0
- package/telegram-plugin/tests/idle-footer.test.ts +66 -0
- package/telegram-plugin/tests/inbound-coalesce.test.ts +127 -0
- package/telegram-plugin/tests/inline-keyboard-callbacks.test.ts +150 -0
- package/telegram-plugin/tests/interrupt-marker.test.ts +126 -0
- package/telegram-plugin/tests/ipc-protocol.test.ts +218 -0
- package/telegram-plugin/tests/ipc-server-anonymous-refuse.test.ts +82 -0
- package/telegram-plugin/tests/ipc-server-client.test.ts +323 -0
- package/telegram-plugin/tests/ipc-server-race.test.ts +183 -0
- package/telegram-plugin/tests/ipc-server-validate-operator.test.ts +91 -0
- package/telegram-plugin/tests/ipc-server-validate-pty-partial.test.ts +64 -0
- package/telegram-plugin/tests/ipc-server-validate-update-placeholder.test.ts +77 -0
- package/telegram-plugin/tests/ipc-validator.test.ts +274 -0
- package/telegram-plugin/tests/issues-card.test.ts +495 -0
- package/telegram-plugin/tests/issues-watcher.test.ts +165 -0
- package/telegram-plugin/tests/model-unavailable.test.ts +303 -0
- package/telegram-plugin/tests/multi-turn-continuity.test.ts +159 -0
- package/telegram-plugin/tests/operator-events-history.test.ts +125 -0
- package/telegram-plugin/tests/operator-events-session-tail.test.ts +192 -0
- package/telegram-plugin/tests/operator-events.test.ts +331 -0
- package/telegram-plugin/tests/outbound-ordering.test.ts +293 -0
- package/telegram-plugin/tests/parse-mode-rotation.test.ts +164 -0
- package/telegram-plugin/tests/permission-rule.test.ts +121 -0
- package/telegram-plugin/tests/permission-title.test.ts +106 -0
- package/telegram-plugin/tests/pin-event-log.test.ts +124 -0
- package/telegram-plugin/tests/plugin-logger.test.ts +97 -0
- package/telegram-plugin/tests/poll-health.test.ts +86 -0
- package/telegram-plugin/tests/preamble-suppressor.test.ts +285 -0
- package/telegram-plugin/tests/progress-card-api-failure-during-deferred.test.ts +73 -0
- package/telegram-plugin/tests/progress-card-close-paths-converge.test.ts +272 -0
- package/telegram-plugin/tests/progress-card-cross-turn.test.ts +258 -0
- package/telegram-plugin/tests/progress-card-dispose-preservepending.test.ts +81 -0
- package/telegram-plugin/tests/progress-card-draft-flag.test.ts +80 -0
- package/telegram-plugin/tests/progress-card-driver-eviction.test.ts +215 -0
- package/telegram-plugin/tests/progress-card-driver-fleet-shadow.test.ts +123 -0
- package/telegram-plugin/tests/progress-card-driver-force-complete-parent-done.test.ts +76 -0
- package/telegram-plugin/tests/progress-card-edit-timestamps-budget.test.ts +62 -0
- package/telegram-plugin/tests/progress-card-memory-bounds.test.ts +84 -0
- package/telegram-plugin/tests/progress-card-pin-failure-paths.test.ts +139 -0
- package/telegram-plugin/tests/progress-card-pin-manager.test.ts +773 -0
- package/telegram-plugin/tests/progress-card-pin-race-fast-turn.test.ts +66 -0
- package/telegram-plugin/tests/progress-card-pin-sidecar-partial-write.test.ts +64 -0
- package/telegram-plugin/tests/progress-card-pin-watchdog.test.ts +190 -0
- package/telegram-plugin/tests/progress-card-sigterm-pin-flush.test.ts +146 -0
- package/telegram-plugin/tests/progress-update.test.ts +236 -0
- package/telegram-plugin/tests/protocol-fixtures.test.ts +59 -0
- package/telegram-plugin/tests/protocol-fixtures.ts +198 -0
- package/telegram-plugin/tests/pty-partial-handler.test.ts +326 -0
- package/telegram-plugin/tests/pty-tail-real-fixture.test.ts +114 -0
- package/telegram-plugin/tests/pty-tail-tmux-fragment.test.ts +71 -0
- package/telegram-plugin/tests/pty-tail.test.ts +525 -0
- package/telegram-plugin/tests/quota-cache.test.ts +187 -0
- package/telegram-plugin/tests/quota-check.test.ts +622 -0
- package/telegram-plugin/tests/races.test.ts +842 -0
- package/telegram-plugin/tests/real-gateway-f1-ladder-integrity.test.ts +123 -0
- package/telegram-plugin/tests/real-gateway-f2-instant-draft.test.ts +82 -0
- package/telegram-plugin/tests/real-gateway-f3-late-card.test.ts +114 -0
- package/telegram-plugin/tests/real-gateway-harness.ts +699 -0
- package/telegram-plugin/tests/real-gateway-i6-turn-flush-replay-dedup.test.ts +313 -0
- package/telegram-plugin/tests/real-gateway-ipc-lifecycle.test.ts +299 -0
- package/telegram-plugin/tests/real-gateway-spec.test.ts +487 -0
- package/telegram-plugin/tests/real-gateway.smoke.test.ts +101 -0
- package/telegram-plugin/tests/recent-outbound-dedup.test.ts +192 -0
- package/telegram-plugin/tests/registry-turns.test.ts +432 -0
- package/telegram-plugin/tests/reply-terminal-reaction.test.ts +149 -0
- package/telegram-plugin/tests/resolve-calling-subagent.test.ts +269 -0
- package/telegram-plugin/tests/restart-watchdog.test.ts +224 -0
- package/telegram-plugin/tests/retry-api-call.test.ts +287 -0
- package/telegram-plugin/tests/secret-detect-audit.test.ts +58 -0
- package/telegram-plugin/tests/secret-detect-fail-closed.test.ts +83 -0
- package/telegram-plugin/tests/secret-detect-gitleaks.test.ts +32 -0
- package/telegram-plugin/tests/secret-detect-oauth-code.test.ts +308 -0
- package/telegram-plugin/tests/secret-detect-pipeline.test.ts +123 -0
- package/telegram-plugin/tests/secret-detect-secretlint.test.ts +101 -0
- package/telegram-plugin/tests/secret-detect-staging.test.ts +45 -0
- package/telegram-plugin/tests/secret-detect-suppressor-no-silent-allow.test.ts +67 -0
- package/telegram-plugin/tests/secret-detect.test.ts +223 -0
- package/telegram-plugin/tests/secret-guard-pretool.test.ts +194 -0
- package/telegram-plugin/tests/send-typing-action-validation.test.ts +61 -0
- package/telegram-plugin/tests/session-tail-capped.test.ts +285 -0
- package/telegram-plugin/tests/session-tail.test.ts +524 -0
- package/telegram-plugin/tests/setup-flow.test.ts +510 -0
- package/telegram-plugin/tests/setup-state.test.ts +146 -0
- package/telegram-plugin/tests/silent-reply-guard.test.ts +122 -0
- package/telegram-plugin/tests/slot-banner-driver.e2e.test.ts +350 -0
- package/telegram-plugin/tests/slot-banner.test.ts +74 -0
- package/telegram-plugin/tests/snapshot-serializer.ts +79 -0
- package/telegram-plugin/tests/spawn-detached-cgroup-escape.test.ts +51 -0
- package/telegram-plugin/tests/status-accent.test.ts +186 -0
- package/telegram-plugin/tests/status-reactions-allowed-filter.test.ts +132 -0
- package/telegram-plugin/tests/status-reactions.test.ts +314 -0
- package/telegram-plugin/tests/steering.test.ts +282 -0
- package/telegram-plugin/tests/sticker-aliases.test.ts +232 -0
- package/telegram-plugin/tests/stream-controller-html-fallback.test.ts +127 -0
- package/telegram-plugin/tests/stream-controller.test.ts +262 -0
- package/telegram-plugin/tests/stream-reply-error-paths.test.ts +208 -0
- package/telegram-plugin/tests/stream-reply-handler.test.ts +1292 -0
- package/telegram-plugin/tests/streaming-e2e.test.ts +389 -0
- package/telegram-plugin/tests/streaming-metrics.test.ts +201 -0
- package/telegram-plugin/tests/streaming-orchestration.test.ts +756 -0
- package/telegram-plugin/tests/subagent-registry-bugs.test.ts +725 -0
- package/telegram-plugin/tests/subagent-tracker-hooks.test.ts +213 -0
- package/telegram-plugin/tests/subagent-watcher-parent-marker.test.ts +274 -0
- package/telegram-plugin/tests/subagent-watcher-stall-notification.test.ts +243 -0
- package/telegram-plugin/tests/subagent-watcher.test.ts +877 -0
- package/telegram-plugin/tests/subagents-schema-init-order.test.ts +109 -0
- package/telegram-plugin/tests/sync-chat-running-subagents.test.ts +116 -0
- package/telegram-plugin/tests/telegram-button-constraints.test.ts +194 -0
- package/telegram-plugin/tests/telegram-format.test.ts +1093 -0
- package/telegram-plugin/tests/telegraph.test.ts +246 -0
- package/telegram-plugin/tests/tool-labels.test.ts +383 -0
- package/telegram-plugin/tests/turn-active-marker.test.ts +195 -0
- package/telegram-plugin/tests/turn-end-regressions.test.ts +489 -0
- package/telegram-plugin/tests/turn-flush-card-takeover.test.ts +218 -0
- package/telegram-plugin/tests/turn-flush-dedup-controller.test.ts +144 -0
- package/telegram-plugin/tests/turn-flush-prose-recovery.test.ts +78 -0
- package/telegram-plugin/tests/turn-flush-safety.test.ts +189 -0
- package/telegram-plugin/tests/turn-signal-tracker.test.ts +107 -0
- package/telegram-plugin/tests/turns-writer.test.ts +323 -0
- package/telegram-plugin/tests/two-zone-bg-carry-full-lifecycle.test.ts +131 -0
- package/telegram-plugin/tests/two-zone-bg-detection.test.ts +120 -0
- package/telegram-plugin/tests/two-zone-bg-done-when-all-terminal.test.ts +114 -0
- package/telegram-plugin/tests/two-zone-bg-early-turn-end.test.ts +87 -0
- package/telegram-plugin/tests/two-zone-bg-survives-next-turn.test.ts +211 -0
- package/telegram-plugin/tests/two-zone-card-cap.test.ts +62 -0
- package/telegram-plugin/tests/two-zone-card-fleet-row.test.ts +101 -0
- package/telegram-plugin/tests/two-zone-card-header-phases.test.ts +68 -0
- package/telegram-plugin/tests/two-zone-card-html-balance.test.ts +110 -0
- package/telegram-plugin/tests/two-zone-card-lifecycle.test.ts +128 -0
- package/telegram-plugin/tests/two-zone-card-sanitise.test.ts +58 -0
- package/telegram-plugin/tests/two-zone-card-snapshot.test.ts +133 -0
- package/telegram-plugin/tests/two-zone-concurrent-turns-isolation.test.ts +155 -0
- package/telegram-plugin/tests/two-zone-phasefor-precedence.test.ts +117 -0
- package/telegram-plugin/tests/two-zone-snapshot-extras.test.ts +143 -0
- package/telegram-plugin/tests/two-zone-stuck-edit-throttle.test.ts +149 -0
- package/telegram-plugin/tests/two-zone-stuck-header-escalation.test.ts +101 -0
- package/telegram-plugin/tests/two-zone-stuck-per-member.test.ts +114 -0
- package/telegram-plugin/tests/two-zone-stuck-recovery.test.ts +105 -0
- package/telegram-plugin/tests/typing-wrap.test.ts +141 -0
- package/telegram-plugin/tests/unhandled-rejection-policy.test.ts +147 -0
- package/telegram-plugin/tests/update-factory-edited-and-reactions.test.ts +108 -0
- package/telegram-plugin/tests/update-factory.ts +305 -0
- package/telegram-plugin/tests/vault-grant-wizard.test.ts +84 -0
- package/telegram-plugin/tests/vault-grants-revoke.test.ts +265 -0
- package/telegram-plugin/tests/vault-subcommands.test.ts +234 -0
- package/telegram-plugin/tests/voice-transcribe.test.ts +196 -0
- package/telegram-plugin/tests/waiting-ux-harness.ts +381 -0
- package/telegram-plugin/tests/waiting-ux.e2e.test.ts +233 -0
- package/telegram-plugin/tests/welcome-text.test.ts +407 -0
- package/telegram-plugin/tool-error-filter.ts +89 -0
- package/telegram-plugin/tool-labels.ts +330 -0
- package/telegram-plugin/tool-names.ts +53 -0
- package/telegram-plugin/turn-flush-prose-recovery.ts +40 -0
- package/telegram-plugin/turn-flush-safety.ts +109 -0
- package/telegram-plugin/turn-signal-tracker.ts +79 -0
- package/telegram-plugin/two-zone-card.ts +249 -0
- package/telegram-plugin/typing-wrap.ts +92 -0
- package/telegram-plugin/voice-transcribe.ts +166 -0
- package/telegram-plugin/welcome-text.ts +359 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression: TTL eviction of internal dedup maps must NOT depend on the
|
|
3
|
+
* heartbeat tick. The heartbeat stops whenever `chats.size === 0`, so any
|
|
4
|
+
* eviction inside it leaves `seenEnqueueMsgIds` and `pendingSyncEchoes` to
|
|
5
|
+
* grow unbounded across idle periods. Outer-base-key entries
|
|
6
|
+
* (`chatRunningSubagents`, `baseTurnSeqs`) likewise need an explicit
|
|
7
|
+
* cleanup hook on chat-close because nothing else ever drops them.
|
|
8
|
+
*
|
|
9
|
+
* Fix shape: an inline throttled `maybeEvict(now)` runs at the top of
|
|
10
|
+
* every public ingress, and `completeTurnFully` calls
|
|
11
|
+
* `cleanupBaseKeyIfUnused` after `chats.delete`.
|
|
12
|
+
*/
|
|
13
|
+
import { describe, it, expect } from 'vitest'
|
|
14
|
+
import { createProgressDriver } from '../progress-card-driver.js'
|
|
15
|
+
import type { SessionEvent } from '../session-tail.js'
|
|
16
|
+
|
|
17
|
+
let nextMsgId = 9000
|
|
18
|
+
|
|
19
|
+
function harness() {
|
|
20
|
+
let now = 1000
|
|
21
|
+
const timers: Array<{ fireAt: number; fn: () => void; ref: number; repeat?: number }> = []
|
|
22
|
+
let nextRef = 0
|
|
23
|
+
const emits: Array<{ chatId: string; threadId?: string; turnKey: string; html: string; done: boolean }> = []
|
|
24
|
+
|
|
25
|
+
const driver = createProgressDriver({
|
|
26
|
+
emit: (a) => emits.push(a),
|
|
27
|
+
minIntervalMs: 0,
|
|
28
|
+
coalesceMs: 0,
|
|
29
|
+
initialDelayMs: 0,
|
|
30
|
+
heartbeatMs: 5000,
|
|
31
|
+
now: () => now,
|
|
32
|
+
setTimeout: (fn, ms) => {
|
|
33
|
+
const ref = nextRef++
|
|
34
|
+
timers.push({ fireAt: now + ms, fn, ref })
|
|
35
|
+
return { ref }
|
|
36
|
+
},
|
|
37
|
+
clearTimeout: (handle) => {
|
|
38
|
+
const target = (handle as { ref: number }).ref
|
|
39
|
+
const idx = timers.findIndex((t) => t.ref === target)
|
|
40
|
+
if (idx !== -1) timers.splice(idx, 1)
|
|
41
|
+
},
|
|
42
|
+
setInterval: (fn, ms) => {
|
|
43
|
+
const ref = nextRef++
|
|
44
|
+
timers.push({ fireAt: now + ms, fn, ref, repeat: ms })
|
|
45
|
+
return { ref }
|
|
46
|
+
},
|
|
47
|
+
clearInterval: (handle) => {
|
|
48
|
+
const target = (handle as { ref: number }).ref
|
|
49
|
+
const idx = timers.findIndex((t) => t.ref === target)
|
|
50
|
+
if (idx !== -1) timers.splice(idx, 1)
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const advance = (ms: number): void => {
|
|
55
|
+
now += ms
|
|
56
|
+
for (;;) {
|
|
57
|
+
timers.sort((a, b) => a.fireAt - b.fireAt)
|
|
58
|
+
const next = timers[0]
|
|
59
|
+
if (!next || next.fireAt > now) break
|
|
60
|
+
if (next.repeat != null) {
|
|
61
|
+
next.fireAt += next.repeat
|
|
62
|
+
next.fn()
|
|
63
|
+
} else {
|
|
64
|
+
timers.shift()
|
|
65
|
+
next.fn()
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return { driver, emits, advance, getNow: () => now }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function enqueue(chatId: string, threadId?: string): SessionEvent {
|
|
74
|
+
return {
|
|
75
|
+
kind: 'enqueue',
|
|
76
|
+
chatId,
|
|
77
|
+
messageId: String(nextMsgId++),
|
|
78
|
+
threadId: threadId ?? null,
|
|
79
|
+
rawContent: `<channel chat_id="${chatId}">hi</channel>`,
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
describe('progress-card-driver: TTL eviction off the heartbeat', () => {
|
|
84
|
+
it('seenEnqueueMsgIds and pendingSyncEchoes stay bounded across idle periods (chats.size==0)', () => {
|
|
85
|
+
const { driver, advance } = harness()
|
|
86
|
+
const maps = driver._debugGetMaps!()
|
|
87
|
+
|
|
88
|
+
// Drive 20 turn enqueue->complete cycles, advancing past the 60s TTL
|
|
89
|
+
// between cycles. Critically, chats.size returns to 0 between cycles,
|
|
90
|
+
// so the heartbeat stops — exposing the leak the fix targets.
|
|
91
|
+
for (let i = 0; i < 20; i++) {
|
|
92
|
+
driver.ingest(enqueue('chatA'), null)
|
|
93
|
+
driver.ingest({ kind: 'turn_end', durationMs: 100 }, 'chatA')
|
|
94
|
+
// Advance well past both TTLs (60s for messageIds, 30s for echoes)
|
|
95
|
+
// and past the eviction throttle (30s) so the next ingest evicts.
|
|
96
|
+
advance(65_000)
|
|
97
|
+
expect(maps.chats.size).toBe(0)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// After 20 cycles spread across >20 minutes of fake time, both dedup
|
|
101
|
+
// maps must be tiny — they should never accumulate stale entries.
|
|
102
|
+
expect(maps.seenEnqueueMsgIds.size).toBeLessThanOrEqual(1)
|
|
103
|
+
expect(maps.pendingSyncEchoes.size).toBeLessThanOrEqual(1)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('chatRunningSubagents and baseTurnSeqs drop their base-key on full chat close', () => {
|
|
107
|
+
const { driver, advance } = harness()
|
|
108
|
+
const maps = driver._debugGetMaps!()
|
|
109
|
+
|
|
110
|
+
for (let i = 0; i < 20; i++) {
|
|
111
|
+
driver.ingest(enqueue('chatA'), null)
|
|
112
|
+
driver.ingest({ kind: 'sub_agent_started', agentId: `agent-${i}`, firstPromptText: 'x' }, 'chatA')
|
|
113
|
+
driver.ingest({ kind: 'sub_agent_turn_end', agentId: `agent-${i}`, durationMs: 50 }, 'chatA')
|
|
114
|
+
driver.ingest({ kind: 'turn_end', durationMs: 100 }, 'chatA')
|
|
115
|
+
advance(65_000)
|
|
116
|
+
// Between turns, no chat is alive — outer base-key entries must be
|
|
117
|
+
// gone too.
|
|
118
|
+
expect(maps.chats.size).toBe(0)
|
|
119
|
+
expect(maps.chatRunningSubagents.size).toBe(0)
|
|
120
|
+
expect(maps.baseTurnSeqs.size).toBe(0)
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('two chats sharing a baseKey: closing one does NOT delete the shared outer key', () => {
|
|
125
|
+
// baseKey collapses (chatId, threadId) pairs with no thread to a single
|
|
126
|
+
// string. Two threads on the same chat share a base only if they have
|
|
127
|
+
// the same threadId; two distinct chatIds always have distinct bases.
|
|
128
|
+
// Within a single chat, multiple concurrent turn-keys share the same
|
|
129
|
+
// base — closing one of them must NOT prematurely drop the outer key
|
|
130
|
+
// while the other turn is still alive.
|
|
131
|
+
const { driver } = harness()
|
|
132
|
+
const maps = driver._debugGetMaps!()
|
|
133
|
+
|
|
134
|
+
// Start turn 1 on chatA — synthesises an enqueue and creates the card.
|
|
135
|
+
driver.startTurn({ chatId: 'chatA', userText: 'first' })
|
|
136
|
+
expect(maps.chats.size).toBe(1)
|
|
137
|
+
expect(maps.baseTurnSeqs.get('chatA')).toBeGreaterThanOrEqual(1)
|
|
138
|
+
|
|
139
|
+
// A second startTurn on the same chat force-closes turn 1 and creates
|
|
140
|
+
// turn 2 — there is exactly one chat live again, but baseTurnSeqs has
|
|
141
|
+
// ticked to 2. That outer entry must remain because turn 2 is alive.
|
|
142
|
+
driver.startTurn({ chatId: 'chatA', userText: 'second' })
|
|
143
|
+
expect(maps.chats.size).toBe(1)
|
|
144
|
+
const seqAfter = maps.baseTurnSeqs.get('chatA')
|
|
145
|
+
expect(seqAfter).toBeGreaterThanOrEqual(2)
|
|
146
|
+
|
|
147
|
+
// End turn 2 → chats empty → base-key cleanup must run.
|
|
148
|
+
driver.ingest({ kind: 'turn_end', durationMs: 100 }, 'chatA')
|
|
149
|
+
expect(maps.chats.size).toBe(0)
|
|
150
|
+
expect(maps.baseTurnSeqs.has('chatA')).toBe(false)
|
|
151
|
+
expect(maps.chatRunningSubagents.has('chatA')).toBe(false)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('two distinct chats: closing one does NOT touch the other base-key', () => {
|
|
155
|
+
// The driver routes turn_end via `currentTurnKey`, not `chatIdMaybe` —
|
|
156
|
+
// a quirk of the session-tail single-stream design. To close a specific
|
|
157
|
+
// chat from a test we use `forceCompleteTurn`, which is the path the
|
|
158
|
+
// gateway invokes for explicit per-chat fan-out.
|
|
159
|
+
const { driver } = harness()
|
|
160
|
+
const maps = driver._debugGetMaps!()
|
|
161
|
+
|
|
162
|
+
driver.ingest(enqueue('chatA'), null)
|
|
163
|
+
driver.ingest(enqueue('chatB'), null)
|
|
164
|
+
expect(maps.chats.size).toBe(2)
|
|
165
|
+
expect(maps.baseTurnSeqs.has('chatA')).toBe(true)
|
|
166
|
+
expect(maps.baseTurnSeqs.has('chatB')).toBe(true)
|
|
167
|
+
|
|
168
|
+
// Close A only — must not touch chatB's base-key.
|
|
169
|
+
driver.forceCompleteTurn({ chatId: 'chatA' })
|
|
170
|
+
expect(maps.baseTurnSeqs.has('chatA')).toBe(false)
|
|
171
|
+
expect(maps.baseTurnSeqs.has('chatB')).toBe(true)
|
|
172
|
+
|
|
173
|
+
// Now close B.
|
|
174
|
+
driver.forceCompleteTurn({ chatId: 'chatB' })
|
|
175
|
+
expect(maps.baseTurnSeqs.has('chatB')).toBe(false)
|
|
176
|
+
expect(maps.chats.size).toBe(0)
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
it('PR-C2 follow-up: bg-subagent-carry guard — chatRunningSubagents inner map survives turn_end while a sub-agent is still in flight', () => {
|
|
180
|
+
// When parent turn_end fires but a sub-agent is still running, the
|
|
181
|
+
// chatState enters pendingCompletion and the per-base
|
|
182
|
+
// `chatRunningSubagents` inner map MUST NOT be cleaned up — the
|
|
183
|
+
// next turn's enqueue will clone it back into the new fleet
|
|
184
|
+
// (issue #334 / #64). Cleanup on close is gated on the inner map
|
|
185
|
+
// being empty.
|
|
186
|
+
const { driver } = harness()
|
|
187
|
+
const maps = driver._debugGetMaps!()
|
|
188
|
+
|
|
189
|
+
driver.ingest(enqueue('chatA'), null)
|
|
190
|
+
driver.ingest(
|
|
191
|
+
{
|
|
192
|
+
kind: 'tool_use', toolName: 'Agent', toolUseId: 'tu1',
|
|
193
|
+
input: { prompt: 'bg', run_in_background: true },
|
|
194
|
+
},
|
|
195
|
+
'chatA',
|
|
196
|
+
)
|
|
197
|
+
driver.ingest({ kind: 'sub_agent_started', agentId: 'saBG', firstPromptText: 'bg' }, 'chatA')
|
|
198
|
+
driver.ingest({ kind: 'tool_use', toolName: 'mcp__switchroom-telegram__reply' }, 'chatA')
|
|
199
|
+
driver.recordOutboundDelivered('chatA')
|
|
200
|
+
driver.ingest({ kind: 'turn_end', durationMs: 100 }, 'chatA')
|
|
201
|
+
|
|
202
|
+
// Pending — chats.size==1 (originating bg-pending state survives).
|
|
203
|
+
expect(maps.chats.size).toBe(1)
|
|
204
|
+
// Critical: the running-subagents inner map for 'chatA' must still
|
|
205
|
+
// contain saBG. If cleanupBaseKeyIfUnused regressed and ran here,
|
|
206
|
+
// the next turn would lose the bg carry.
|
|
207
|
+
expect(maps.chatRunningSubagents.get('chatA')?.has('saBG')).toBe(true)
|
|
208
|
+
|
|
209
|
+
// Resolve the bg sub-agent; now full close should also drain the
|
|
210
|
+
// sync registry inner map.
|
|
211
|
+
driver.ingest({ kind: 'sub_agent_turn_end', agentId: 'saBG' }, 'chatA')
|
|
212
|
+
expect(maps.chats.size).toBe(0)
|
|
213
|
+
expect(maps.chatRunningSubagents.has('chatA')).toBe(false)
|
|
214
|
+
})
|
|
215
|
+
})
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P0 of #662 — invariant test that the driver's `fleet` shadow Map
|
|
3
|
+
* stays in lockstep with the legacy `chatState.subAgents` map across a
|
|
4
|
+
* full sub-agent lifecycle.
|
|
5
|
+
*
|
|
6
|
+
* We drive the real driver via createProgressDriver (no Telegram bot
|
|
7
|
+
* required — the emit callback just records calls) and feed a complete
|
|
8
|
+
* lifecycle: started → 3× tool_use → tool_result(isError=true) →
|
|
9
|
+
* turn_end. After every event we assert:
|
|
10
|
+
* - cardinality matches between fleet and subAgents
|
|
11
|
+
* - on terminal turn_end: status='failed' (errorSeen accumulated)
|
|
12
|
+
* - originatingTurnKey was snapshotted from currentTurnKey
|
|
13
|
+
* - lastTool reflects the most recent tool_use's sanitised arg
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { describe, it, expect } from 'vitest'
|
|
17
|
+
import { createProgressDriver } from '../progress-card-driver.js'
|
|
18
|
+
import type { SessionEvent } from '../session-tail.js'
|
|
19
|
+
|
|
20
|
+
function harness() {
|
|
21
|
+
let now = 1000
|
|
22
|
+
const timers: Array<{ fireAt: number; fn: () => void; ref: number; repeat?: number }> = []
|
|
23
|
+
let nextRef = 0
|
|
24
|
+
const driver = createProgressDriver({
|
|
25
|
+
emit: () => {},
|
|
26
|
+
minIntervalMs: 500,
|
|
27
|
+
coalesceMs: 400,
|
|
28
|
+
initialDelayMs: 0,
|
|
29
|
+
promoteAfterMs: 999_999,
|
|
30
|
+
now: () => now,
|
|
31
|
+
setTimeout: (fn, ms) => {
|
|
32
|
+
const ref = nextRef++
|
|
33
|
+
timers.push({ fireAt: now + ms, fn, ref })
|
|
34
|
+
return { ref }
|
|
35
|
+
},
|
|
36
|
+
clearTimeout: (h) => {
|
|
37
|
+
const ref = (h as { ref: number }).ref
|
|
38
|
+
const idx = timers.findIndex((t) => t.ref === ref)
|
|
39
|
+
if (idx !== -1) timers.splice(idx, 1)
|
|
40
|
+
},
|
|
41
|
+
setInterval: (fn, ms) => {
|
|
42
|
+
const ref = nextRef++
|
|
43
|
+
timers.push({ fireAt: now + ms, fn, ref, repeat: ms })
|
|
44
|
+
return { ref }
|
|
45
|
+
},
|
|
46
|
+
clearInterval: (h) => {
|
|
47
|
+
const ref = (h as { ref: number }).ref
|
|
48
|
+
const idx = timers.findIndex((t) => t.ref === ref)
|
|
49
|
+
if (idx !== -1) timers.splice(idx, 1)
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
return { driver, advance: (ms: number) => { now += ms } }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const enqueue = (chatId: string): SessionEvent => ({
|
|
56
|
+
kind: 'enqueue',
|
|
57
|
+
chatId,
|
|
58
|
+
messageId: '1',
|
|
59
|
+
threadId: null,
|
|
60
|
+
rawContent: `<channel chat_id="${chatId}">go</channel>`,
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
describe('driver fleet-state shadow', () => {
|
|
64
|
+
it('shadow Map stays in lockstep with chatState.subAgents through a failed sub-agent lifecycle', () => {
|
|
65
|
+
const { driver } = harness()
|
|
66
|
+
const CHAT = 'c1'
|
|
67
|
+
driver.ingest(enqueue(CHAT), null)
|
|
68
|
+
|
|
69
|
+
const events: SessionEvent[] = [
|
|
70
|
+
{ kind: 'sub_agent_started', agentId: 'sa1', firstPromptText: 'do work', subagentType: 'worker' },
|
|
71
|
+
{ kind: 'sub_agent_tool_use', agentId: 'sa1', toolUseId: 't1', toolName: 'Read', input: { file_path: '/etc/secrets/k.key' } },
|
|
72
|
+
{ kind: 'sub_agent_tool_use', agentId: 'sa1', toolUseId: 't2', toolName: 'Bash', input: { command: 'ls' } },
|
|
73
|
+
{ kind: 'sub_agent_tool_use', agentId: 'sa1', toolUseId: 't3', toolName: 'Edit', input: { file_path: '/tmp/x.ts' } },
|
|
74
|
+
{ kind: 'sub_agent_tool_result', agentId: 'sa1', toolUseId: 't3', isError: true, errorText: 'boom' },
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
for (const ev of events) {
|
|
78
|
+
driver.ingest(ev, CHAT)
|
|
79
|
+
const state = driver.peek(CHAT)
|
|
80
|
+
const fleet = driver.peekFleet(CHAT)
|
|
81
|
+
expect(state).toBeDefined()
|
|
82
|
+
expect(fleet).toBeDefined()
|
|
83
|
+
// Cardinality invariant — every sub-agent in the legacy map has a
|
|
84
|
+
// shadow entry, and vice versa.
|
|
85
|
+
expect(fleet!.size).toBe(state!.subAgents.size)
|
|
86
|
+
for (const id of state!.subAgents.keys()) {
|
|
87
|
+
expect(fleet!.has(id)).toBe(true)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Pre-turn-end: fleet member exists, status still running, errorSeen true.
|
|
92
|
+
const midFleet = driver.peekFleet(CHAT)!
|
|
93
|
+
const midMember = midFleet.get('sa1')!
|
|
94
|
+
expect(midMember.status).toBe('running')
|
|
95
|
+
expect(midMember.errorSeen).toBe(true)
|
|
96
|
+
expect(midMember.toolCount).toBe(3)
|
|
97
|
+
expect(midMember.lastTool).toEqual({ name: 'Edit', sanitisedArg: 'x.ts' })
|
|
98
|
+
expect(midMember.role).toBe('worker') // from subagentType fallback
|
|
99
|
+
// Snapshotted from currentTurnKey at sub_agent_started.
|
|
100
|
+
expect(midMember.originatingTurnKey).toMatch(/^c1:/)
|
|
101
|
+
|
|
102
|
+
// Now end the sub-agent's turn — fleet member should flip to failed.
|
|
103
|
+
driver.ingest({ kind: 'sub_agent_turn_end', agentId: 'sa1' }, CHAT)
|
|
104
|
+
const finalFleet = driver.peekFleet(CHAT)!
|
|
105
|
+
const finalMember = finalFleet.get('sa1')!
|
|
106
|
+
expect(finalMember.status).toBe('failed')
|
|
107
|
+
expect(finalMember.terminalAt).not.toBeNull()
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('uses description as role when present', () => {
|
|
111
|
+
const { driver } = harness()
|
|
112
|
+
driver.ingest(enqueue('c2'), null)
|
|
113
|
+
// session-tail's sub_agent_started doesn't carry description directly,
|
|
114
|
+
// but the watcher path supplies subagentType — verify the fallback chain
|
|
115
|
+
// works when neither is set: first 20 chars of firstPromptText.
|
|
116
|
+
driver.ingest(
|
|
117
|
+
{ kind: 'sub_agent_started', agentId: 'sa2', firstPromptText: 'investigate the auth bug end-to-end' },
|
|
118
|
+
'c2',
|
|
119
|
+
)
|
|
120
|
+
const m = driver.peekFleet('c2')!.get('sa2')!
|
|
121
|
+
expect(m.role).toBe('investigate the auth')
|
|
122
|
+
})
|
|
123
|
+
})
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression: forceCompleteTurn must set `parentTurnEndAt` so the heartbeat's
|
|
3
|
+
* `parentDone` branch lights up and the elapsed counter keeps ticking through
|
|
4
|
+
* `subAgentTickIntervalMs` while sub-agents are still running.
|
|
5
|
+
*
|
|
6
|
+
* Bug shape (#686, fixed in #687): forceCompleteTurn reduced `turn_end` but
|
|
7
|
+
* never set `parentTurnEndAt`. The heartbeat's `parentDone` was therefore
|
|
8
|
+
* always false during the deferred-unpin window, the elapsed-ticker bypass
|
|
9
|
+
* never engaged, and the rendered card froze on its last emit until the
|
|
10
|
+
* sub-agents finished.
|
|
11
|
+
*
|
|
12
|
+
* Test shape: spawn a sub-agent, call forceCompleteTurn, then advance fake
|
|
13
|
+
* time across several heartbeat ticks. The "Done" header (parentDone branch
|
|
14
|
+
* of the renderer) MUST appear and elapsed time MUST keep advancing in the
|
|
15
|
+
* emitted HTML.
|
|
16
|
+
*/
|
|
17
|
+
import { describe, it, expect } from 'vitest'
|
|
18
|
+
import { makeHarness, enqueue } from './_progress-card-harness.js'
|
|
19
|
+
|
|
20
|
+
describe('progress-card-driver: forceCompleteTurn unfreezes elapsed-ticker', () => {
|
|
21
|
+
it('parentDone engages and elapsed advances after forceCompleteTurn while a sub-agent is still running', () => {
|
|
22
|
+
const { driver, emits, advance } = makeHarness({
|
|
23
|
+
minIntervalMs: 0,
|
|
24
|
+
coalesceMs: 0,
|
|
25
|
+
heartbeatMs: 1_000,
|
|
26
|
+
})
|
|
27
|
+
const CHAT = 'chatF'
|
|
28
|
+
|
|
29
|
+
driver.ingest(enqueue(CHAT), null)
|
|
30
|
+
driver.ingest(
|
|
31
|
+
{
|
|
32
|
+
kind: 'tool_use',
|
|
33
|
+
toolName: 'Agent',
|
|
34
|
+
toolUseId: 'tu1',
|
|
35
|
+
input: { prompt: 'bg work', run_in_background: true },
|
|
36
|
+
},
|
|
37
|
+
CHAT,
|
|
38
|
+
)
|
|
39
|
+
driver.ingest({ kind: 'sub_agent_started', agentId: 'saBG', firstPromptText: 'bg work' }, CHAT)
|
|
40
|
+
driver.ingest({ kind: 'tool_use', toolName: 'mcp__switchroom-telegram__reply' }, CHAT)
|
|
41
|
+
driver.recordOutboundDelivered(CHAT)
|
|
42
|
+
|
|
43
|
+
// External completion signal (e.g. stream_reply done=true). Sub-agent
|
|
44
|
+
// is still running, so the chatState enters pendingCompletion and the
|
|
45
|
+
// heartbeat keeps the card alive.
|
|
46
|
+
driver.forceCompleteTurn({ chatId: CHAT })
|
|
47
|
+
|
|
48
|
+
// The flush triggered by forceCompleteTurn itself produces an emit
|
|
49
|
+
// with the parentDone-branch ("Done") header.
|
|
50
|
+
const emitsAfterForce = emits.length
|
|
51
|
+
expect(emitsAfterForce).toBeGreaterThan(0)
|
|
52
|
+
const renderedAtForce = emits[emitsAfterForce - 1].html
|
|
53
|
+
// The renderer surfaces "Background" once parentDone=true and a bg
|
|
54
|
+
// sub-agent is still running; if the bug regresses (parentTurnEndAt
|
|
55
|
+
// stays null), parentDone is false and we'd see "Working".
|
|
56
|
+
expect(renderedAtForce).toMatch(/Background/)
|
|
57
|
+
expect(renderedAtForce).not.toMatch(/Working/)
|
|
58
|
+
|
|
59
|
+
// Advance well past the elapsed-ticker interval to prove the
|
|
60
|
+
// heartbeat keeps emitting fresh elapsed values rather than freezing
|
|
61
|
+
// on the last emit. Several ticks should produce at least one extra
|
|
62
|
+
// emit with different rendered HTML.
|
|
63
|
+
advance(15_000)
|
|
64
|
+
const tailEmits = emits.slice(emitsAfterForce)
|
|
65
|
+
expect(tailEmits.length).toBeGreaterThan(0)
|
|
66
|
+
// At least one post-force emit must differ from the force-emit HTML —
|
|
67
|
+
// proving the elapsed counter advanced rather than freezing.
|
|
68
|
+
const advanced = tailEmits.some((e) => e.html !== renderedAtForce)
|
|
69
|
+
expect(advanced).toBe(true)
|
|
70
|
+
|
|
71
|
+
// Resolve the sub-agent and assert the deferred completion fires.
|
|
72
|
+
driver.ingest({ kind: 'sub_agent_turn_end', agentId: 'saBG' }, CHAT)
|
|
73
|
+
const finalEmit = emits[emits.length - 1]
|
|
74
|
+
expect(finalEmit.done).toBe(true)
|
|
75
|
+
})
|
|
76
|
+
})
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PR-C2 — `editTimestamps` sliding-window cleanup must keep the array
|
|
3
|
+
* bounded under sustained burst.
|
|
4
|
+
*
|
|
5
|
+
* The driver maintains a per-turn array of recent emit timestamps and
|
|
6
|
+
* uses its length within the trailing 60s to flip "hot" mode (longer
|
|
7
|
+
* coalesce window). The cleanup is `while (arr[0] < cutoff) arr.shift()`,
|
|
8
|
+
* which only fires when `recordEdit` or `isBudgetHot` is called. If
|
|
9
|
+
* that cleanup ever regresses, the array would grow unbounded across a
|
|
10
|
+
* long-running turn.
|
|
11
|
+
*
|
|
12
|
+
* fails when: the `arr.shift()` cleanup is removed from `recordEdit` or
|
|
13
|
+
* `isBudgetHot`, OR the cutoff window is widened beyond 60s without a
|
|
14
|
+
* matching upper bound.
|
|
15
|
+
*/
|
|
16
|
+
import { describe, it, expect } from 'vitest'
|
|
17
|
+
import { makeHarness, enqueue } from './_progress-card-harness.js'
|
|
18
|
+
|
|
19
|
+
describe('PR-C2: editTimestamps stays bounded under sustained emit burst', () => {
|
|
20
|
+
it('after 100 emits spread across 5 minutes, the per-turn array holds <= ~window-worth', () => {
|
|
21
|
+
// Use very low coalesce so each ingest can drive an emit. Keep the
|
|
22
|
+
// turn open for the whole burst.
|
|
23
|
+
const { driver, advance } = makeHarness({
|
|
24
|
+
minIntervalMs: 0,
|
|
25
|
+
coalesceMs: 0,
|
|
26
|
+
heartbeatMs: 999_999, // never auto-fire heartbeat
|
|
27
|
+
promoteAfterMs: 999_999,
|
|
28
|
+
})
|
|
29
|
+
const maps = driver._debugGetMaps!()
|
|
30
|
+
|
|
31
|
+
driver.ingest(enqueue('cA'), null)
|
|
32
|
+
|
|
33
|
+
// Drive 100 events spaced 3s apart — so the trailing 60s only ever
|
|
34
|
+
// contains ~21 timestamps. With a working sliding-window cleanup the
|
|
35
|
+
// array should stay bounded near that figure.
|
|
36
|
+
for (let i = 0; i < 100; i++) {
|
|
37
|
+
driver.ingest(
|
|
38
|
+
{
|
|
39
|
+
kind: 'tool_use',
|
|
40
|
+
toolName: 'Read',
|
|
41
|
+
toolUseId: `tu${i}`,
|
|
42
|
+
input: { file_path: `/tmp/${i}.txt` },
|
|
43
|
+
},
|
|
44
|
+
'cA',
|
|
45
|
+
)
|
|
46
|
+
advance(3000)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Find the per-turn timestamp array. The key is the active turnKey;
|
|
50
|
+
// there's only one turn so we can pick it.
|
|
51
|
+
const sizes = [...maps.editTimestamps.values()].map((a) => a.length)
|
|
52
|
+
expect(sizes.length).toBeGreaterThan(0)
|
|
53
|
+
const max = Math.max(...sizes)
|
|
54
|
+
// 60s window / 3s spacing = 20 entries. Allow tight slack (<= 22)
|
|
55
|
+
// for one or two boundary timestamps recorded by the harness's
|
|
56
|
+
// setup (initial enqueue, etc.) — anything looser fails to catch
|
|
57
|
+
// off-by-N regressions in the sliding-window cleanup.
|
|
58
|
+
expect(max).toBeLessThanOrEqual(22)
|
|
59
|
+
// And critically, NOT 100+ — that would mean cleanup never ran.
|
|
60
|
+
expect(max).toBeLessThan(100)
|
|
61
|
+
})
|
|
62
|
+
})
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PR-C2 — end-to-end memory bounds: drive 100 turn cycles and assert
|
|
3
|
+
* every internal Map remains bounded.
|
|
4
|
+
*
|
|
5
|
+
* Companion to PR-B's targeted eviction test, which drove only 20
|
|
6
|
+
* cycles and asserted on `seenEnqueueMsgIds` / `pendingSyncEchoes`.
|
|
7
|
+
* This larger run is a regression net for "everything else" — if a
|
|
8
|
+
* future refactor forgets to evict any new map keyed by chat/turn,
|
|
9
|
+
* the size invariant blows up here even when the PR-B test still
|
|
10
|
+
* passes.
|
|
11
|
+
*
|
|
12
|
+
* fails when: any of the per-chat/per-turn Maps in `_debugGetMaps`
|
|
13
|
+
* grows linearly with turn count (e.g. cleanup is removed from
|
|
14
|
+
* completeTurnFully, or a new Map is added without an eviction hook).
|
|
15
|
+
*/
|
|
16
|
+
import { describe, it, expect } from 'vitest'
|
|
17
|
+
import { makeHarness, enqueue } from './_progress-card-harness.js'
|
|
18
|
+
|
|
19
|
+
describe('PR-C2: end-to-end memory bounds across 100 turn cycles', () => {
|
|
20
|
+
it('all _debugGetMaps Maps stay bounded', () => {
|
|
21
|
+
const { driver, advance } = makeHarness({
|
|
22
|
+
heartbeatMs: 5_000,
|
|
23
|
+
promoteAfterMs: 999_999,
|
|
24
|
+
})
|
|
25
|
+
const maps = driver._debugGetMaps!()
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < 100; i++) {
|
|
28
|
+
driver.ingest(enqueue('chatA'), null)
|
|
29
|
+
driver.ingest({ kind: 'tool_use', toolName: 'mcp__switchroom-telegram__reply' }, 'chatA')
|
|
30
|
+
driver.recordOutboundDelivered('chatA')
|
|
31
|
+
driver.ingest({ kind: 'turn_end', durationMs: 50 }, 'chatA')
|
|
32
|
+
// Advance well past TTLs (60s) and the eviction throttle (~30s).
|
|
33
|
+
advance(65_000)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
expect(maps.chats.size).toBe(0)
|
|
37
|
+
expect(maps.chatRunningSubagents.size).toBe(0)
|
|
38
|
+
expect(maps.baseTurnSeqs.size).toBe(0)
|
|
39
|
+
// The dedup maps may keep at most one straggler from the final turn.
|
|
40
|
+
expect(maps.seenEnqueueMsgIds.size).toBeLessThanOrEqual(1)
|
|
41
|
+
expect(maps.pendingSyncEchoes.size).toBeLessThanOrEqual(1)
|
|
42
|
+
// editTimestamps is per-turnKey; cleared on completeTurnFully.
|
|
43
|
+
expect(maps.editTimestamps.size).toBeLessThanOrEqual(1)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('with a long-lived bg sub-agent across cycles, only the originating turnKey persists', () => {
|
|
47
|
+
const { driver, advance } = makeHarness({
|
|
48
|
+
heartbeatMs: 5_000,
|
|
49
|
+
promoteAfterMs: 999_999,
|
|
50
|
+
})
|
|
51
|
+
const maps = driver._debugGetMaps!()
|
|
52
|
+
|
|
53
|
+
// One bg sub-agent that NEVER finishes; 50 surrounding turns close cleanly.
|
|
54
|
+
driver.ingest(enqueue('chatA'), null)
|
|
55
|
+
driver.ingest(
|
|
56
|
+
{
|
|
57
|
+
kind: 'tool_use', toolName: 'Agent', toolUseId: 'tu1',
|
|
58
|
+
input: { prompt: 'forever-bg', run_in_background: true },
|
|
59
|
+
},
|
|
60
|
+
'chatA',
|
|
61
|
+
)
|
|
62
|
+
driver.ingest({ kind: 'sub_agent_started', agentId: 'saBG', firstPromptText: 'forever-bg' }, 'chatA')
|
|
63
|
+
driver.ingest({ kind: 'tool_use', toolName: 'mcp__switchroom-telegram__reply' }, 'chatA')
|
|
64
|
+
driver.recordOutboundDelivered('chatA')
|
|
65
|
+
driver.ingest({ kind: 'turn_end', durationMs: 50 }, 'chatA')
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < 50; i++) {
|
|
68
|
+
driver.ingest(enqueue('chatA'), null)
|
|
69
|
+
driver.ingest({ kind: 'tool_use', toolName: 'mcp__switchroom-telegram__reply' }, 'chatA')
|
|
70
|
+
driver.recordOutboundDelivered('chatA')
|
|
71
|
+
driver.ingest({ kind: 'turn_end', durationMs: 50 }, 'chatA')
|
|
72
|
+
advance(65_000)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// After 50 clean surrounding turns each followed by `advance(65_000)`
|
|
76
|
+
// (well past TTL + eviction throttle), every chatState — including
|
|
77
|
+
// the originating one whose bg sub-agent never finished — has been
|
|
78
|
+
// rolled forward and evicted. Empty is the correct steady state, not
|
|
79
|
+
// the "≤ 2" the original PR shipped. What this test really proves
|
|
80
|
+
// is that `chats` doesn't grow with cycle count.
|
|
81
|
+
expect(maps.chats.size).toBe(0)
|
|
82
|
+
expect(maps.baseTurnSeqs.size).toBeLessThanOrEqual(1)
|
|
83
|
+
})
|
|
84
|
+
})
|