crewly 1.20.194 → 1.20.196
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/config/constants.ts +68 -0
- package/config/hooks/agent-status/report.sh +31 -12
- package/config/hooks/subagent-guard/subagent.sh +25 -1
- package/config/roles/auditor/prompt.md +2 -2
- package/config/roles/orchestrator/fragments/communication.md +1 -1
- package/config/roles/orchestrator/fragments/lifecycle.md +1 -1
- package/config/roles/orchestrator/prompt.md +18 -508
- package/config/skills/_common/lib.sh +28 -5
- package/config/skills/_common/lib.test.sh +32 -1
- package/config/skills/agent/computer-use/SKILL.md +6 -0
- package/config/skills/agent/core/create-intent-tasks/execute.sh +2 -0
- package/config/skills/agent/core/decompose-intent/execute.sh +2 -0
- package/config/skills/agent/core/experiment-card/SKILL.md +38 -5
- package/config/skills/agent/core/experiment-card/execute.sh +40 -4
- package/config/skills/agent/core/experiment-card/execute.test.sh +17 -0
- package/config/skills/agent/core/project-tickets/SKILL.md +35 -2
- package/config/skills/agent/core/project-tickets/execute.sh +59 -6
- package/config/skills/agent/core/project-tickets/execute.test.sh +24 -0
- package/config/skills/agent/core/send-message/execute.sh +16 -0
- package/config/skills/agent/core/send-message/execute.test.sh +10 -0
- package/config/skills/agent/core/trace-read/SKILL.md +117 -0
- package/config/skills/agent/core/trace-read/execute.sh +116 -0
- package/config/skills/agent/core/update-intent-task/execute.sh +2 -0
- package/config/skills/agent/desktop-app-control/execute.sh +5 -2
- package/config/skills/agent/marketing/submit-for-approval/execute.sh +3 -2
- package/config/skills/orchestrator/decompose-mission/execute.sh +2 -0
- package/config/skills/orchestrator/decompose-okr/execute.sh +1 -0
- package/config/skills/orchestrator/design-team/execute.sh +2 -0
- package/config/skills/orchestrator/measure-kr/execute.sh +2 -0
- package/config/skills/orchestrator/review-mission/execute.sh +2 -0
- package/config/skills/orchestrator/send-message/execute.sh +27 -2
- package/config/skills/orchestrator/send-message/execute.test.sh +89 -0
- package/config/skills/registry.json +6 -5
- package/config/skills/team-leader/design-checklist/execute.sh +2 -0
- package/config/skills/team-leader/signal-digest/SKILL.md +110 -0
- package/config/skills/team-leader/signal-digest/execute.sh +173 -0
- package/config/skills/team-leader/signal-digest/execute.test.sh +123 -0
- package/config/skills/team-leader/signal-digest/signal-digest.config.example.json +23 -0
- package/config/skills/team-leader/signal-digest/signal_digest.py +572 -0
- package/config/skills/team-leader/signal-digest/signal_digest.test.py +319 -0
- package/dist/backend/backend/src/constants.d.ts +356 -5
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +341 -8
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.d.ts +9 -3
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.js +38 -5
- package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/approvals/approvals.controller.d.ts +4 -9
- package/dist/backend/backend/src/controllers/approvals/approvals.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/approvals/approvals.controller.js +6 -14
- package/dist/backend/backend/src/controllers/approvals/approvals.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/auth/owner-session.controller.d.ts +64 -0
- package/dist/backend/backend/src/controllers/auth/owner-session.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/auth/owner-session.controller.js +164 -0
- package/dist/backend/backend/src/controllers/auth/owner-session.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/browser/browser.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.routes.js +18 -5
- package/dist/backend/backend/src/controllers/browser/browser.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/canva/canva.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/canva/canva.routes.js +8 -1
- package/dist/backend/backend/src/controllers/canva/canva.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.js +16 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js +3 -1
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud-device-pairing.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud-device-pairing.controller.js +3 -5
- package/dist/backend/backend/src/controllers/cloud/cloud-device-pairing.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/connector/connector.controller.d.ts +4 -2
- package/dist/backend/backend/src/controllers/connector/connector.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/connector/connector.controller.js +17 -2
- package/dist/backend/backend/src/controllers/connector/connector.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/connector/grant-sharing.handler.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/connector/grant-sharing.handler.js +2 -3
- package/dist/backend/backend/src/controllers/connector/grant-sharing.handler.js.map +1 -1
- package/dist/backend/backend/src/controllers/decisions/decisions.controller.d.ts +4 -2
- package/dist/backend/backend/src/controllers/decisions/decisions.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/decisions/decisions.controller.js +31 -20
- package/dist/backend/backend/src/controllers/decisions/decisions.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/desktop/desktop.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/desktop/desktop.controller.js +16 -0
- package/dist/backend/backend/src/controllers/desktop/desktop.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.controller.js +9 -5
- package/dist/backend/backend/src/controllers/google/google.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.routes.js +16 -3
- package/dist/backend/backend/src/controllers/google/google.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/harness/harness.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/harness/harness.controller.js +3 -5
- package/dist/backend/backend/src/controllers/harness/harness.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.d.ts +1 -0
- package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.js +1 -0
- package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.routes.js +8 -1
- package/dist/backend/backend/src/controllers/microsoft/microsoft-todo.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/mission/mission-policy.routes.js +1 -1
- package/dist/backend/backend/src/controllers/mission/mission-policy.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +5 -2
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.controller.js +3 -5
- package/dist/backend/backend/src/controllers/owner-receipt/owner-receipt.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/people/people.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/people/people.routes.js +3 -5
- package/dist/backend/backend/src/controllers/people/people.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts +35 -2
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js +138 -4
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.d.ts +2 -0
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.js +7 -1
- package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/request/open-items.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/request/open-items.controller.js +2 -4
- package/dist/backend/backend/src/controllers/request/open-items.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/request/request.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/request/request.controller.js +5 -1
- package/dist/backend/backend/src/controllers/request/request.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/settings/settings.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/settings/settings.controller.js +18 -2
- package/dist/backend/backend/src/controllers/settings/settings.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/signal-digest/signal-digest.controller.d.ts +26 -0
- package/dist/backend/backend/src/controllers/signal-digest/signal-digest.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/signal-digest/signal-digest.controller.js +100 -0
- package/dist/backend/backend/src/controllers/signal-digest/signal-digest.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.js +9 -0
- package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.js +11 -0
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/system/system-control.controller.d.ts +6 -4
- package/dist/backend/backend/src/controllers/system/system-control.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/system/system-control.controller.js +20 -13
- package/dist/backend/backend/src/controllers/system/system-control.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.js +14 -7
- package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/tickets/tickets.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/tickets/tickets.controller.js +5 -7
- package/dist/backend/backend/src/controllers/tickets/tickets.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/trace/trace.controller.d.ts +73 -0
- package/dist/backend/backend/src/controllers/trace/trace.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/trace/trace.controller.js +437 -0
- package/dist/backend/backend/src/controllers/trace/trace.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp-inbox.controller.d.ts +3 -3
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp-inbox.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp-inbox.controller.js +4 -2
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp-inbox.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.js +10 -2
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts +34 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +342 -61
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/middleware/agent-origin-correction.d.ts +31 -0
- package/dist/backend/backend/src/middleware/agent-origin-correction.d.ts.map +1 -0
- package/dist/backend/backend/src/middleware/agent-origin-correction.js +31 -0
- package/dist/backend/backend/src/middleware/agent-origin-correction.js.map +1 -0
- package/dist/backend/backend/src/middleware/agent-origin.middleware.d.ts +6 -0
- package/dist/backend/backend/src/middleware/agent-origin.middleware.d.ts.map +1 -1
- package/dist/backend/backend/src/middleware/agent-origin.middleware.js +4 -1
- package/dist/backend/backend/src/middleware/agent-origin.middleware.js.map +1 -1
- package/dist/backend/backend/src/middleware/api-token.middleware.d.ts +20 -17
- package/dist/backend/backend/src/middleware/api-token.middleware.d.ts.map +1 -1
- package/dist/backend/backend/src/middleware/api-token.middleware.js +27 -37
- package/dist/backend/backend/src/middleware/api-token.middleware.js.map +1 -1
- package/dist/backend/backend/src/middleware/caller-identity.middleware.d.ts +213 -0
- package/dist/backend/backend/src/middleware/caller-identity.middleware.d.ts.map +1 -0
- package/dist/backend/backend/src/middleware/caller-identity.middleware.js +481 -0
- package/dist/backend/backend/src/middleware/caller-identity.middleware.js.map +1 -0
- package/dist/backend/backend/src/middleware/caller-identity.testing.d.ts +67 -0
- package/dist/backend/backend/src/middleware/caller-identity.testing.d.ts.map +1 -0
- package/dist/backend/backend/src/middleware/caller-identity.testing.js +108 -0
- package/dist/backend/backend/src/middleware/caller-identity.testing.js.map +1 -0
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +11 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +17 -2
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.d.ts +7 -5
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.js +19 -10
- package/dist/backend/backend/src/services/agent/control-plane-guard.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +10 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.d.ts +1 -1
- package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/restore-filter.d.ts +5 -2
- package/dist/backend/backend/src/services/agent/restore-filter.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/restore-filter.js +5 -2
- package/dist/backend/backend/src/services/agent/restore-filter.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js +4 -0
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts +29 -0
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js +77 -1
- package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts +4 -2
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.js +22 -6
- package/dist/backend/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.js +2 -2
- package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +1 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/dist/backend/backend/src/services/backup/backup-archive.service.d.ts +6 -0
- package/dist/backend/backend/src/services/backup/backup-archive.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/backup/backup-archive.service.js +7 -1
- package/dist/backend/backend/src/services/backup/backup-archive.service.js.map +1 -1
- package/dist/backend/backend/src/services/boot/boot-announce.service.d.ts +1 -1
- package/dist/backend/backend/src/services/boot/boot-announce.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat/chat.service.d.ts +175 -2
- package/dist/backend/backend/src/services/chat/chat.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat/chat.service.js +444 -35
- package/dist/backend/backend/src/services/chat/chat.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +30 -5
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +34 -4
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +4 -3
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +7 -4
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.d.ts +18 -11
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.js +19 -25
- package/dist/backend/backend/src/services/chat-v2/sqlite/channel.store.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +7 -4
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +8 -4
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/types.d.ts +0 -1
- package/dist/backend/backend/src/services/chat-v2/types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/types.js +0 -1
- package/dist/backend/backend/src/services/chat-v2/types.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +5 -0
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -1
- package/dist/backend/backend/src/services/core/api-token.service.d.ts +28 -0
- package/dist/backend/backend/src/services/core/api-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/core/api-token.service.js +46 -0
- package/dist/backend/backend/src/services/core/api-token.service.js.map +1 -1
- package/dist/backend/backend/src/services/core/dashboard-build.d.ts +49 -0
- package/dist/backend/backend/src/services/core/dashboard-build.d.ts.map +1 -0
- package/dist/backend/backend/src/services/core/dashboard-build.js +68 -0
- package/dist/backend/backend/src/services/core/dashboard-build.js.map +1 -0
- package/dist/backend/backend/src/services/core/owner-auth.service.d.ts +127 -0
- package/dist/backend/backend/src/services/core/owner-auth.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/core/owner-auth.service.js +205 -0
- package/dist/backend/backend/src/services/core/owner-auth.service.js.map +1 -0
- package/dist/backend/backend/src/services/core/peer-process.service.d.ts +168 -0
- package/dist/backend/backend/src/services/core/peer-process.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/core/peer-process.service.js +352 -0
- package/dist/backend/backend/src/services/core/peer-process.service.js.map +1 -0
- package/dist/backend/backend/src/services/decisions/decision-store.d.ts.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision-store.js +5 -1
- package/dist/backend/backend/src/services/decisions/decision-store.js.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.wiring.d.ts +10 -1
- package/dist/backend/backend/src/services/decisions/decision.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.wiring.js +20 -9
- package/dist/backend/backend/src/services/decisions/decision.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/experiments/experiment-verdict.d.ts +1 -1
- package/dist/backend/backend/src/services/experiments/experiment-verdict.js +2 -2
- package/dist/backend/backend/src/services/experiments/experiment-verdict.js.map +1 -1
- package/dist/backend/backend/src/services/experiments/experiment.service.d.ts +149 -4
- package/dist/backend/backend/src/services/experiments/experiment.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/experiments/experiment.service.js +549 -24
- package/dist/backend/backend/src/services/experiments/experiment.service.js.map +1 -1
- package/dist/backend/backend/src/services/experiments/experiment.wiring.d.ts +20 -5
- package/dist/backend/backend/src/services/experiments/experiment.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/experiments/experiment.wiring.js +46 -9
- package/dist/backend/backend/src/services/experiments/experiment.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.d.ts +7 -0
- package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.d.ts.map +1 -1
- package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.js +21 -1
- package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.js +7 -0
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.js +2 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/thread-status-queue.service.d.ts +0 -8
- package/dist/backend/backend/src/services/messaging/thread-status-queue.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/thread-status-queue.service.js +0 -18
- package/dist/backend/backend/src/services/messaging/thread-status-queue.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts +19 -0
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js +41 -5
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/agent-turn-state.d.ts +184 -0
- package/dist/backend/backend/src/services/monitoring/agent-turn-state.d.ts.map +1 -0
- package/dist/backend/backend/src/services/monitoring/agent-turn-state.js +391 -0
- package/dist/backend/backend/src/services/monitoring/agent-turn-state.js.map +1 -0
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.d.ts +35 -1
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.js +138 -2
- package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/claude-transcript-turn.d.ts +73 -0
- package/dist/backend/backend/src/services/monitoring/claude-transcript-turn.d.ts.map +1 -0
- package/dist/backend/backend/src/services/monitoring/claude-transcript-turn.js +258 -0
- package/dist/backend/backend/src/services/monitoring/claude-transcript-turn.js.map +1 -0
- package/dist/backend/backend/src/services/monitoring/deferred-idle-settle.d.ts +82 -0
- package/dist/backend/backend/src/services/monitoring/deferred-idle-settle.d.ts.map +1 -0
- package/dist/backend/backend/src/services/monitoring/deferred-idle-settle.js +141 -0
- package/dist/backend/backend/src/services/monitoring/deferred-idle-settle.js.map +1 -0
- package/dist/backend/backend/src/services/monitoring/system-resource-alert.service.d.ts +51 -1
- package/dist/backend/backend/src/services/monitoring/system-resource-alert.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/system-resource-alert.service.js +118 -2
- package/dist/backend/backend/src/services/monitoring/system-resource-alert.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts +7 -0
- package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/token-usage.service.js +4 -0
- package/dist/backend/backend/src/services/monitoring/token-usage.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/transcript-cost-repair.d.ts +103 -0
- package/dist/backend/backend/src/services/monitoring/transcript-cost-repair.d.ts.map +1 -0
- package/dist/backend/backend/src/services/monitoring/transcript-cost-repair.js +86 -0
- package/dist/backend/backend/src/services/monitoring/transcript-cost-repair.js.map +1 -0
- package/dist/backend/backend/src/services/open-items/open-items.service.d.ts +57 -0
- package/dist/backend/backend/src/services/open-items/open-items.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/open-items/open-items.service.js +100 -4
- package/dist/backend/backend/src/services/open-items/open-items.service.js.map +1 -1
- package/dist/backend/backend/src/services/orc/orc-status-router.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orc/orc-status-router.service.js +10 -2
- package/dist/backend/backend/src/services/orc/orc-status-router.service.js.map +1 -1
- package/dist/backend/backend/src/services/orc/reply-destination.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orc/reply-destination.wiring.js +16 -0
- package/dist/backend/backend/src/services/orc/reply-destination.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js +13 -0
- package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/project-ticket.service.d.ts +36 -0
- package/dist/backend/backend/src/services/project-tickets/project-ticket.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/project-ticket.service.js +44 -3
- package/dist/backend/backend/src/services/project-tickets/project-ticket.service.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-assignee-waker.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-assignee-waker.js +2 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-assignee-waker.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.js +3 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.js.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-retro.d.ts +156 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-retro.d.ts.map +1 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-retro.js +308 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-retro.js.map +1 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-stats.d.ts +212 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-stats.d.ts.map +1 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-stats.js +515 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-stats.js.map +1 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-trace.d.ts +186 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-trace.d.ts.map +1 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-trace.js +341 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-trace.js.map +1 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts +309 -0
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js +726 -1
- package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js +15 -0
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js.map +1 -1
- package/dist/backend/backend/src/services/restart/in-flight-turn-tracker.service.d.ts +34 -3
- package/dist/backend/backend/src/services/restart/in-flight-turn-tracker.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/restart/in-flight-turn-tracker.service.js +57 -2
- package/dist/backend/backend/src/services/restart/in-flight-turn-tracker.service.js.map +1 -1
- package/dist/backend/backend/src/services/restart/interrupted-turns.d.ts +61 -3
- package/dist/backend/backend/src/services/restart/interrupted-turns.d.ts.map +1 -1
- package/dist/backend/backend/src/services/restart/interrupted-turns.js +106 -9
- package/dist/backend/backend/src/services/restart/interrupted-turns.js.map +1 -1
- package/dist/backend/backend/src/services/restart/restart-drain.service.d.ts +22 -0
- package/dist/backend/backend/src/services/restart/restart-drain.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/restart/restart-drain.service.js +37 -5
- package/dist/backend/backend/src/services/restart/restart-drain.service.js.map +1 -1
- package/dist/backend/backend/src/services/restart/supervisor-stop-budget.d.ts +62 -0
- package/dist/backend/backend/src/services/restart/supervisor-stop-budget.d.ts.map +1 -0
- package/dist/backend/backend/src/services/restart/supervisor-stop-budget.js +126 -0
- package/dist/backend/backend/src/services/restart/supervisor-stop-budget.js.map +1 -0
- package/dist/backend/backend/src/services/restart/turn-probe.d.ts +17 -2
- package/dist/backend/backend/src/services/restart/turn-probe.d.ts.map +1 -1
- package/dist/backend/backend/src/services/restart/turn-probe.js +29 -4
- package/dist/backend/backend/src/services/restart/turn-probe.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js +4 -0
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js.map +1 -1
- package/dist/backend/backend/src/services/session/session-handoff.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/session/session-handoff.service.js +8 -5
- package/dist/backend/backend/src/services/session/session-handoff.service.js.map +1 -1
- package/dist/backend/backend/src/services/signal-digest/signal-digest-card.d.ts +75 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest-card.d.ts.map +1 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest-card.js +187 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest-card.js.map +1 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest-contract.d.ts +86 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest-contract.d.ts.map +1 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest-contract.js +307 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest-contract.js.map +1 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest-store.d.ts +85 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest-store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest-store.js +185 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest-store.js.map +1 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest.service.d.ts +272 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest.service.js +570 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest.service.js.map +1 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest.wiring.d.ts +51 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest.wiring.d.ts.map +1 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest.wiring.js +116 -0
- package/dist/backend/backend/src/services/signal-digest/signal-digest.wiring.js.map +1 -0
- package/dist/backend/backend/src/services/slack/notify-reconciliation.service.d.ts +5 -1
- package/dist/backend/backend/src/services/slack/notify-reconciliation.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/notify-reconciliation.service.js +6 -2
- package/dist/backend/backend/src/services/slack/notify-reconciliation.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-auto-working.service.d.ts +29 -0
- package/dist/backend/backend/src/services/slack/slack-auto-working.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-auto-working.service.js +66 -3
- package/dist/backend/backend/src/services/slack/slack-auto-working.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +2 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +3 -2
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-relogin-dm.service.d.ts +1 -1
- package/dist/backend/backend/src/services/slack/slack-relogin-dm.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +79 -15
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +200 -41
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts +43 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.js +76 -7
- package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/backend/backend/src/services/system/auto-update.service.d.ts +2 -2
- package/dist/backend/backend/src/services/system/auto-update.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/pool-storage.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/pool-storage.js +4 -0
- package/dist/backend/backend/src/services/task-pool/pool-storage.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js +2 -0
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/trace/trace-analysis.service.d.ts +99 -0
- package/dist/backend/backend/src/services/trace/trace-analysis.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-analysis.service.js +148 -0
- package/dist/backend/backend/src/services/trace/trace-analysis.service.js.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-context.service.d.ts +212 -0
- package/dist/backend/backend/src/services/trace/trace-context.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-context.service.js +489 -0
- package/dist/backend/backend/src/services/trace/trace-context.service.js.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-http.middleware.d.ts +46 -0
- package/dist/backend/backend/src/services/trace/trace-http.middleware.d.ts.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-http.middleware.js +176 -0
- package/dist/backend/backend/src/services/trace/trace-http.middleware.js.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-markers.d.ts +93 -0
- package/dist/backend/backend/src/services/trace/trace-markers.d.ts.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-markers.js +162 -0
- package/dist/backend/backend/src/services/trace/trace-markers.js.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-metrics.d.ts +262 -0
- package/dist/backend/backend/src/services/trace/trace-metrics.d.ts.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-metrics.js +810 -0
- package/dist/backend/backend/src/services/trace/trace-metrics.js.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-recorder.d.ts +338 -0
- package/dist/backend/backend/src/services/trace/trace-recorder.d.ts.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-recorder.js +789 -0
- package/dist/backend/backend/src/services/trace/trace-recorder.js.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-store.d.ts +308 -0
- package/dist/backend/backend/src/services/trace/trace-store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-store.js +714 -0
- package/dist/backend/backend/src/services/trace/trace-store.js.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-summary.d.ts +77 -0
- package/dist/backend/backend/src/services/trace/trace-summary.d.ts.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-summary.js +239 -0
- package/dist/backend/backend/src/services/trace/trace-summary.js.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-timeline.d.ts +74 -0
- package/dist/backend/backend/src/services/trace/trace-timeline.d.ts.map +1 -0
- package/dist/backend/backend/src/services/trace/trace-timeline.js +162 -0
- package/dist/backend/backend/src/services/trace/trace-timeline.js.map +1 -0
- package/dist/backend/backend/src/services/trace/trace.types.d.ts +137 -0
- package/dist/backend/backend/src/services/trace/trace.types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/trace/trace.types.js +104 -0
- package/dist/backend/backend/src/services/trace/trace.types.js.map +1 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt-format-ask.d.ts +80 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt-format-ask.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt-format-ask.js +184 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt-format-ask.js.map +1 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.boot.d.ts +1 -1
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.boot.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.d.ts +7 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.js +16 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.types.d.ts +16 -0
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.types.js.map +1 -1
- package/dist/backend/backend/src/services/v3/request.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/request.service.js +4 -0
- package/dist/backend/backend/src/services/v3/request.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/tl-auto-verify.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/tl-auto-verify.service.js +2 -1
- package/dist/backend/backend/src/services/v3/tl-auto-verify.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts +8 -0
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js +46 -4
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
- package/dist/backend/backend/src/services/whatsapp/whatsapp-draft-gate.d.ts +4 -3
- package/dist/backend/backend/src/services/whatsapp/whatsapp-draft-gate.d.ts.map +1 -1
- package/dist/backend/backend/src/services/whatsapp/whatsapp-draft-gate.js +3 -2
- package/dist/backend/backend/src/services/whatsapp/whatsapp-draft-gate.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.d.ts +3 -1
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.js.map +1 -1
- package/dist/backend/backend/src/services/workflow/message-scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/message-scheduler.service.js +3 -0
- package/dist/backend/backend/src/services/workflow/message-scheduler.service.js.map +1 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.js +3 -0
- package/dist/backend/backend/src/services/workflow/scheduler.service.js.map +1 -1
- package/dist/backend/backend/src/services/worktree/workitem-worktree.subscriber.d.ts.map +1 -1
- package/dist/backend/backend/src/services/worktree/workitem-worktree.subscriber.js +2 -1
- package/dist/backend/backend/src/services/worktree/workitem-worktree.subscriber.js.map +1 -1
- package/dist/backend/backend/src/services/worktree/worktree-janitor.service.d.ts +3 -0
- package/dist/backend/backend/src/services/worktree/worktree-janitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/worktree/worktree-janitor.service.js +7 -0
- package/dist/backend/backend/src/services/worktree/worktree-janitor.service.js.map +1 -1
- package/dist/backend/backend/src/types/decision.types.d.ts +3 -1
- package/dist/backend/backend/src/types/decision.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/experiment.types.d.ts +65 -6
- package/dist/backend/backend/src/types/experiment.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/experiment.types.js.map +1 -1
- package/dist/backend/backend/src/types/signal-digest.types.d.ts +185 -0
- package/dist/backend/backend/src/types/signal-digest.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/signal-digest.types.js +21 -0
- package/dist/backend/backend/src/types/signal-digest.types.js.map +1 -0
- package/dist/backend/backend/src/types/ticket-autopilot.types.d.ts +9 -0
- package/dist/backend/backend/src/types/ticket-autopilot.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/ticket-autopilot.types.js +14 -0
- package/dist/backend/backend/src/types/ticket-autopilot.types.js.map +1 -1
- package/dist/backend/backend/src/types/v2/open-item.types.d.ts +4 -0
- package/dist/backend/backend/src/types/v2/open-item.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/request.types.d.ts +4 -0
- package/dist/backend/backend/src/types/v2/request.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/request.types.js.map +1 -1
- package/dist/backend/backend/src/types/v2/work-item.types.d.ts +5 -1
- package/dist/backend/backend/src/types/v2/work-item.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/work-item.types.js +2 -0
- package/dist/backend/backend/src/types/v2/work-item.types.js.map +1 -1
- package/dist/backend/backend/src/utils/agent-caller.utils.d.ts +44 -37
- package/dist/backend/backend/src/utils/agent-caller.utils.d.ts.map +1 -1
- package/dist/backend/backend/src/utils/agent-caller.utils.js +48 -42
- package/dist/backend/backend/src/utils/agent-caller.utils.js.map +1 -1
- package/dist/backend/backend/src/utils/secret-env.d.ts.map +1 -1
- package/dist/backend/backend/src/utils/secret-env.js +8 -1
- package/dist/backend/backend/src/utils/secret-env.js.map +1 -1
- package/dist/backend/backend/src/utils/security.d.ts +2 -0
- package/dist/backend/backend/src/utils/security.d.ts.map +1 -1
- package/dist/backend/backend/src/utils/security.js +3 -1
- package/dist/backend/backend/src/utils/security.js.map +1 -1
- package/dist/backend/backend/src/websocket/chat.gateway.d.ts +9 -0
- package/dist/backend/backend/src/websocket/chat.gateway.d.ts.map +1 -1
- package/dist/backend/backend/src/websocket/chat.gateway.js +26 -0
- package/dist/backend/backend/src/websocket/chat.gateway.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/backend/config/constants.d.ts +67 -0
- package/dist/backend/config/constants.d.ts.map +1 -1
- package/dist/backend/config/constants.js +67 -0
- package/dist/backend/config/constants.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +356 -5
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +341 -8
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +17 -2
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.d.ts +7 -5
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.js +19 -10
- package/dist/cli/backend/src/services/agent/control-plane-guard.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +10 -1
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts +1 -1
- package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js +4 -0
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts +29 -0
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js +77 -1
- package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts +4 -2
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.js +22 -6
- package/dist/cli/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js +2 -2
- package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/dist/cli/backend/src/services/backup/backup-archive.service.d.ts +6 -0
- package/dist/cli/backend/src/services/backup/backup-archive.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/backup/backup-archive.service.js +7 -1
- package/dist/cli/backend/src/services/backup/backup-archive.service.js.map +1 -1
- package/dist/cli/backend/src/services/chat/chat.service.d.ts +282 -0
- package/dist/cli/backend/src/services/chat/chat.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/chat/chat.service.js +783 -0
- package/dist/cli/backend/src/services/chat/chat.service.js.map +1 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +30 -5
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +34 -4
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts +4 -3
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js +7 -4
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.d.ts +18 -11
- package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.js +19 -25
- package/dist/cli/backend/src/services/chat-v2/sqlite/channel.store.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts +7 -4
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js +8 -4
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/types.d.ts +0 -1
- package/dist/cli/backend/src/services/chat-v2/types.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/types.js +0 -1
- package/dist/cli/backend/src/services/chat-v2/types.js.map +1 -1
- package/dist/cli/backend/src/services/core/api-token.service.d.ts +28 -0
- package/dist/cli/backend/src/services/core/api-token.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/core/api-token.service.js +46 -0
- package/dist/cli/backend/src/services/core/api-token.service.js.map +1 -1
- package/dist/cli/backend/src/services/core/owner-auth.service.d.ts +127 -0
- package/dist/cli/backend/src/services/core/owner-auth.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/core/owner-auth.service.js +205 -0
- package/dist/cli/backend/src/services/core/owner-auth.service.js.map +1 -0
- package/dist/cli/backend/src/services/decisions/decision-store.d.ts.map +1 -1
- package/dist/cli/backend/src/services/decisions/decision-store.js +5 -1
- package/dist/cli/backend/src/services/decisions/decision-store.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.js +7 -0
- package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/thread-status-queue.service.d.ts +0 -8
- package/dist/cli/backend/src/services/messaging/thread-status-queue.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/thread-status-queue.service.js +0 -18
- package/dist/cli/backend/src/services/messaging/thread-status-queue.service.js.map +1 -1
- package/dist/cli/backend/src/services/monitoring/activity-monitor.service.d.ts +19 -0
- package/dist/cli/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/monitoring/activity-monitor.service.js +41 -5
- package/dist/cli/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
- package/dist/cli/backend/src/services/monitoring/agent-turn-state.d.ts +184 -0
- package/dist/cli/backend/src/services/monitoring/agent-turn-state.d.ts.map +1 -0
- package/dist/cli/backend/src/services/monitoring/agent-turn-state.js +391 -0
- package/dist/cli/backend/src/services/monitoring/agent-turn-state.js.map +1 -0
- package/dist/cli/backend/src/services/monitoring/claude-transcript-turn.d.ts +73 -0
- package/dist/cli/backend/src/services/monitoring/claude-transcript-turn.d.ts.map +1 -0
- package/dist/cli/backend/src/services/monitoring/claude-transcript-turn.js +258 -0
- package/dist/cli/backend/src/services/monitoring/claude-transcript-turn.js.map +1 -0
- package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts +7 -0
- package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/monitoring/token-usage.service.js +4 -0
- package/dist/cli/backend/src/services/monitoring/token-usage.service.js.map +1 -1
- package/dist/cli/backend/src/services/open-items/open-items.service.d.ts +57 -0
- package/dist/cli/backend/src/services/open-items/open-items.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/open-items/open-items.service.js +100 -4
- package/dist/cli/backend/src/services/open-items/open-items.service.js.map +1 -1
- package/dist/cli/backend/src/services/project-tickets/project-ticket.service.d.ts +36 -0
- package/dist/cli/backend/src/services/project-tickets/project-ticket.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/project-tickets/project-ticket.service.js +44 -3
- package/dist/cli/backend/src/services/project-tickets/project-ticket.service.js.map +1 -1
- package/dist/cli/backend/src/services/restart/in-flight-turn-tracker.service.d.ts +34 -3
- package/dist/cli/backend/src/services/restart/in-flight-turn-tracker.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/restart/in-flight-turn-tracker.service.js +57 -2
- package/dist/cli/backend/src/services/restart/in-flight-turn-tracker.service.js.map +1 -1
- package/dist/cli/backend/src/services/restart/restart-drain.service.d.ts +22 -0
- package/dist/cli/backend/src/services/restart/restart-drain.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/restart/restart-drain.service.js +37 -5
- package/dist/cli/backend/src/services/restart/restart-drain.service.js.map +1 -1
- package/dist/cli/backend/src/services/session/session-handoff.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/session/session-handoff.service.js +8 -5
- package/dist/cli/backend/src/services/session/session-handoff.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-auto-working.service.d.ts +29 -0
- package/dist/cli/backend/src/services/slack/slack-auto-working.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-auto-working.service.js +66 -3
- package/dist/cli/backend/src/services/slack/slack-auto-working.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts +2 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +3 -2
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +79 -15
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +200 -41
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack.service.d.ts +43 -1
- package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack.service.js +76 -7
- package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/cli/backend/src/services/task-pool/pool-storage.d.ts.map +1 -1
- package/dist/cli/backend/src/services/task-pool/pool-storage.js +4 -0
- package/dist/cli/backend/src/services/task-pool/pool-storage.js.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js +2 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/cli/backend/src/services/trace/trace-context.service.d.ts +212 -0
- package/dist/cli/backend/src/services/trace/trace-context.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/trace/trace-context.service.js +489 -0
- package/dist/cli/backend/src/services/trace/trace-context.service.js.map +1 -0
- package/dist/cli/backend/src/services/trace/trace-markers.d.ts +93 -0
- package/dist/cli/backend/src/services/trace/trace-markers.d.ts.map +1 -0
- package/dist/cli/backend/src/services/trace/trace-markers.js +162 -0
- package/dist/cli/backend/src/services/trace/trace-markers.js.map +1 -0
- package/dist/cli/backend/src/services/trace/trace-recorder.d.ts +338 -0
- package/dist/cli/backend/src/services/trace/trace-recorder.d.ts.map +1 -0
- package/dist/cli/backend/src/services/trace/trace-recorder.js +789 -0
- package/dist/cli/backend/src/services/trace/trace-recorder.js.map +1 -0
- package/dist/cli/backend/src/services/trace/trace-store.d.ts +308 -0
- package/dist/cli/backend/src/services/trace/trace-store.d.ts.map +1 -0
- package/dist/cli/backend/src/services/trace/trace-store.js +714 -0
- package/dist/cli/backend/src/services/trace/trace-store.js.map +1 -0
- package/dist/cli/backend/src/services/trace/trace.types.d.ts +137 -0
- package/dist/cli/backend/src/services/trace/trace.types.d.ts.map +1 -0
- package/dist/cli/backend/src/services/trace/trace.types.js +104 -0
- package/dist/cli/backend/src/services/trace/trace.types.js.map +1 -0
- package/dist/cli/backend/src/services/v3/request.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/v3/request.service.js +4 -0
- package/dist/cli/backend/src/services/v3/request.service.js.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.d.ts +3 -1
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.js.map +1 -1
- package/dist/cli/backend/src/types/decision.types.d.ts +3 -1
- package/dist/cli/backend/src/types/decision.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/ticket-autopilot.types.d.ts +9 -0
- package/dist/cli/backend/src/types/ticket-autopilot.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/ticket-autopilot.types.js +14 -0
- package/dist/cli/backend/src/types/ticket-autopilot.types.js.map +1 -1
- package/dist/cli/backend/src/types/v2/open-item.types.d.ts +4 -0
- package/dist/cli/backend/src/types/v2/open-item.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/v2/request.types.d.ts +4 -0
- package/dist/cli/backend/src/types/v2/request.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/v2/request.types.js.map +1 -1
- package/dist/cli/backend/src/types/v2/work-item.types.d.ts +5 -1
- package/dist/cli/backend/src/types/v2/work-item.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/v2/work-item.types.js +2 -0
- package/dist/cli/backend/src/types/v2/work-item.types.js.map +1 -1
- package/dist/cli/backend/src/utils/secret-env.d.ts.map +1 -1
- package/dist/cli/backend/src/utils/secret-env.js +8 -1
- package/dist/cli/backend/src/utils/secret-env.js.map +1 -1
- package/dist/cli/backend/src/utils/security.d.ts +196 -0
- package/dist/cli/backend/src/utils/security.d.ts.map +1 -0
- package/dist/cli/backend/src/utils/security.js +538 -0
- package/dist/cli/backend/src/utils/security.js.map +1 -0
- package/dist/cli/backend/src/websocket/chat.gateway.d.ts +9 -0
- package/dist/cli/backend/src/websocket/chat.gateway.d.ts.map +1 -1
- package/dist/cli/backend/src/websocket/chat.gateway.js +26 -0
- package/dist/cli/backend/src/websocket/chat.gateway.js.map +1 -1
- package/dist/cli/cli/src/commands/service.d.ts +12 -0
- package/dist/cli/cli/src/commands/service.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/service.js +36 -2
- package/dist/cli/cli/src/commands/service.js.map +1 -1
- package/dist/cli/cli/src/index.js +4 -0
- package/dist/cli/cli/src/index.js.map +1 -1
- package/dist/cli/cli/src/utils/owner-token-fetch.d.ts +41 -0
- package/dist/cli/cli/src/utils/owner-token-fetch.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/owner-token-fetch.js +83 -0
- package/dist/cli/cli/src/utils/owner-token-fetch.js.map +1 -0
- package/dist/cli/cli/src/utils/safe-shutdown.d.ts +13 -3
- package/dist/cli/cli/src/utils/safe-shutdown.d.ts.map +1 -1
- package/dist/cli/cli/src/utils/safe-shutdown.js +26 -4
- package/dist/cli/cli/src/utils/safe-shutdown.js.map +1 -1
- package/dist/cli/config/constants.d.ts +67 -0
- package/dist/cli/config/constants.d.ts.map +1 -1
- package/dist/cli/config/constants.js +67 -0
- package/dist/cli/config/constants.js.map +1 -1
- package/frontend/dist/assets/index-bfa0e2e8.css +42 -0
- package/frontend/dist/assets/{index-800118ca.js → index-edfa8e04.js} +285 -285
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/packages/crewly-agent/src/runtime/api-client.test.ts +42 -0
- package/packages/crewly-agent/src/runtime/api-client.ts +6 -0
- package/dist/backend/backend/src/services/v3/request-notification.service.d.ts +0 -52
- package/dist/backend/backend/src/services/v3/request-notification.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/v3/request-notification.service.js +0 -161
- package/dist/backend/backend/src/services/v3/request-notification.service.js.map +0 -1
- package/frontend/dist/assets/index-5e967795.css +0 -42
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
* resolves the agent's prediction, appends the result to the wiki
|
|
11
11
|
* experiment log and tells the owner.
|
|
12
12
|
*
|
|
13
|
-
* The experiment is a trace root: `traceId` (`
|
|
13
|
+
* The experiment is a trace root: `traceId` (a run trace, `tr-…`; the ticket's
|
|
14
|
+
* trace when its ticket already has one) names the run, and
|
|
14
15
|
* the timeline records every step (created, shipped, baseline, each fetch
|
|
15
16
|
* failure, measured, logged, reported), so the whole run can be reviewed.
|
|
16
17
|
*
|
|
@@ -27,6 +28,7 @@ import { EXPERIMENT_CONSTANTS } from '../../constants.js';
|
|
|
27
28
|
import { LoggerService } from '../core/logger.service.js';
|
|
28
29
|
import { isExperimentSource, isExperimentStatus, } from '../../types/experiment.types.js';
|
|
29
30
|
import { decideVerdict, defaultDirection, experimentWindows, formatValue } from './experiment-verdict.js';
|
|
31
|
+
import { startExperimentTrace, traceExperimentEvent } from '../trace/trace-recorder.js';
|
|
30
32
|
/** An error with an HTTP status. */
|
|
31
33
|
export class ExperimentError extends Error {
|
|
32
34
|
status;
|
|
@@ -40,6 +42,22 @@ export class ExperimentError extends Error {
|
|
|
40
42
|
this.name = 'ExperimentError';
|
|
41
43
|
}
|
|
42
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* A ship time: a valid ISO instant that is not in the future.
|
|
47
|
+
*
|
|
48
|
+
* @param raw - Value
|
|
49
|
+
* @param now - Current time
|
|
50
|
+
* @returns ISO time
|
|
51
|
+
* @throws ExperimentError(400)
|
|
52
|
+
*/
|
|
53
|
+
function parseShipTime(raw, now) {
|
|
54
|
+
const t = Date.parse(raw);
|
|
55
|
+
if (Number.isNaN(t))
|
|
56
|
+
throw new ExperimentError(400, 'shippedAt must be an ISO time');
|
|
57
|
+
if (t > now.getTime())
|
|
58
|
+
throw new ExperimentError(400, 'shippedAt is in the future');
|
|
59
|
+
return new Date(t).toISOString();
|
|
60
|
+
}
|
|
43
61
|
/**
|
|
44
62
|
* Error text.
|
|
45
63
|
*
|
|
@@ -49,6 +67,34 @@ export class ExperimentError extends Error {
|
|
|
49
67
|
function errText(err) {
|
|
50
68
|
return err instanceof Error ? err.message : String(err);
|
|
51
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* A local calendar day (the autopilot's days; the budget resets at local midnight).
|
|
72
|
+
*
|
|
73
|
+
* @param d - Time
|
|
74
|
+
* @returns YYYY-MM-DD
|
|
75
|
+
*/
|
|
76
|
+
export function localDay(d) {
|
|
77
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
78
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The process windows of an autopilot card, in local days: the observation
|
|
82
|
+
* window starts ON the start day (the autopilot works that day too), the
|
|
83
|
+
* baseline is the equal window right before it.
|
|
84
|
+
*
|
|
85
|
+
* @param startedAt - When the card started (ISO)
|
|
86
|
+
* @param windowDays - Days per window
|
|
87
|
+
* @returns Baseline, observation, and when the observation window is over
|
|
88
|
+
*/
|
|
89
|
+
export function processWindows(startedAt, windowDays) {
|
|
90
|
+
const t = new Date(startedAt);
|
|
91
|
+
const at = (delta) => new Date(t.getFullYear(), t.getMonth(), t.getDate() + delta, 12);
|
|
92
|
+
return {
|
|
93
|
+
baseline: { start: localDay(at(-windowDays)), end: localDay(at(-1)) },
|
|
94
|
+
observation: { start: localDay(at(0)), end: localDay(at(windowDays - 1)) },
|
|
95
|
+
dueAtMs: new Date(t.getFullYear(), t.getMonth(), t.getDate() + windowDays, 0, 0, 0, 0).getTime(),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
52
98
|
/**
|
|
53
99
|
* Trimmed, length-capped string, or undefined.
|
|
54
100
|
*
|
|
@@ -61,6 +107,30 @@ function text(v) {
|
|
|
61
107
|
const t = v.trim();
|
|
62
108
|
return t ? t.slice(0, EXPERIMENT_CONSTANTS.MAX_TEXT_LENGTH) : undefined;
|
|
63
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* A GA4 landing-page filter as a path: GA4 reports landing pages as paths, so
|
|
112
|
+
* a full URL is reduced to its path and any query string / fragment dropped
|
|
113
|
+
* (`https://site/x/?utm=1` → `/x/`).
|
|
114
|
+
*
|
|
115
|
+
* @param page - Page as given
|
|
116
|
+
* @returns The path
|
|
117
|
+
* @throws ExperimentError(400) when it is a URL that cannot be read
|
|
118
|
+
*/
|
|
119
|
+
export function ga4PagePath(page) {
|
|
120
|
+
let p = page.trim();
|
|
121
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(p)) {
|
|
122
|
+
try {
|
|
123
|
+
p = new URL(p).pathname;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
throw new ExperimentError(400, `metric.page is not a valid URL: ${page} (for ga4 give the landing page path, e.g. /h1b-guide)`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
p = p.split('#')[0].split('?')[0];
|
|
130
|
+
if (!p.startsWith('/'))
|
|
131
|
+
p = `/${p}`;
|
|
132
|
+
return p;
|
|
133
|
+
}
|
|
64
134
|
/**
|
|
65
135
|
* Validate a metric definition.
|
|
66
136
|
*
|
|
@@ -84,7 +154,7 @@ export function validateMetric(raw) {
|
|
|
84
154
|
const out = { source: m.source, measure: m.measure, config };
|
|
85
155
|
const page = text(m.page);
|
|
86
156
|
if (page)
|
|
87
|
-
out.page = page;
|
|
157
|
+
out.page = m.source === 'ga4' ? ga4PagePath(page) : page;
|
|
88
158
|
if (m.pageMatch !== undefined) {
|
|
89
159
|
if (m.pageMatch !== 'exact' && m.pageMatch !== 'contains')
|
|
90
160
|
throw new ExperimentError(400, 'metric.pageMatch must be exact or contains');
|
|
@@ -103,7 +173,7 @@ export function validateMetric(raw) {
|
|
|
103
173
|
}
|
|
104
174
|
const event = text(m.event);
|
|
105
175
|
if (out.measure === 'events' && !event)
|
|
106
|
-
throw new ExperimentError(400, 'metric.event is required for ga4 events (e.g. generate_lead)');
|
|
176
|
+
throw new ExperimentError(400, 'metric.event is required for ga4 events (e.g. generate_lead); for every key event use measure conversions');
|
|
107
177
|
if (event)
|
|
108
178
|
out.event = event;
|
|
109
179
|
const channel = text(m.channel);
|
|
@@ -196,11 +266,62 @@ export function resultSummary(e) {
|
|
|
196
266
|
}
|
|
197
267
|
if (e.baseline && e.result)
|
|
198
268
|
lines.push(`Baseline ${e.baseline.start}..${e.baseline.end} · Result ${e.result.start}..${e.result.end}`);
|
|
269
|
+
if (e.autopilot)
|
|
270
|
+
lines.push(...autopilotSummaryLines(e.autopilot));
|
|
199
271
|
if (e.ticket)
|
|
200
272
|
lines.push(`Ticket: ${ticketLabel(e.ticket)}`);
|
|
201
|
-
lines.push(`Trace: ${e.traceId}`);
|
|
202
273
|
return lines.join('\n');
|
|
203
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* Duration in words.
|
|
277
|
+
*
|
|
278
|
+
* @param ms - Milliseconds
|
|
279
|
+
* @returns "3h 10m" / "45m"
|
|
280
|
+
*/
|
|
281
|
+
function durationText(ms) {
|
|
282
|
+
const m = Math.round(ms / 60_000);
|
|
283
|
+
if (m < 60)
|
|
284
|
+
return `${m}m`;
|
|
285
|
+
const h = Math.floor(m / 60);
|
|
286
|
+
return m % 60 ? `${h}h ${m % 60}m` : `${h}h`;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* The process numbers as one line.
|
|
290
|
+
*
|
|
291
|
+
* @param p - Process summary
|
|
292
|
+
* @returns e.g. "9 tickets shipped · 1.2 owner touches per ticket · stalls 3h 10m · $2.10 per shipped ticket"
|
|
293
|
+
*/
|
|
294
|
+
export function processLine(p) {
|
|
295
|
+
return [
|
|
296
|
+
`${p.ticketsShipped} ticket${p.ticketsShipped === 1 ? '' : 's'} shipped (${p.ticketsStarted} started)`,
|
|
297
|
+
`${p.ownerTouchesPerTicket === null ? `${p.ownerTouches} owner touches` : `${p.ownerTouchesPerTicket} owner touches per ticket`}`,
|
|
298
|
+
`stalls ${p.stalls === 0 ? 'none' : `${p.stalls} (${durationText(p.stallMs)})`}`,
|
|
299
|
+
p.costPerShippedTicket === null ? `$${p.costUsd.toFixed(2)} spent` : `$${p.costPerShippedTicket.toFixed(2)} per shipped ticket`,
|
|
300
|
+
].join(' · ');
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* The autopilot part of a result: the other outcome metrics and the process.
|
|
304
|
+
*
|
|
305
|
+
* @param a - Scope
|
|
306
|
+
* @returns Lines
|
|
307
|
+
*/
|
|
308
|
+
export function autopilotSummaryLines(a) {
|
|
309
|
+
const lines = [];
|
|
310
|
+
if (a.outcomes.length > 0) {
|
|
311
|
+
lines.push('Other metrics:');
|
|
312
|
+
for (const o of a.outcomes) {
|
|
313
|
+
const word = o.verdict === 'worked' ? 'worked' : o.verdict === 'didnt' ? "didn't work" : o.verdict ? 'inconclusive' : 'not measured';
|
|
314
|
+
lines.push(`- ${metricLabel(o.metric)}: ${o.verdictReason ?? (o.lastError ? `fetch failed (${o.lastError.slice(0, 120)})` : 'n/a')} — ${word}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
const scope = `autopilot of ${a.projectName}${a.label ? `, label ${a.label}` : ''}`;
|
|
318
|
+
if (a.processResult)
|
|
319
|
+
lines.push(`Process (${scope}): ${a.processResult.noData ? 'no autopilot work recorded' : processLine(a.processResult)}`);
|
|
320
|
+
// A baseline window without autopilot traces is no data, not zeros: left out.
|
|
321
|
+
if (a.processBaseline && !a.processBaseline.noData)
|
|
322
|
+
lines.push(`Process before: ${processLine(a.processBaseline)}`);
|
|
323
|
+
return lines;
|
|
324
|
+
}
|
|
204
325
|
/**
|
|
205
326
|
* Experiment cards: store, lifecycle and the measuring tick.
|
|
206
327
|
*/
|
|
@@ -213,6 +334,10 @@ export class ExperimentService {
|
|
|
213
334
|
timer = null;
|
|
214
335
|
/** A tick is running (fetches can be slow; ticks never overlap) */
|
|
215
336
|
ticking = false;
|
|
337
|
+
/** Check-ins whose reads / send keep failing: next try and failures so far */
|
|
338
|
+
checkInRetry = new Map();
|
|
339
|
+
/** Experiments being measured right now (a measureNow racing a tick fetches once) */
|
|
340
|
+
measuring = new Set();
|
|
216
341
|
/**
|
|
217
342
|
* @param deps - Dependencies
|
|
218
343
|
*/
|
|
@@ -331,6 +456,7 @@ export class ExperimentService {
|
|
|
331
456
|
*/
|
|
332
457
|
record(e, event, detail) {
|
|
333
458
|
e.timeline.push({ at: this.now().toISOString(), event, ...(detail ? { detail: detail.slice(0, 500) } : {}) });
|
|
459
|
+
traceExperimentEvent(e.traceId, e.id, event, detail);
|
|
334
460
|
if (e.timeline.length > EXPERIMENT_CONSTANTS.MAX_TIMELINE)
|
|
335
461
|
e.timeline.splice(0, e.timeline.length - EXPERIMENT_CONSTANTS.MAX_TIMELINE);
|
|
336
462
|
}
|
|
@@ -414,14 +540,41 @@ export class ExperimentService {
|
|
|
414
540
|
}
|
|
415
541
|
const ticket = validateTicketLink(input.ticket);
|
|
416
542
|
const title = text(input.title) ?? hypothesis.slice(0, 80);
|
|
543
|
+
const scope = await this.parseAutopilotScope(input, metric);
|
|
544
|
+
const startedAt = input.startedAt === undefined || input.startedAt === null || input.startedAt === '' ? undefined : parseShipTime(String(input.startedAt), this.now());
|
|
545
|
+
// An autopilot card starts at its creation (or startedAt): the baseline is
|
|
546
|
+
// the equal window before it (specs/2026-10-03-autopilot-experiments.md §3).
|
|
547
|
+
const explicitShip = scope
|
|
548
|
+
? (startedAt ?? (input.shippedAt ? parseShipTime(String(input.shippedAt), this.now()) : this.now().toISOString()))
|
|
549
|
+
: input.shippedAt === undefined || input.shippedAt === null || input.shippedAt === ''
|
|
550
|
+
? undefined
|
|
551
|
+
: parseShipTime(String(input.shippedAt), this.now());
|
|
552
|
+
// A ticket that is already done ships the card right away. Its done
|
|
553
|
+
// transition dates the ship; with no recorded done time the caller must
|
|
554
|
+
// say when the change went live (guessing would skew the baseline).
|
|
555
|
+
let ticketDoneAt;
|
|
556
|
+
if (ticket && this.deps.ticketShipState && !explicitShip) {
|
|
557
|
+
const state = await this.deps.ticketShipState(ticket).catch((err) => {
|
|
558
|
+
this.logger.debug('Could not read the linked ticket (non-fatal)', { ticket: ticketLabel(ticket), error: errText(err) });
|
|
559
|
+
return { done: false };
|
|
560
|
+
});
|
|
561
|
+
if (state.done && !state.at) {
|
|
562
|
+
throw new ExperimentError(400, `Ticket ${ticketLabel(ticket)} is already done but has no recorded done time; pass shippedAt (the ISO time the change went live)`);
|
|
563
|
+
}
|
|
564
|
+
if (state.done && state.at)
|
|
565
|
+
ticketDoneAt = new Date(Math.min(Date.parse(state.at), this.now().getTime())).toISOString();
|
|
566
|
+
}
|
|
417
567
|
const created = await this.serial(async () => {
|
|
418
568
|
const data = await this.load();
|
|
419
569
|
const id = `${C.ID_PREFIX}${data.nextNumber}`;
|
|
420
570
|
data.nextNumber += 1;
|
|
421
571
|
const at = this.now().toISOString();
|
|
572
|
+
// The card's run: its ticket's trace, else a new `experiment` root
|
|
573
|
+
// (specs/2026-10-03-run-traces.md). `exp:EXP-n` only when tracing failed.
|
|
574
|
+
const traceId = startExperimentTrace({ id, title, ...(ticket ? { ticket: { kind: ticket.kind, id: ticket.id } } : {}) }, caller) ?? `exp:${id}`;
|
|
422
575
|
const e = {
|
|
423
576
|
id,
|
|
424
|
-
traceId
|
|
577
|
+
traceId,
|
|
425
578
|
title,
|
|
426
579
|
hypothesis,
|
|
427
580
|
direction,
|
|
@@ -434,9 +587,13 @@ export class ExperimentService {
|
|
|
434
587
|
status: 'planned',
|
|
435
588
|
createdAt: at,
|
|
436
589
|
updatedAt: at,
|
|
590
|
+
...(scope ? { autopilot: scope } : {}),
|
|
437
591
|
timeline: [],
|
|
438
592
|
};
|
|
439
593
|
this.record(e, 'created', `by ${caller}${ticket ? ` on ${ticketLabel(ticket)}` : ''}`);
|
|
594
|
+
if (scope) {
|
|
595
|
+
this.record(e, 'autopilot_scope', `autopilot of ${scope.projectName}${scope.label ? `, label ${scope.label}` : ''}; outcome metrics: ${[metricLabel(metric), ...scope.outcomes.map((o) => metricLabel(o.metric))].join('; ')}`);
|
|
596
|
+
}
|
|
440
597
|
data.experiments.push(e);
|
|
441
598
|
await this.save(data);
|
|
442
599
|
return e;
|
|
@@ -445,8 +602,231 @@ export class ExperimentService {
|
|
|
445
602
|
await this.deps.noteOnTicket(ticket, `Experiment ${created.id}: ${hypothesis} (metric: ${metricLabel(metric)}, ${windowDays}-day window; measured automatically after ship)`).catch((err) => this.logger.debug('Could not note the experiment on its ticket (non-fatal)', { id: created.id, error: errText(err) }));
|
|
446
603
|
}
|
|
447
604
|
this.logger.info('Experiment created', { id: created.id, caller, ticket: ticket ? ticketLabel(ticket) : undefined });
|
|
605
|
+
if (explicitShip)
|
|
606
|
+
return this.ship(created.id, caller, explicitShip);
|
|
607
|
+
if (ticketDoneAt && ticket)
|
|
608
|
+
return this.ship(created.id, `ticket ${ticketLabel(ticket)} done`, ticketDoneAt);
|
|
448
609
|
return created;
|
|
449
610
|
}
|
|
611
|
+
/**
|
|
612
|
+
* The autopilot scope of a new card, validated.
|
|
613
|
+
*
|
|
614
|
+
* @param input - Create input
|
|
615
|
+
* @param primary - The primary metric (its config is the default of the extra metrics)
|
|
616
|
+
* @returns Scope, or undefined for an ordinary card
|
|
617
|
+
* @throws ExperimentError(400)
|
|
618
|
+
*/
|
|
619
|
+
async parseAutopilotScope(input, primary) {
|
|
620
|
+
if (input.autopilot === undefined || input.autopilot === null || input.autopilot === '' || input.autopilot === false) {
|
|
621
|
+
if (input.metrics !== undefined && input.metrics !== null)
|
|
622
|
+
throw new ExperimentError(400, 'metrics (extra outcome metrics) are for autopilot cards: add autopilot: {project}');
|
|
623
|
+
return undefined;
|
|
624
|
+
}
|
|
625
|
+
if (!this.deps.autopilot)
|
|
626
|
+
throw new ExperimentError(400, 'Autopilot experiments are not available (the ticket autopilot is not running)');
|
|
627
|
+
const raw = (typeof input.autopilot === 'object' ? input.autopilot : {});
|
|
628
|
+
const ref = text(raw.project) ?? text(raw.projectId);
|
|
629
|
+
if (!ref)
|
|
630
|
+
throw new ExperimentError(400, 'autopilot.project is required (project id, name or path)');
|
|
631
|
+
let project;
|
|
632
|
+
try {
|
|
633
|
+
project = await this.deps.autopilot.resolveProject(ref);
|
|
634
|
+
}
|
|
635
|
+
catch (err) {
|
|
636
|
+
throw new ExperimentError(400, `autopilot.project: ${errText(err)}`);
|
|
637
|
+
}
|
|
638
|
+
const label = text(raw.label);
|
|
639
|
+
const list = input.metrics === undefined || input.metrics === null ? [] : input.metrics;
|
|
640
|
+
if (!Array.isArray(list))
|
|
641
|
+
throw new ExperimentError(400, 'metrics must be a list of metric definitions');
|
|
642
|
+
if (list.length > EXPERIMENT_CONSTANTS.MAX_EXTRA_METRICS)
|
|
643
|
+
throw new ExperimentError(400, `at most ${EXPERIMENT_CONSTANTS.MAX_EXTRA_METRICS} extra metrics`);
|
|
644
|
+
const outcomes = [];
|
|
645
|
+
for (const [i, m] of list.entries()) {
|
|
646
|
+
const withConfig = m && typeof m === 'object' ? { config: primary.config, ...m } : m;
|
|
647
|
+
try {
|
|
648
|
+
const metric = validateMetric(withConfig);
|
|
649
|
+
if (metric.config !== primary.config && this.deps.fileExists && !(await this.deps.fileExists(metric.config))) {
|
|
650
|
+
throw new ExperimentError(400, `seo-ops config not found: ${metric.config}`);
|
|
651
|
+
}
|
|
652
|
+
outcomes.push({ metric });
|
|
653
|
+
}
|
|
654
|
+
catch (err) {
|
|
655
|
+
throw new ExperimentError(400, `metrics[${i}]: ${errText(err)}`);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
return { projectId: project.id, projectName: project.name, ...(label ? { label } : {}), outcomes, checkIns: 0 };
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Autopilot cards: fetch the extra outcome metrics' baselines and the
|
|
662
|
+
* process baseline that are still missing (retried by the tick).
|
|
663
|
+
*
|
|
664
|
+
* @param id - EXP-n
|
|
665
|
+
*/
|
|
666
|
+
async captureAutopilotBaseline(id) {
|
|
667
|
+
const e = await this.get(id);
|
|
668
|
+
if (!e || e.status !== 'running' || !e.autopilot || !e.shippedAt)
|
|
669
|
+
return;
|
|
670
|
+
const fetched = [];
|
|
671
|
+
for (const [index, o] of e.autopilot.outcomes.entries()) {
|
|
672
|
+
if (o.baseline)
|
|
673
|
+
continue;
|
|
674
|
+
const ow = experimentWindows(e.shippedAt, e.windowDays, o.metric.source);
|
|
675
|
+
try {
|
|
676
|
+
fetched.push({ index, m: await this.deps.fetchMetric(o.metric, ow.baseline) });
|
|
677
|
+
}
|
|
678
|
+
catch (err) {
|
|
679
|
+
fetched.push({ index, error: errText(err).slice(0, 500) });
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
if (fetched.length === 0)
|
|
683
|
+
return;
|
|
684
|
+
await this.mutate(id, (x) => {
|
|
685
|
+
if (!x.autopilot)
|
|
686
|
+
return;
|
|
687
|
+
for (const f of fetched) {
|
|
688
|
+
const o = x.autopilot.outcomes[f.index];
|
|
689
|
+
if (!o || o.baseline)
|
|
690
|
+
continue;
|
|
691
|
+
if (f.m) {
|
|
692
|
+
o.baseline = f.m;
|
|
693
|
+
delete o.lastError;
|
|
694
|
+
this.record(x, 'outcome_baseline', `${metricLabel(o.metric)}: ${formatValue(f.m.total, o.metric.measure)} over ${f.m.start}..${f.m.end}`);
|
|
695
|
+
}
|
|
696
|
+
else if (o.lastError !== f.error) {
|
|
697
|
+
o.lastError = f.error;
|
|
698
|
+
this.record(x, 'fetch_failed', `baseline of ${metricLabel(o.metric)}: ${f.error}`);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Autopilot cards: the process baseline (as soon as the card starts) and
|
|
705
|
+
* the process result (once the observation window's last local day is
|
|
706
|
+
* over), each recorded once, independent of the outcome metrics. A failed
|
|
707
|
+
* read is retried by the next tick; a window with no autopilot traces is
|
|
708
|
+
* stored as no-data, never as zeros.
|
|
709
|
+
*
|
|
710
|
+
* @param id - EXP-n
|
|
711
|
+
*/
|
|
712
|
+
async captureProcess(id) {
|
|
713
|
+
const e = await this.get(id);
|
|
714
|
+
if (!e || e.status !== 'running' || !e.autopilot || !e.shippedAt || !this.deps.autopilot)
|
|
715
|
+
return;
|
|
716
|
+
const w = processWindows(e.shippedAt, e.windowDays);
|
|
717
|
+
const label = e.autopilot.label ?? null;
|
|
718
|
+
const read = async (range, what) => this.deps.autopilot?.process(e.autopilot.projectId, label, range).catch((err) => {
|
|
719
|
+
this.logger.debug(`Could not read the autopilot process ${what}`, { id, error: errText(err) });
|
|
720
|
+
return undefined;
|
|
721
|
+
});
|
|
722
|
+
const base = e.autopilot.processBaseline ? undefined : await read(w.baseline, 'baseline');
|
|
723
|
+
const result = !e.autopilot.processResult && this.now().getTime() >= w.dueAtMs ? await read(w.observation, 'result') : undefined;
|
|
724
|
+
if (!base && !result)
|
|
725
|
+
return;
|
|
726
|
+
await this.mutate(id, (x) => {
|
|
727
|
+
if (!x.autopilot)
|
|
728
|
+
return;
|
|
729
|
+
if (base && !x.autopilot.processBaseline) {
|
|
730
|
+
x.autopilot.processBaseline = base;
|
|
731
|
+
this.record(x, 'process_baseline', base.noData ? `no autopilot work in ${w.baseline.start}..${w.baseline.end}` : processLine(base));
|
|
732
|
+
}
|
|
733
|
+
if (result && !x.autopilot.processResult) {
|
|
734
|
+
x.autopilot.processResult = result;
|
|
735
|
+
this.record(x, 'process_result', result.noData ? `no autopilot work in ${w.observation.start}..${w.observation.end}` : processLine(result));
|
|
736
|
+
}
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Autopilot cards whose outcome fetch keeps failing: remind the owner at
|
|
741
|
+
* most once a week (the first notice is {@link fetchFailed}'s).
|
|
742
|
+
*
|
|
743
|
+
* @param id - EXP-n
|
|
744
|
+
*/
|
|
745
|
+
async remindStuck(id) {
|
|
746
|
+
const e = await this.get(id);
|
|
747
|
+
if (!e || !e.autopilot || !e.stuckReported || !this.deps.notifyOwner)
|
|
748
|
+
return;
|
|
749
|
+
const last = Date.parse(e.stuckNoticeAt ?? '') || 0;
|
|
750
|
+
if (this.now().getTime() - last < EXPERIMENT_CONSTANTS.CHECK_IN_INTERVAL_MS)
|
|
751
|
+
return;
|
|
752
|
+
const process = e.autopilot.processResult && !e.autopilot.processResult.noData ? `\nProcess so far: ${processLine(e.autopilot.processResult)}` : '';
|
|
753
|
+
const sent = await this.deps
|
|
754
|
+
.notifyOwner({
|
|
755
|
+
title: `Experiment ${e.id} still can't fetch its metric`,
|
|
756
|
+
message: `${e.title}\nMetric: ${metricLabel(e.metric)}\nStill failing: ${e.lastError ?? 'unknown error'}\nFix the seo-ops config or credentials (${e.metric.config}).${process}`,
|
|
757
|
+
urgent: false,
|
|
758
|
+
})
|
|
759
|
+
.catch(() => false);
|
|
760
|
+
if (sent)
|
|
761
|
+
await this.mutate(id, (x) => {
|
|
762
|
+
x.stuckNoticeAt = this.now().toISOString();
|
|
763
|
+
this.record(x, 'stuck_reminder', x.lastError ?? '');
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Autopilot cards: one short owner note per week while running.
|
|
768
|
+
*
|
|
769
|
+
* @param id - EXP-n
|
|
770
|
+
* @returns True when a check-in went out
|
|
771
|
+
*/
|
|
772
|
+
async checkIn(id) {
|
|
773
|
+
const e = await this.get(id);
|
|
774
|
+
if (!e || e.status !== 'running' || !e.autopilot || !e.shippedAt || !this.deps.autopilot)
|
|
775
|
+
return false;
|
|
776
|
+
const nowMs = this.now().getTime();
|
|
777
|
+
if (e.dueAt && Date.parse(e.dueAt) <= nowMs)
|
|
778
|
+
return false;
|
|
779
|
+
const week = Math.floor((nowMs - Date.parse(e.shippedAt)) / EXPERIMENT_CONSTANTS.CHECK_IN_INTERVAL_MS);
|
|
780
|
+
if (week < 1 || week <= e.autopilot.checkIns)
|
|
781
|
+
return false;
|
|
782
|
+
const retry = this.checkInRetry.get(id);
|
|
783
|
+
if (retry && nowMs < retry.at)
|
|
784
|
+
return false;
|
|
785
|
+
const backOff = () => {
|
|
786
|
+
const failures = (retry?.failures ?? 0) + 1;
|
|
787
|
+
const C = EXPERIMENT_CONSTANTS;
|
|
788
|
+
this.checkInRetry.set(id, { failures, at: nowMs + Math.min(C.CHECK_IN_RETRY_MAX_MS, C.CHECK_IN_RETRY_MIN_MS * 2 ** (failures - 1)) });
|
|
789
|
+
return false;
|
|
790
|
+
};
|
|
791
|
+
const w = experimentWindows(e.shippedAt, e.windowDays, e.metric.source);
|
|
792
|
+
// Process numbers in local days, start day included (the autopilot's days).
|
|
793
|
+
const pw = processWindows(e.shippedAt, e.windowDays);
|
|
794
|
+
const today = localDay(this.now());
|
|
795
|
+
const soFar = { start: pw.observation.start, end: today < pw.observation.end ? today : pw.observation.end };
|
|
796
|
+
const process = await this.deps.autopilot.process(e.autopilot.projectId, e.autopilot.label ?? null, soFar).catch(() => null);
|
|
797
|
+
// No process numbers: no note (it would say nothing); retry with a backoff.
|
|
798
|
+
if (!process)
|
|
799
|
+
return backOff();
|
|
800
|
+
// The primary metric so far: only days that have settled.
|
|
801
|
+
const lag = EXPERIMENT_CONSTANTS.SOURCE_LAG_DAYS[e.metric.source] ?? 0;
|
|
802
|
+
const settled = new Date(nowMs - (lag + 1) * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
|
|
803
|
+
const metricEnd = settled < w.observation.end ? settled : w.observation.end;
|
|
804
|
+
let metricSoFar = null;
|
|
805
|
+
if (metricEnd >= w.observation.start) {
|
|
806
|
+
metricSoFar = await this.deps.fetchMetric(e.metric, { start: w.observation.start, end: metricEnd }).catch(() => null);
|
|
807
|
+
}
|
|
808
|
+
const lines = [`${e.id} week ${week}: ${e.title}`];
|
|
809
|
+
lines.push(process.noData ? 'No autopilot work recorded yet.' : processLine(process));
|
|
810
|
+
if (metricSoFar) {
|
|
811
|
+
const days = Math.round((Date.parse(`${metricEnd}T00:00:00Z`) - Date.parse(`${w.observation.start}T00:00:00Z`)) / (24 * 60 * 60 * 1000)) + 1;
|
|
812
|
+
const base = e.baseline ? ` (baseline ${formatValue(e.baseline.total, e.metric.measure)} over ${e.windowDays} days)` : '';
|
|
813
|
+
lines.push(`${metricLabel(e.metric)}: ${formatValue(metricSoFar.total, e.metric.measure)} over the first ${days} day${days === 1 ? '' : 's'}${base}`);
|
|
814
|
+
}
|
|
815
|
+
lines.push(`Result due ${e.dueAt?.slice(0, 10) ?? 'later'}.`);
|
|
816
|
+
const message = lines.join('\n');
|
|
817
|
+
const sent = this.deps.notifyOwner ? await this.deps.notifyOwner({ title: `Experiment ${e.id}: week ${week}`, message, urgent: false }).catch(() => false) : true;
|
|
818
|
+
if (!sent)
|
|
819
|
+
return backOff();
|
|
820
|
+
this.checkInRetry.delete(id);
|
|
821
|
+
await this.mutate(id, (x) => {
|
|
822
|
+
if (!x.autopilot)
|
|
823
|
+
return;
|
|
824
|
+
x.autopilot.checkIns = week;
|
|
825
|
+
x.autopilot.lastCheckInAt = this.now().toISOString();
|
|
826
|
+
this.record(x, 'check_in', `week ${week}: ${process.noData ? 'no autopilot work yet' : processLine(process)}${metricSoFar ? `; ${metricLabel(e.metric)} so far ${formatValue(metricSoFar.total, e.metric.measure)}` : ''}`);
|
|
827
|
+
});
|
|
828
|
+
return true;
|
|
829
|
+
}
|
|
450
830
|
/**
|
|
451
831
|
* Mark an experiment shipped: fix its windows, record the prediction and
|
|
452
832
|
* capture the baseline.
|
|
@@ -458,12 +838,7 @@ export class ExperimentService {
|
|
|
458
838
|
* @throws ExperimentError(404 / 409 / 400)
|
|
459
839
|
*/
|
|
460
840
|
async ship(id, caller, shippedAt) {
|
|
461
|
-
const
|
|
462
|
-
const t = Date.parse(at);
|
|
463
|
-
if (Number.isNaN(t))
|
|
464
|
-
throw new ExperimentError(400, 'shippedAt must be an ISO time');
|
|
465
|
-
if (t > this.now().getTime())
|
|
466
|
-
throw new ExperimentError(400, 'shippedAt is in the future');
|
|
841
|
+
const t = Date.parse(parseShipTime(shippedAt ?? this.now().toISOString(), this.now()));
|
|
467
842
|
await this.mutate(id, (e) => {
|
|
468
843
|
if (e.status !== 'planned')
|
|
469
844
|
throw new ExperimentError(409, `${e.id} is ${e.status}; only a planned experiment can ship`);
|
|
@@ -473,10 +848,13 @@ export class ExperimentService {
|
|
|
473
848
|
e.dueAt = w.dueAt;
|
|
474
849
|
e.fetchAttempts = 0;
|
|
475
850
|
e.stuckReported = false;
|
|
851
|
+
delete e.lastFetchAt;
|
|
476
852
|
this.record(e, 'shipped', `by ${caller}; baseline ${w.baseline.start}..${w.baseline.end}, result ${w.observation.start}..${w.observation.end}, due ${w.dueAt.slice(0, 10)}`);
|
|
477
853
|
});
|
|
478
854
|
await this.recordPrediction(id);
|
|
479
855
|
await this.captureBaseline(id);
|
|
856
|
+
// Autopilot cards: the process baseline does not wait for the outcome fetch.
|
|
857
|
+
await this.captureProcess(id);
|
|
480
858
|
return (await this.get(id));
|
|
481
859
|
}
|
|
482
860
|
/**
|
|
@@ -550,18 +928,33 @@ export class ExperimentService {
|
|
|
550
928
|
const nowMs = this.now().getTime();
|
|
551
929
|
for (const e of all.experiments) {
|
|
552
930
|
try {
|
|
553
|
-
if (e.status === 'planned' && e.ticket && this.deps.
|
|
554
|
-
const
|
|
555
|
-
if (at) {
|
|
556
|
-
const t = Math.min(Date.parse(at) || nowMs, nowMs);
|
|
931
|
+
if (e.status === 'planned' && e.ticket && this.deps.ticketShipState) {
|
|
932
|
+
const state = await this.deps.ticketShipState(e.ticket);
|
|
933
|
+
if (state.done && state.at) {
|
|
934
|
+
const t = Math.min(Date.parse(state.at) || nowMs, nowMs);
|
|
557
935
|
await this.ship(e.id, `ticket ${ticketLabel(e.ticket)} done`, new Date(t).toISOString());
|
|
558
936
|
shipped += 1;
|
|
559
937
|
}
|
|
938
|
+
else if (state.done) {
|
|
939
|
+
await this.shipTimeUnknown(e.id);
|
|
940
|
+
}
|
|
560
941
|
continue;
|
|
561
942
|
}
|
|
562
943
|
if (e.status === 'running') {
|
|
944
|
+
// Autopilot process numbers and check-ins run on their own schedule:
|
|
945
|
+
// a failing outcome fetch (e.g. missing credentials) never holds them.
|
|
946
|
+
if (e.autopilot) {
|
|
947
|
+
await this.captureProcess(e.id);
|
|
948
|
+
await this.checkIn(e.id);
|
|
949
|
+
await this.remindStuck(e.id);
|
|
950
|
+
}
|
|
951
|
+
// After MAX_FETCH_ATTEMPTS failures in a row, retry once a day.
|
|
952
|
+
if (this.backingOff(e, nowMs))
|
|
953
|
+
continue;
|
|
563
954
|
if (!e.baseline)
|
|
564
955
|
await this.captureBaseline(e.id);
|
|
956
|
+
if (e.autopilot)
|
|
957
|
+
await this.captureAutopilotBaseline(e.id);
|
|
565
958
|
if (e.dueAt && Date.parse(e.dueAt) <= nowMs) {
|
|
566
959
|
const after = await this.get(e.id);
|
|
567
960
|
if (after?.baseline) {
|
|
@@ -583,6 +976,49 @@ export class ExperimentService {
|
|
|
583
976
|
// ---------------------------------------------------------------------------
|
|
584
977
|
// Steps
|
|
585
978
|
// ---------------------------------------------------------------------------
|
|
979
|
+
/**
|
|
980
|
+
* Whether a running experiment's fetches are backing off: after
|
|
981
|
+
* MAX_FETCH_ATTEMPTS failures in a row the tick retries once every
|
|
982
|
+
* FETCH_BACKOFF_MS instead of every tick.
|
|
983
|
+
*
|
|
984
|
+
* @param e - Experiment
|
|
985
|
+
* @param nowMs - Now
|
|
986
|
+
* @returns True to skip this tick
|
|
987
|
+
*/
|
|
988
|
+
backingOff(e, nowMs) {
|
|
989
|
+
if ((e.fetchAttempts ?? 0) < EXPERIMENT_CONSTANTS.MAX_FETCH_ATTEMPTS || !e.lastFetchAt)
|
|
990
|
+
return false;
|
|
991
|
+
return nowMs - Date.parse(e.lastFetchAt) < EXPERIMENT_CONSTANTS.FETCH_BACKOFF_MS;
|
|
992
|
+
}
|
|
993
|
+
/**
|
|
994
|
+
* The linked ticket is done but its done time is not recorded: the card
|
|
995
|
+
* cannot be dated, so it waits for an explicit ship. Recorded (and the
|
|
996
|
+
* owner told) once.
|
|
997
|
+
*
|
|
998
|
+
* @param id - EXP-n
|
|
999
|
+
*/
|
|
1000
|
+
async shipTimeUnknown(id) {
|
|
1001
|
+
let first = null;
|
|
1002
|
+
await this.mutate(id, (e) => {
|
|
1003
|
+
if (e.status !== 'planned' || e.timeline.some((t) => t.event === 'ship_time_unknown'))
|
|
1004
|
+
return;
|
|
1005
|
+
this.record(e, 'ship_time_unknown', 'the linked ticket is done but has no recorded done time; ship it with shippedAt');
|
|
1006
|
+
first = { ...e };
|
|
1007
|
+
});
|
|
1008
|
+
if (!first)
|
|
1009
|
+
return;
|
|
1010
|
+
const e = first;
|
|
1011
|
+
this.logger.warn('Experiment ticket is done without a done time; waiting for an explicit ship', { id });
|
|
1012
|
+
if (this.deps.notifyOwner && e.ticket) {
|
|
1013
|
+
await this.deps
|
|
1014
|
+
.notifyOwner({
|
|
1015
|
+
title: `Experiment ${e.id} needs its ship time`,
|
|
1016
|
+
message: `${e.title}\nTicket ${ticketLabel(e.ticket)} is done, but its log has no done time, so the baseline can't be dated. Ship it with the time the change went live: experiment-card ship --id ${e.id} --shipped-at <ISO time>.`,
|
|
1017
|
+
urgent: false,
|
|
1018
|
+
})
|
|
1019
|
+
.catch(() => false);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
586
1022
|
/**
|
|
587
1023
|
* Record the creating agent's prediction that the hypothesis holds.
|
|
588
1024
|
*
|
|
@@ -614,22 +1050,27 @@ export class ExperimentService {
|
|
|
614
1050
|
let tell = null;
|
|
615
1051
|
await this.mutate(id, (e) => {
|
|
616
1052
|
e.fetchAttempts = (e.fetchAttempts ?? 0) + 1;
|
|
1053
|
+
e.lastFetchAt = this.now().toISOString();
|
|
617
1054
|
e.lastError = errText(err).slice(0, 500);
|
|
618
1055
|
this.record(e, 'fetch_failed', `${step}: ${e.lastError}`);
|
|
619
1056
|
if (e.fetchAttempts >= EXPERIMENT_CONSTANTS.MAX_FETCH_ATTEMPTS && !e.stuckReported) {
|
|
620
1057
|
e.stuckReported = true;
|
|
1058
|
+
e.stuckNoticeAt = this.now().toISOString();
|
|
621
1059
|
tell = { ...e };
|
|
622
1060
|
}
|
|
623
1061
|
});
|
|
624
1062
|
if (tell && this.deps.notifyOwner) {
|
|
625
1063
|
const e = tell;
|
|
626
|
-
await this.deps
|
|
1064
|
+
const sent = await this.deps
|
|
627
1065
|
.notifyOwner({
|
|
628
1066
|
title: `Experiment ${e.id} can't fetch its ${step}`,
|
|
629
|
-
message: `${e.title}\nMetric: ${metricLabel(e.metric)}\nThe last ${EXPERIMENT_CONSTANTS.MAX_FETCH_ATTEMPTS} tries failed: ${e.lastError}\nIt
|
|
1067
|
+
message: `${e.title}\nMetric: ${metricLabel(e.metric)}\nThe last ${EXPERIMENT_CONSTANTS.MAX_FETCH_ATTEMPTS} tries failed: ${e.lastError}\nIt now retries once a day; fix the seo-ops config or credentials (${e.metric.config}).`,
|
|
630
1068
|
urgent: false,
|
|
631
1069
|
})
|
|
632
1070
|
.catch(() => false);
|
|
1071
|
+
// Not delivered: try again on the next failure.
|
|
1072
|
+
if (!sent)
|
|
1073
|
+
await this.mutate(id, (x) => { x.stuckReported = false; }).catch(() => undefined);
|
|
633
1074
|
}
|
|
634
1075
|
}
|
|
635
1076
|
/**
|
|
@@ -651,12 +1092,20 @@ export class ExperimentService {
|
|
|
651
1092
|
return;
|
|
652
1093
|
}
|
|
653
1094
|
await this.mutate(id, (x) => {
|
|
1095
|
+
// A concurrent measureNow / tick may have captured it meanwhile.
|
|
1096
|
+
if (x.status !== 'running' || x.baseline)
|
|
1097
|
+
return;
|
|
654
1098
|
x.baseline = m;
|
|
655
1099
|
x.fetchAttempts = 0;
|
|
656
1100
|
x.stuckReported = false;
|
|
657
1101
|
delete x.lastError;
|
|
1102
|
+
delete x.lastFetchAt;
|
|
658
1103
|
this.record(x, 'baseline_captured', `${formatValue(m.total, x.metric.measure)} over ${m.start}..${m.end} (volume ${m.volume})`);
|
|
659
1104
|
});
|
|
1105
|
+
if (e.autopilot) {
|
|
1106
|
+
await this.captureAutopilotBaseline(id);
|
|
1107
|
+
await this.captureProcess(id);
|
|
1108
|
+
}
|
|
660
1109
|
}
|
|
661
1110
|
/**
|
|
662
1111
|
* Fetch the observation window and label the result.
|
|
@@ -664,6 +1113,22 @@ export class ExperimentService {
|
|
|
664
1113
|
* @param id - EXP-n
|
|
665
1114
|
*/
|
|
666
1115
|
async measure(id) {
|
|
1116
|
+
if (this.measuring.has(id))
|
|
1117
|
+
return;
|
|
1118
|
+
this.measuring.add(id);
|
|
1119
|
+
try {
|
|
1120
|
+
await this.measureOnce(id);
|
|
1121
|
+
}
|
|
1122
|
+
finally {
|
|
1123
|
+
this.measuring.delete(id);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* One measurement (see {@link measure}).
|
|
1128
|
+
*
|
|
1129
|
+
* @param id - EXP-n
|
|
1130
|
+
*/
|
|
1131
|
+
async measureOnce(id) {
|
|
667
1132
|
const e = await this.get(id);
|
|
668
1133
|
if (!e || e.status !== 'running' || !e.baseline || !e.shippedAt)
|
|
669
1134
|
return;
|
|
@@ -676,8 +1141,27 @@ export class ExperimentService {
|
|
|
676
1141
|
await this.fetchFailed(id, 'result', err);
|
|
677
1142
|
return;
|
|
678
1143
|
}
|
|
1144
|
+
// Autopilot cards: the extra outcome metrics and the process numbers of
|
|
1145
|
+
// the same window (a failed extra fetch never blocks the result).
|
|
1146
|
+
const extras = [];
|
|
1147
|
+
let process = null;
|
|
1148
|
+
if (e.autopilot) {
|
|
1149
|
+
for (const o of e.autopilot.outcomes) {
|
|
1150
|
+
try {
|
|
1151
|
+
extras.push({ m: await this.deps.fetchMetric(o.metric, experimentWindows(e.shippedAt, e.windowDays, o.metric.source).observation) });
|
|
1152
|
+
}
|
|
1153
|
+
catch (err) {
|
|
1154
|
+
extras.push({ error: errText(err).slice(0, 500) });
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
if (this.deps.autopilot && !e.autopilot.processResult) {
|
|
1158
|
+
process = await this.deps.autopilot.process(e.autopilot.projectId, e.autopilot.label ?? null, processWindows(e.shippedAt, e.windowDays).observation).catch(() => null);
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
679
1161
|
await this.mutate(id, (x) => {
|
|
680
|
-
|
|
1162
|
+
// Re-checked under the store lock: a racing measureNow / tick may
|
|
1163
|
+
// have measured it already.
|
|
1164
|
+
if (x.status !== 'running' || !x.baseline)
|
|
681
1165
|
return;
|
|
682
1166
|
const v = decideVerdict(x.metric.measure, x.direction, x.baseline, m);
|
|
683
1167
|
x.result = m;
|
|
@@ -686,7 +1170,33 @@ export class ExperimentService {
|
|
|
686
1170
|
x.status = 'done';
|
|
687
1171
|
x.fetchAttempts = 0;
|
|
688
1172
|
delete x.lastError;
|
|
1173
|
+
delete x.lastFetchAt;
|
|
689
1174
|
this.record(x, 'measured', `${v.verdict}: ${v.reason}`);
|
|
1175
|
+
if (x.autopilot) {
|
|
1176
|
+
for (const [i, o] of x.autopilot.outcomes.entries()) {
|
|
1177
|
+
const got = extras[i];
|
|
1178
|
+
if (!got)
|
|
1179
|
+
continue;
|
|
1180
|
+
if (got.m) {
|
|
1181
|
+
o.result = got.m;
|
|
1182
|
+
delete o.lastError;
|
|
1183
|
+
if (o.baseline) {
|
|
1184
|
+
const ov = decideVerdict(o.metric.measure, defaultDirection(o.metric.measure), o.baseline, got.m);
|
|
1185
|
+
o.verdict = ov.verdict;
|
|
1186
|
+
o.verdictReason = ov.reason;
|
|
1187
|
+
}
|
|
1188
|
+
this.record(x, 'outcome_result', `${metricLabel(o.metric)}: ${o.verdictReason ?? `${formatValue(got.m.total, o.metric.measure)} (no baseline)`}`);
|
|
1189
|
+
}
|
|
1190
|
+
else {
|
|
1191
|
+
o.lastError = got.error;
|
|
1192
|
+
this.record(x, 'fetch_failed', `result of ${metricLabel(o.metric)}: ${got.error}`);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
if (process && !x.autopilot.processResult) {
|
|
1196
|
+
x.autopilot.processResult = process;
|
|
1197
|
+
this.record(x, 'process_result', process.noData ? 'no autopilot work in the window' : processLine(process));
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
690
1200
|
});
|
|
691
1201
|
this.logger.info('Experiment measured', { id });
|
|
692
1202
|
}
|
|
@@ -722,14 +1232,29 @@ export class ExperimentService {
|
|
|
722
1232
|
});
|
|
723
1233
|
}
|
|
724
1234
|
if (!e.reportedAt && this.deps.notifyOwner) {
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
1235
|
+
// Claim the report under the store lock before sending, so a racing
|
|
1236
|
+
// followUp cannot send it twice; release the claim when not delivered.
|
|
1237
|
+
const claimAt = this.now().toISOString();
|
|
1238
|
+
let claimed = false;
|
|
1239
|
+
await this.mutate(id, (x) => {
|
|
1240
|
+
if (x.reportedAt)
|
|
1241
|
+
return;
|
|
1242
|
+
x.reportedAt = claimAt;
|
|
1243
|
+
claimed = true;
|
|
1244
|
+
});
|
|
1245
|
+
if (claimed) {
|
|
1246
|
+
const sent = await this.deps
|
|
1247
|
+
.notifyOwner({ title: `Experiment ${e.id} ${verdictWord(e)}`, message: summary, urgent: false })
|
|
1248
|
+
.catch(() => false);
|
|
729
1249
|
await this.mutate(id, (x) => {
|
|
730
|
-
x.reportedAt
|
|
731
|
-
|
|
1250
|
+
if (x.reportedAt !== claimAt)
|
|
1251
|
+
return;
|
|
1252
|
+
if (sent)
|
|
1253
|
+
this.record(x, 'reported', 'owner');
|
|
1254
|
+
else
|
|
1255
|
+
delete x.reportedAt;
|
|
732
1256
|
});
|
|
1257
|
+
}
|
|
733
1258
|
}
|
|
734
1259
|
if (e.ticket && this.deps.noteOnTicket && !e.timeline.some((t) => t.event === 'ticket_noted')) {
|
|
735
1260
|
try {
|