crewly 1.20.195 → 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/orchestrator/fragments/lifecycle.md +1 -1
- package/config/roles/orchestrator/prompt.md +3 -3
- package/config/skills/_common/lib.sh +28 -5
- package/config/skills/_common/lib.test.sh +32 -1
- 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 +29 -1
- package/config/skills/agent/core/experiment-card/execute.sh +35 -1
- package/config/skills/agent/core/experiment-card/execute.test.sh +11 -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/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 +10 -2
- package/config/skills/orchestrator/send-message/execute.test.sh +9 -0
- package/config/skills/team-leader/design-checklist/execute.sh +2 -0
- package/dist/backend/backend/src/constants.d.ts +223 -5
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +206 -6
- 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 +10 -1
- package/dist/backend/backend/src/controllers/chat/chat.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/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/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/signal-digest/signal-digest.controller.js +1 -1
- package/dist/backend/backend/src/controllers/signal-digest/signal-digest.controller.js.map +1 -1
- 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 +30 -4
- package/dist/backend/backend/src/controllers/trace/trace.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/trace/trace.controller.js +278 -10
- package/dist/backend/backend/src/controllers/trace/trace.controller.js.map +1 -1
- 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 +313 -42
- 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/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +12 -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/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/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/chat/chat.service.d.ts +99 -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 +265 -40
- 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/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/experiments/experiment.service.d.ts +97 -1
- package/dist/backend/backend/src/services/experiments/experiment.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/experiments/experiment.service.js +372 -1
- package/dist/backend/backend/src/services/experiments/experiment.service.js.map +1 -1
- package/dist/backend/backend/src/services/experiments/experiment.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/experiments/experiment.wiring.js +19 -2
- package/dist/backend/backend/src/services/experiments/experiment.wiring.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/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/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 +42 -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/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/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-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 +18 -0
- package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.js +32 -0
- package/dist/backend/backend/src/services/slack/slack.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 +17 -0
- package/dist/backend/backend/src/services/trace/trace-context.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/trace/trace-context.service.js +58 -1
- package/dist/backend/backend/src/services/trace/trace-context.service.js.map +1 -1
- package/dist/backend/backend/src/services/trace/trace-http.middleware.d.ts +4 -0
- package/dist/backend/backend/src/services/trace/trace-http.middleware.d.ts.map +1 -1
- package/dist/backend/backend/src/services/trace/trace-http.middleware.js +32 -2
- package/dist/backend/backend/src/services/trace/trace-http.middleware.js.map +1 -1
- 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 +48 -0
- package/dist/backend/backend/src/services/trace/trace-recorder.d.ts.map +1 -1
- package/dist/backend/backend/src/services/trace/trace-recorder.js +121 -1
- package/dist/backend/backend/src/services/trace/trace-recorder.js.map +1 -1
- package/dist/backend/backend/src/services/trace/trace-store.d.ts +40 -1
- package/dist/backend/backend/src/services/trace/trace-store.d.ts.map +1 -1
- package/dist/backend/backend/src/services/trace/trace-store.js +126 -14
- package/dist/backend/backend/src/services/trace/trace-store.js.map +1 -1
- 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 +22 -3
- package/dist/backend/backend/src/services/trace/trace.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/trace/trace.types.js +20 -1
- package/dist/backend/backend/src/services/trace/trace.types.js.map +1 -1
- 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.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/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 +24 -2
- 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/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 +57 -0
- 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/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/work-item.types.d.ts +1 -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 +1 -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/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 +223 -5
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +206 -6
- 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 +12 -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/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/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/chat/chat.service.d.ts +99 -2
- package/dist/cli/backend/src/services/chat/chat.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat/chat.service.js +265 -40
- package/dist/cli/backend/src/services/chat/chat.service.js.map +1 -1
- 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/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/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/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 +42 -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/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-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 +18 -0
- package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack.service.js +32 -0
- package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/cli/backend/src/services/trace/trace-context.service.d.ts +17 -0
- package/dist/cli/backend/src/services/trace/trace-context.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/trace/trace-context.service.js +58 -1
- package/dist/cli/backend/src/services/trace/trace-context.service.js.map +1 -1
- package/dist/cli/backend/src/services/trace/trace-recorder.d.ts +48 -0
- package/dist/cli/backend/src/services/trace/trace-recorder.d.ts.map +1 -1
- package/dist/cli/backend/src/services/trace/trace-recorder.js +121 -1
- package/dist/cli/backend/src/services/trace/trace-recorder.js.map +1 -1
- package/dist/cli/backend/src/services/trace/trace-store.d.ts +40 -1
- package/dist/cli/backend/src/services/trace/trace-store.d.ts.map +1 -1
- package/dist/cli/backend/src/services/trace/trace-store.js +126 -14
- package/dist/cli/backend/src/services/trace/trace-store.js.map +1 -1
- package/dist/cli/backend/src/services/trace/trace.types.d.ts +22 -3
- package/dist/cli/backend/src/services/trace/trace.types.d.ts.map +1 -1
- package/dist/cli/backend/src/services/trace/trace.types.js +20 -1
- package/dist/cli/backend/src/services/trace/trace.types.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/work-item.types.d.ts +1 -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 +1 -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/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
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* @module services/project-tickets/ticket-autopilot.service
|
|
21
21
|
*/
|
|
22
22
|
import * as path from 'path';
|
|
23
|
-
import { TICKET_AUTOPILOT_CONSTANTS, USAGE_CONSTANTS } from '../../constants.js';
|
|
23
|
+
import { ORCHESTRATOR_SESSION_NAME, TICKET_AUTOPILOT_CONSTANTS, USAGE_CONSTANTS } from '../../constants.js';
|
|
24
24
|
import { LoggerService } from '../core/logger.service.js';
|
|
25
25
|
import { atomicWriteJson, safeReadJson } from '../../utils/file-io.utils.js';
|
|
26
26
|
import { createWorkItem, MAX_BRIEF_MARKDOWN_BYTES } from '../../types/v2/work-item.types.js';
|
|
@@ -30,6 +30,20 @@ import { getTeamLeads } from '../../utils/team.utils.js';
|
|
|
30
30
|
import { isTeamLead, } from './project-ticket-workflow.service.js';
|
|
31
31
|
import { OPEN_TICKET_STATUSES, decideDigest, decideTriage, hasNeedsOwnerLabel, inFlightByAssignee, isMemberIdle, localDateKey, memberAvailability, memberResponsibility, localMidnight, selectTriageCandidates, } from './ticket-autopilot-decision.js';
|
|
32
32
|
import { buildBudgetPausedMessage, buildDigestMessage, buildTriageBrief, } from './ticket-autopilot-messages.js';
|
|
33
|
+
import { autopilotRunTrace, startTriageTrace, traceAutopilotAction, createAutopilotTicketListener } from './ticket-autopilot-trace.js';
|
|
34
|
+
import { computeAutopilotStats, dayEndMs, daysBetween, dayStartMs, rangeDays, } from './ticket-autopilot-stats.js';
|
|
35
|
+
import { buildRetroBrief, duplicateOf, renderRetroMarkdown, RetroInputError, validateRetroInput, } from './ticket-autopilot-retro.js';
|
|
36
|
+
import { getTraceStore } from '../trace/trace-store.js';
|
|
37
|
+
import { clampStallMinutes, defaultStallMinutes } from '../trace/trace-metrics.js';
|
|
38
|
+
/** Skip reasons in words (run trace). */
|
|
39
|
+
const SKIP_WORDS = {
|
|
40
|
+
no_driver: 'no team lead to drive it',
|
|
41
|
+
budget_reached: 'daily budget reached',
|
|
42
|
+
triage_in_flight: 'a triage is still open',
|
|
43
|
+
nothing_to_triage: 'nothing to triage',
|
|
44
|
+
nobody_idle: 'nobody on the team is idle',
|
|
45
|
+
too_soon: 'too soon after the last triage',
|
|
46
|
+
};
|
|
33
47
|
/** WorkItem statuses that keep a triage "live" (one per project). */
|
|
34
48
|
const LIVE_STATUSES = new Set([
|
|
35
49
|
'queued',
|
|
@@ -59,6 +73,10 @@ export class TicketAutopilotService {
|
|
|
59
73
|
timer = null;
|
|
60
74
|
/** Serialises evaluations so an idle event and the tick never create two triages */
|
|
61
75
|
chain = Promise.resolve();
|
|
76
|
+
/** Unsubscribe of the ticket-change tracing listener */
|
|
77
|
+
unlisten = null;
|
|
78
|
+
/** Serialises retro submissions */
|
|
79
|
+
retroChain = Promise.resolve();
|
|
62
80
|
/**
|
|
63
81
|
* @param deps - Stores, pool, ledger, owner notifier, state file, clock
|
|
64
82
|
*/
|
|
@@ -93,6 +111,11 @@ export class TicketAutopilotService {
|
|
|
93
111
|
*/
|
|
94
112
|
start(intervalMs = TICKET_AUTOPILOT_CONSTANTS.TICK_INTERVAL_MS) {
|
|
95
113
|
this.deps.workflow.setAutopilotPolicy?.(this.policy());
|
|
114
|
+
// Ticket status / label changes go into the ticket's autopilot trace
|
|
115
|
+
// (specs/2026-10-03-autopilot-experiments.md §1).
|
|
116
|
+
if (!this.unlisten && this.deps.tickets.onChange) {
|
|
117
|
+
this.unlisten = this.deps.tickets.onChange(createAutopilotTicketListener(() => this.deps.directory.getProjects(), this.now));
|
|
118
|
+
}
|
|
96
119
|
if (intervalMs > 0 && !this.timer) {
|
|
97
120
|
this.timer = setInterval(() => {
|
|
98
121
|
void this.tick().catch((err) => this.logger.warn('Ticket autopilot tick failed (non-fatal)', { error: err instanceof Error ? err.message : String(err) }));
|
|
@@ -106,6 +129,8 @@ export class TicketAutopilotService {
|
|
|
106
129
|
clearInterval(this.timer);
|
|
107
130
|
this.timer = null;
|
|
108
131
|
this.deps.workflow.setAutopilotPolicy?.(null);
|
|
132
|
+
this.unlisten?.();
|
|
133
|
+
this.unlisten = null;
|
|
109
134
|
}
|
|
110
135
|
/**
|
|
111
136
|
* The brakes the ticket workflow asks about.
|
|
@@ -198,6 +223,7 @@ export class TicketAutopilotService {
|
|
|
198
223
|
}
|
|
199
224
|
if (projects.length > 0) {
|
|
200
225
|
await this.processDigest(projects).catch((err) => this.logger.warn('Ticket digest pass failed', { error: err instanceof Error ? err.message : String(err) }));
|
|
226
|
+
await this.processRetros(projects).catch((err) => this.logger.warn('Autopilot retro pass failed', { error: err instanceof Error ? err.message : String(err) }));
|
|
201
227
|
}
|
|
202
228
|
return out;
|
|
203
229
|
});
|
|
@@ -255,6 +281,7 @@ export class TicketAutopilotService {
|
|
|
255
281
|
const budget = this.budgetToday(settings, teams).tokens;
|
|
256
282
|
if (settings.enabled && spent >= budget)
|
|
257
283
|
await this.noticeBudgetPaused(project, ps, spent, budget, now, teams[0]?.name);
|
|
284
|
+
this.traceBudgetState(project, ps, settings.enabled && spent >= budget, spent, budget, now);
|
|
258
285
|
const { tickets } = await this.deps.tickets.list(project.path);
|
|
259
286
|
const live = await this.liveTriageItem(project, nowMs);
|
|
260
287
|
const selection = selectTriageCandidates({ tickets, teams, now: nowMs, listed: ps.listed });
|
|
@@ -274,6 +301,8 @@ export class TicketAutopilotService {
|
|
|
274
301
|
});
|
|
275
302
|
if (decision.action === 'skip' || !driver) {
|
|
276
303
|
this.logger.debug('Ticket autopilot: no triage', { projectId: project.id, trigger, decision });
|
|
304
|
+
if (decision.action === 'skip')
|
|
305
|
+
this.traceSkip(project, ps, decision.reason, trigger, selection.candidates.length, now);
|
|
277
306
|
await this.saveState();
|
|
278
307
|
return { projectId: project.id, decision };
|
|
279
308
|
}
|
|
@@ -332,7 +361,14 @@ export class TicketAutopilotService {
|
|
|
332
361
|
});
|
|
333
362
|
workItem.createdAt = now.toISOString();
|
|
334
363
|
workItem.targetSource = 'assigned';
|
|
364
|
+
// The triage turn runs in its own trace (tagged with the project and day),
|
|
365
|
+
// so its calls and usage never eat the run trace's event budget.
|
|
366
|
+
autopilotRunTrace(project, now);
|
|
367
|
+
const triageTrace = startTriageTrace(project, n, now);
|
|
368
|
+
if (triageTrace)
|
|
369
|
+
workItem.traceId = triageTrace;
|
|
335
370
|
await this.deps.pool.addToPool(workItem);
|
|
371
|
+
this.traceTriage(project, ps, workItem, driver.session, trigger, selection.candidates.map((c) => c.ticket), now);
|
|
336
372
|
ps.lastTriageAt = nowMs;
|
|
337
373
|
ps.lastTriageWorkItemId = workItem.id;
|
|
338
374
|
const listed = {};
|
|
@@ -454,6 +490,679 @@ export class TicketAutopilotService {
|
|
|
454
490
|
}
|
|
455
491
|
}
|
|
456
492
|
// ---------------------------------------------------------------------------
|
|
493
|
+
// Tracing (specs/2026-10-03-autopilot-experiments.md §1)
|
|
494
|
+
// ---------------------------------------------------------------------------
|
|
495
|
+
/**
|
|
496
|
+
* Trace the budget brake turning on or off. A pause from an earlier day
|
|
497
|
+
* ends at that day's rollover (the budget resets at midnight).
|
|
498
|
+
*
|
|
499
|
+
* @param project - Project
|
|
500
|
+
* @param ps - Its bookkeeping
|
|
501
|
+
* @param paused - Over the budget now
|
|
502
|
+
* @param spent - Tokens used today
|
|
503
|
+
* @param budget - Today's budget
|
|
504
|
+
* @param now - Clock
|
|
505
|
+
*/
|
|
506
|
+
traceBudgetState(project, ps, paused, spent, budget, now) {
|
|
507
|
+
const today = localDateKey(now);
|
|
508
|
+
if (ps.budgetPausedAt !== undefined) {
|
|
509
|
+
const fromEarlierDay = localDateKey(new Date(ps.budgetPausedAt)) !== today;
|
|
510
|
+
if (!paused || fromEarlierDay) {
|
|
511
|
+
traceAutopilotAction(project, 'budget_resumed', {
|
|
512
|
+
summary: fromEarlierDay ? `${project.name}: the daily budget reset at midnight; the autopilot runs again` : `${project.name}: under the daily budget again (boost); the autopilot runs again`,
|
|
513
|
+
outcome: 'ok',
|
|
514
|
+
data: { reason: fromEarlierDay ? 'new_day' : 'boost', pausedSince: new Date(ps.budgetPausedAt).toISOString(), spentTokens: spent, budgetTokens: Number.isFinite(budget) ? budget : -1 },
|
|
515
|
+
now,
|
|
516
|
+
});
|
|
517
|
+
delete ps.budgetPausedAt;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
if (paused && ps.budgetPausedAt === undefined) {
|
|
521
|
+
ps.budgetPausedAt = now.getTime();
|
|
522
|
+
traceAutopilotAction(project, 'budget_paused', {
|
|
523
|
+
summary: `${project.name}: daily budget reached (${spent} of ${budget} tokens); no triage or auto-claim until it resets`,
|
|
524
|
+
outcome: 'blocked',
|
|
525
|
+
data: { spentTokens: spent, budgetTokens: budget },
|
|
526
|
+
now,
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Trace a skipped evaluation, once per reason change per day (the tick
|
|
532
|
+
* runs every few minutes and must not flood the run trace).
|
|
533
|
+
*
|
|
534
|
+
* @param project - Project
|
|
535
|
+
* @param ps - Its bookkeeping
|
|
536
|
+
* @param reason - Why no triage
|
|
537
|
+
* @param trigger - Tick or idle member
|
|
538
|
+
* @param candidates - Tickets that would be triaged
|
|
539
|
+
* @param now - Clock
|
|
540
|
+
*/
|
|
541
|
+
traceSkip(project, ps, reason, trigger, candidates, now) {
|
|
542
|
+
if (reason === 'off')
|
|
543
|
+
return;
|
|
544
|
+
const day = localDateKey(now);
|
|
545
|
+
const seen = ps.skips?.day === day ? ps.skips.reasons : [];
|
|
546
|
+
if (seen.includes(reason))
|
|
547
|
+
return;
|
|
548
|
+
// A skip alone never starts the day's run trace: a day with nothing but
|
|
549
|
+
// skips is not an autopilot run (and gets no retro).
|
|
550
|
+
const run = traceAutopilotAction(project, 'skip', {
|
|
551
|
+
summary: `${project.name}: no triage — ${SKIP_WORDS[reason] ?? reason}`,
|
|
552
|
+
outcome: 'skipped',
|
|
553
|
+
data: { reason, trigger, candidates },
|
|
554
|
+
create: false,
|
|
555
|
+
now,
|
|
556
|
+
});
|
|
557
|
+
if (run)
|
|
558
|
+
ps.skips = { day, reasons: [...seen, reason] };
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Trace a triage: the step, and each ticket listed for the first time today.
|
|
562
|
+
*
|
|
563
|
+
* @param project - Project
|
|
564
|
+
* @param ps - Its bookkeeping
|
|
565
|
+
* @param workItem - The triage item
|
|
566
|
+
* @param driver - Who triages
|
|
567
|
+
* @param trigger - Tick or idle member
|
|
568
|
+
* @param tickets - Tickets listed
|
|
569
|
+
* @param now - Clock
|
|
570
|
+
*/
|
|
571
|
+
traceTriage(project, ps, workItem, driver, trigger, tickets, now) {
|
|
572
|
+
traceAutopilotAction(project, 'triage', {
|
|
573
|
+
summary: `${project.name}: ${driver} woken to triage ${tickets.length} ticket${tickets.length === 1 ? '' : 's'}`,
|
|
574
|
+
outcome: 'queued',
|
|
575
|
+
workItemId: workItem.id,
|
|
576
|
+
session: driver,
|
|
577
|
+
data: { trigger, count: tickets.length, tickets: tickets.map((t) => t.id).join(',') },
|
|
578
|
+
alsoTraceId: workItem.traceId ?? null,
|
|
579
|
+
now,
|
|
580
|
+
});
|
|
581
|
+
const day = localDateKey(now);
|
|
582
|
+
const seen = new Set(ps.triaged?.day === day ? ps.triaged.ids : []);
|
|
583
|
+
for (const t of tickets) {
|
|
584
|
+
if (seen.has(t.id))
|
|
585
|
+
continue;
|
|
586
|
+
seen.add(t.id);
|
|
587
|
+
traceAutopilotAction(project, 'triage_ticket', {
|
|
588
|
+
summary: `${t.id} listed for triage: ${t.title}`,
|
|
589
|
+
ticketId: t.id,
|
|
590
|
+
session: driver,
|
|
591
|
+
data: { status: t.status, priority: t.priority, labels: t.labels.join(',') },
|
|
592
|
+
now,
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
ps.triaged = { day, ids: [...seen] };
|
|
596
|
+
}
|
|
597
|
+
// ---------------------------------------------------------------------------
|
|
598
|
+
// Stats and runs (specs/2026-10-03-autopilot-experiments.md §2)
|
|
599
|
+
// ---------------------------------------------------------------------------
|
|
600
|
+
/**
|
|
601
|
+
* Stats of a project over the last `days` days (today included).
|
|
602
|
+
*
|
|
603
|
+
* @param ref - Project id, name or path
|
|
604
|
+
* @param caller - Owner, orchestrator or a lead of a project team
|
|
605
|
+
* @param opts - days (1..STATS_MAX_DAYS), label, stallMinutes
|
|
606
|
+
* @returns Stats, with the project and its settings
|
|
607
|
+
* @throws ProjectTicketError(400/403/404)
|
|
608
|
+
*/
|
|
609
|
+
async getStats(ref, caller, opts = {}) {
|
|
610
|
+
const project = await this.deps.workflow.resolveProject(ref);
|
|
611
|
+
await this.requireReader(caller, project);
|
|
612
|
+
const days = this.daysParam(opts.days);
|
|
613
|
+
const range = rangeDays(this.now(), days);
|
|
614
|
+
const stats = await this.statsFor(project, range[0], range[range.length - 1], opts.label ?? null, opts.stallMinutes);
|
|
615
|
+
const status = await this.statusOf(project);
|
|
616
|
+
return { ...stats, project: { id: project.id, name: project.name }, settings: status.settings, pausedForToday: status.pausedForToday };
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Stats of a project between two local days (no access check: experiments
|
|
620
|
+
* and the retro call it).
|
|
621
|
+
*
|
|
622
|
+
* @param projectRef - Project id, name or path
|
|
623
|
+
* @param start - First day (YYYY-MM-DD)
|
|
624
|
+
* @param end - Last day (YYYY-MM-DD)
|
|
625
|
+
* @param label - Only tickets with this label
|
|
626
|
+
* @param stallMinutes - Stall threshold
|
|
627
|
+
* @returns Stats
|
|
628
|
+
*/
|
|
629
|
+
async statsBetween(projectRef, start, end, label = null, stallMinutes) {
|
|
630
|
+
const project = await this.deps.workflow.resolveProject(projectRef);
|
|
631
|
+
return this.statsFor(project, start, end, label, stallMinutes);
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Stats of a project over a range of days.
|
|
635
|
+
*
|
|
636
|
+
* @param project - Project
|
|
637
|
+
* @param start - First day
|
|
638
|
+
* @param end - Last day
|
|
639
|
+
* @param label - Label filter
|
|
640
|
+
* @param stallMinutes - Stall threshold
|
|
641
|
+
* @returns Stats
|
|
642
|
+
*/
|
|
643
|
+
async statsFor(project, start, end, label, stallMinutes) {
|
|
644
|
+
const reader = this.traceReader();
|
|
645
|
+
const minutes = clampStallMinutes(stallMinutes ?? defaultStallMinutes());
|
|
646
|
+
const days = daysBetween(start, end);
|
|
647
|
+
const since = new Date(dayStartMs(start));
|
|
648
|
+
const until = dayEndMs(end);
|
|
649
|
+
// listTagged throws when the index cannot be read: a read failure is
|
|
650
|
+
// never reported as a range without autopilot work.
|
|
651
|
+
const entries = reader.listTagged({ autopilotProjectId: project.id, since }).filter((e) => Date.parse(e.root.createdAt) < until);
|
|
652
|
+
const traces = [];
|
|
653
|
+
let unreadable = 0;
|
|
654
|
+
for (const entry of entries) {
|
|
655
|
+
try {
|
|
656
|
+
const full = await reader.readAll(entry.traceId);
|
|
657
|
+
if (!full) {
|
|
658
|
+
unreadable += 1;
|
|
659
|
+
continue;
|
|
660
|
+
}
|
|
661
|
+
// Metrics are computed per day by the stats (event times, every stall).
|
|
662
|
+
traces.push({ entry: { ...entry, root: full.root ?? entry.root }, events: full.events });
|
|
663
|
+
}
|
|
664
|
+
catch {
|
|
665
|
+
unreadable += 1;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
const settings = resolveTicketAutopilotSettings(project.ticketAutopilot);
|
|
669
|
+
const teams = await this.projectTeams(project);
|
|
670
|
+
return computeAutopilotStats({
|
|
671
|
+
projectId: project.id,
|
|
672
|
+
label,
|
|
673
|
+
days,
|
|
674
|
+
traces,
|
|
675
|
+
ledger: this.ledgerByDay(teams, days),
|
|
676
|
+
dailyBudgetTokens: settings.dailyBudgetTokens,
|
|
677
|
+
stallMinutes: minutes,
|
|
678
|
+
now: this.now(),
|
|
679
|
+
unreadable,
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Run traces and ticket traces of the last `days` days, newest day first.
|
|
684
|
+
*
|
|
685
|
+
* @param ref - Project id, name or path
|
|
686
|
+
* @param caller - Owner, orchestrator or a lead of a project team
|
|
687
|
+
* @param opts - days, label
|
|
688
|
+
* @returns Days with their traces
|
|
689
|
+
*/
|
|
690
|
+
async getRuns(ref, caller, opts = {}) {
|
|
691
|
+
const project = await this.deps.workflow.resolveProject(ref);
|
|
692
|
+
await this.requireReader(caller, project);
|
|
693
|
+
const range = rangeDays(this.now(), this.daysParam(opts.days));
|
|
694
|
+
const wanted = new Set(range);
|
|
695
|
+
const entries = this.traceReader().listTagged({ autopilotProjectId: project.id, since: new Date(dayStartMs(range[0])) });
|
|
696
|
+
const label = opts.label?.trim().toLowerCase();
|
|
697
|
+
const byDay = new Map(range.map((d) => [d, { day: d, runTraceId: null, traces: [] }]));
|
|
698
|
+
for (const e of entries) {
|
|
699
|
+
const day = e.tags?.autopilot?.day;
|
|
700
|
+
if (!day || !wanted.has(day))
|
|
701
|
+
continue;
|
|
702
|
+
const row = byDay.get(day);
|
|
703
|
+
if (e.root.kind === 'autopilot') {
|
|
704
|
+
row.runTraceId = e.traceId;
|
|
705
|
+
continue;
|
|
706
|
+
}
|
|
707
|
+
const labels = e.tags?.labels ?? [];
|
|
708
|
+
if (label && !labels.some((l) => l.toLowerCase() === label))
|
|
709
|
+
continue;
|
|
710
|
+
row.traces.push({
|
|
711
|
+
traceId: e.traceId,
|
|
712
|
+
kind: e.root.kind,
|
|
713
|
+
summary: e.root.summary,
|
|
714
|
+
...(e.root.refs.ticketId ? { ticketId: e.root.refs.ticketId } : {}),
|
|
715
|
+
labels,
|
|
716
|
+
updatedAt: e.updatedAt,
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
return { project: { id: project.id, name: project.name }, days: [...byDay.values()].reverse() };
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* `?days=` within bounds.
|
|
723
|
+
*
|
|
724
|
+
* @param days - Requested
|
|
725
|
+
* @returns 1..STATS_MAX_DAYS (default STATS_DEFAULT_DAYS)
|
|
726
|
+
*/
|
|
727
|
+
daysParam(days) {
|
|
728
|
+
const C = TICKET_AUTOPILOT_CONSTANTS;
|
|
729
|
+
if (days === undefined || !Number.isFinite(days))
|
|
730
|
+
return C.STATS_DEFAULT_DAYS;
|
|
731
|
+
const n = Math.floor(days);
|
|
732
|
+
if (n < 1 || n > C.STATS_MAX_DAYS)
|
|
733
|
+
throw new ProjectTicketError(400, `days must be 1 to ${C.STATS_MAX_DAYS}`);
|
|
734
|
+
return n;
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* The ledger of the project's team sessions per day (what the budget counts).
|
|
738
|
+
*
|
|
739
|
+
* @param teams - Project teams
|
|
740
|
+
* @param days - Day keys
|
|
741
|
+
* @returns Tokens and USD per day
|
|
742
|
+
*/
|
|
743
|
+
ledgerByDay(teams, days) {
|
|
744
|
+
const sessions = new Set(teams.flatMap((t) => (t.members ?? []).map(sessionOf)).filter((x) => !!x));
|
|
745
|
+
const out = {};
|
|
746
|
+
for (const day of days) {
|
|
747
|
+
const since = new Date(dayStartMs(day));
|
|
748
|
+
const until = new Date(dayEndMs(day) - 1);
|
|
749
|
+
let tokens = 0;
|
|
750
|
+
let costUsd = 0;
|
|
751
|
+
for (const s of sessions) {
|
|
752
|
+
try {
|
|
753
|
+
const u = this.deps.ledger.getSessionUsageSince(s, since, until);
|
|
754
|
+
tokens += u.totalTokens;
|
|
755
|
+
costUsd += u.cost ?? 0;
|
|
756
|
+
}
|
|
757
|
+
catch {
|
|
758
|
+
// A ledger read failure leaves the day's number short, never fails the stats.
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
out[day] = { tokens, costUsd };
|
|
762
|
+
}
|
|
763
|
+
return out;
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* The trace reader (injected, else the process store + analysis).
|
|
767
|
+
*
|
|
768
|
+
* @returns Reader
|
|
769
|
+
*/
|
|
770
|
+
traceReader() {
|
|
771
|
+
if (this.deps.traces)
|
|
772
|
+
return this.deps.traces;
|
|
773
|
+
return {
|
|
774
|
+
listTagged: (filter) => getTraceStore().listTagged(filter),
|
|
775
|
+
readAll: (id) => getTraceStore().readAll(id),
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Whether an agent may read a project's autopilot traces: anyone on a team
|
|
780
|
+
* that works on the project (the rule decision cards use for tickets).
|
|
781
|
+
* The owner and the orchestrator are let through without a lookup.
|
|
782
|
+
*
|
|
783
|
+
* @param projectRef - Project id, name or path
|
|
784
|
+
* @param caller - Caller
|
|
785
|
+
* @returns True when allowed (false for an unknown project)
|
|
786
|
+
*/
|
|
787
|
+
async canReadProjectTraces(projectRef, caller) {
|
|
788
|
+
if (!caller.session || caller.session === ORCHESTRATOR_SESSION_NAME)
|
|
789
|
+
return true;
|
|
790
|
+
let project;
|
|
791
|
+
try {
|
|
792
|
+
project = await this.deps.workflow.resolveProject(projectRef);
|
|
793
|
+
}
|
|
794
|
+
catch {
|
|
795
|
+
return false;
|
|
796
|
+
}
|
|
797
|
+
const { access } = await this.deps.workflow.accessOf(caller, project);
|
|
798
|
+
return access !== 'outsider';
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* Owner, orchestrator, or a lead of a project team (the driver).
|
|
802
|
+
*
|
|
803
|
+
* @param caller - Caller
|
|
804
|
+
* @param project - Project
|
|
805
|
+
* @throws ProjectTicketError(403)
|
|
806
|
+
*/
|
|
807
|
+
async requireReader(caller, project) {
|
|
808
|
+
const { access } = await this.deps.workflow.accessOf(caller, project);
|
|
809
|
+
if (access !== 'owner' && access !== 'orchestrator' && access !== 'lead') {
|
|
810
|
+
throw new ProjectTicketError(403, 'Only the owner, the orchestrator or a team lead of the project can read its autopilot stats');
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
// ---------------------------------------------------------------------------
|
|
814
|
+
// Daily retro (specs/2026-10-03-autopilot-experiments.md §4)
|
|
815
|
+
// ---------------------------------------------------------------------------
|
|
816
|
+
/**
|
|
817
|
+
* Whether the daily retro runs for a project: its setting, else on while
|
|
818
|
+
* an autopilot experiment on the project is running.
|
|
819
|
+
*
|
|
820
|
+
* @param project - Project
|
|
821
|
+
* @returns True when on
|
|
822
|
+
*/
|
|
823
|
+
async retroOn(project) {
|
|
824
|
+
const setting = resolveTicketAutopilotSettings(project.ticketAutopilot).retro;
|
|
825
|
+
if (setting !== null)
|
|
826
|
+
return setting;
|
|
827
|
+
if (!this.deps.runningExperiment)
|
|
828
|
+
return false;
|
|
829
|
+
return this.deps.runningExperiment(project.id).catch(() => false);
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* Schedule yesterday's retro for every enabled project that wants one
|
|
833
|
+
* (once per project per day, at or after RETRO_HOUR_LOCAL).
|
|
834
|
+
*
|
|
835
|
+
* @param projects - Enabled projects
|
|
836
|
+
* @returns WorkItems created
|
|
837
|
+
*/
|
|
838
|
+
async processRetros(projects) {
|
|
839
|
+
if (!this.deps.retro)
|
|
840
|
+
return [];
|
|
841
|
+
const now = this.now();
|
|
842
|
+
if (now.getHours() < TICKET_AUTOPILOT_CONSTANTS.RETRO_HOUR_LOCAL)
|
|
843
|
+
return [];
|
|
844
|
+
const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1, 12);
|
|
845
|
+
const day = localDateKey(yesterday);
|
|
846
|
+
const state = await this.loadState();
|
|
847
|
+
const out = [];
|
|
848
|
+
let items = null;
|
|
849
|
+
for (const project of projects) {
|
|
850
|
+
const ps = (state.projects[project.id] ??= {});
|
|
851
|
+
if (ps.retroScheduledFor === day)
|
|
852
|
+
continue;
|
|
853
|
+
if (ps.retroRetryAt && now.getTime() < ps.retroRetryAt)
|
|
854
|
+
continue;
|
|
855
|
+
if (!(await this.retroOn(project)))
|
|
856
|
+
continue;
|
|
857
|
+
const runTrace = autopilotRunTrace(project, yesterday, false);
|
|
858
|
+
if (!runTrace) {
|
|
859
|
+
// The autopilot did nothing that day: nothing to review.
|
|
860
|
+
ps.retroScheduledFor = day;
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
const teams = await this.projectTeams(project);
|
|
864
|
+
const driver = this.resolveDriver(resolveTicketAutopilotSettings(project.ticketAutopilot), teams);
|
|
865
|
+
if (!driver)
|
|
866
|
+
continue;
|
|
867
|
+
// Unreadable traces: try again on a later tick rather than judge the day.
|
|
868
|
+
const stats = await this.statsFor(project, day, day, null).catch(() => null);
|
|
869
|
+
const dayStats = stats?.days[0];
|
|
870
|
+
if (!stats || !dayStats || stats.incomplete) {
|
|
871
|
+
// Back off while the reads keep failing (doubling, capped).
|
|
872
|
+
ps.retroFailures = (ps.retroFailures ?? 0) + 1;
|
|
873
|
+
ps.retroRetryAt = now.getTime() + retryBackoffMs(ps.retroFailures);
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
876
|
+
delete ps.retroFailures;
|
|
877
|
+
delete ps.retroRetryAt;
|
|
878
|
+
ps.retroScheduledFor = day;
|
|
879
|
+
// Only a day with real autopilot work gets a retro (skips and budget
|
|
880
|
+
// notices alone are not a run).
|
|
881
|
+
if (dayStats.triaged + dayStats.started + dayStats.done + dayStats.verified === 0) {
|
|
882
|
+
this.logger.debug('Autopilot retro skipped: no autopilot work that day', { projectId: project.id, day });
|
|
883
|
+
continue;
|
|
884
|
+
}
|
|
885
|
+
items ??= await this.deps.pool.getAllItems();
|
|
886
|
+
const live = items.some((wi) => wi.metadata?.kind === TICKET_AUTOPILOT_CONSTANTS.RETRO_METADATA_KIND && wi.metadata?.projectId === project.id && LIVE_STATUSES.has(wi.status));
|
|
887
|
+
if (live) {
|
|
888
|
+
this.logger.info('Autopilot retro skipped: the previous one is still open', { projectId: project.id, day });
|
|
889
|
+
continue;
|
|
890
|
+
}
|
|
891
|
+
const runs = this.traceReader()
|
|
892
|
+
.listTagged({ autopilotProjectId: project.id, day })
|
|
893
|
+
.filter((e) => e.root.kind !== 'autopilot' && e.root.kind !== 'triage')
|
|
894
|
+
.slice(0, 25)
|
|
895
|
+
.map((e) => ({ traceId: e.traceId, title: e.root.summary }));
|
|
896
|
+
const brief = buildRetroBrief({ project: { id: project.id, name: project.name }, day, stats: dayStats, traces: [{ traceId: runTrace, title: `Run trace ${day}` }, ...runs] });
|
|
897
|
+
const workItem = createWorkItem({
|
|
898
|
+
type: TICKET_AUTOPILOT_CONSTANTS.RETRO_WORK_ITEM_TYPE,
|
|
899
|
+
owner: 'team_lead',
|
|
900
|
+
target: driver.session,
|
|
901
|
+
title: `Autopilot retro: ${project.name} ${day}`,
|
|
902
|
+
description: `Review the ${day} autopilot run of ${project.name}: what shipped, where it stalled and why; classify each problem and submit the retro.`,
|
|
903
|
+
briefMarkdown: capBrief(brief),
|
|
904
|
+
metadata: {
|
|
905
|
+
kind: TICKET_AUTOPILOT_CONSTANTS.RETRO_METADATA_KIND,
|
|
906
|
+
projectId: project.id,
|
|
907
|
+
projectPath: project.path,
|
|
908
|
+
teamId: driver.teamId,
|
|
909
|
+
day,
|
|
910
|
+
requiresVerification: false,
|
|
911
|
+
},
|
|
912
|
+
});
|
|
913
|
+
workItem.createdAt = now.toISOString();
|
|
914
|
+
workItem.targetSource = 'assigned';
|
|
915
|
+
workItem.traceId = runTrace;
|
|
916
|
+
await this.deps.pool.addToPool(workItem);
|
|
917
|
+
ps.retroWorkItemId = workItem.id;
|
|
918
|
+
traceAutopilotAction(project, 'retro_scheduled', {
|
|
919
|
+
summary: `${driver.session} asked for the ${day} retro of ${project.name}`,
|
|
920
|
+
outcome: 'queued',
|
|
921
|
+
workItemId: workItem.id,
|
|
922
|
+
session: driver.session,
|
|
923
|
+
data: { day },
|
|
924
|
+
// Recorded in the reviewed day's run only: scheduling never starts today's run trace.
|
|
925
|
+
runTraceId: runTrace,
|
|
926
|
+
now,
|
|
927
|
+
});
|
|
928
|
+
this.logger.info('Autopilot retro scheduled', { projectId: project.id, day, driver: driver.session, workItemId: workItem.id });
|
|
929
|
+
out.push(workItem);
|
|
930
|
+
}
|
|
931
|
+
await this.saveState();
|
|
932
|
+
return out;
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* A retro came in: write it to the project wiki, file the harness gaps on
|
|
936
|
+
* the Crewly project (deduped, capped) and ask the owner ONE card for them.
|
|
937
|
+
*
|
|
938
|
+
* @param ref - Project id, name or path
|
|
939
|
+
* @param body - `{day, summary, problems}`
|
|
940
|
+
* @param caller - Owner, orchestrator or a lead of a project team
|
|
941
|
+
* @returns What was written and filed
|
|
942
|
+
* @throws ProjectTicketError(400/403/404/503)
|
|
943
|
+
*/
|
|
944
|
+
async submitRetro(ref, body, caller) {
|
|
945
|
+
// One retro at a time: the gap dedupe and the daily cap read and write the same state.
|
|
946
|
+
const run = this.retroChain.then(() => this.submitRetroNow(ref, body, caller), () => this.submitRetroNow(ref, body, caller));
|
|
947
|
+
this.retroChain = run.catch(() => undefined);
|
|
948
|
+
return run;
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* {@link submitRetro}, serialised.
|
|
952
|
+
*
|
|
953
|
+
* @param ref - Project
|
|
954
|
+
* @param body - Retro
|
|
955
|
+
* @param caller - Caller
|
|
956
|
+
* @returns What was written and filed
|
|
957
|
+
*/
|
|
958
|
+
async submitRetroNow(ref, body, caller) {
|
|
959
|
+
const project = await this.deps.workflow.resolveProject(ref);
|
|
960
|
+
await this.requireReader(caller, project);
|
|
961
|
+
const retroDeps = this.deps.retro;
|
|
962
|
+
if (!retroDeps)
|
|
963
|
+
throw new ProjectTicketError(503, 'Retros are not available (the autopilot is not fully started)');
|
|
964
|
+
let retro;
|
|
965
|
+
try {
|
|
966
|
+
retro = validateRetroInput(body);
|
|
967
|
+
}
|
|
968
|
+
catch (err) {
|
|
969
|
+
if (err instanceof RetroInputError)
|
|
970
|
+
throw new ProjectTicketError(400, err.message);
|
|
971
|
+
throw err;
|
|
972
|
+
}
|
|
973
|
+
const by = caller.session ?? 'owner';
|
|
974
|
+
const now = this.now();
|
|
975
|
+
if (retro.day > localDateKey(now))
|
|
976
|
+
throw new ProjectTicketError(400, `day ${retro.day} is in the future`);
|
|
977
|
+
const stats = await this.statsFor(project, retro.day, retro.day, null).catch(() => null);
|
|
978
|
+
const runTrace = autopilotRunTrace(project, new Date(dayStartMs(retro.day) + 12 * 3_600_000), false);
|
|
979
|
+
const filed = await this.fileHarnessGaps(project, retro, retroDeps, now);
|
|
980
|
+
const wikiPath = `${TICKET_AUTOPILOT_CONSTANTS.RETRO_WIKI_DIR}/${retro.day}.md`;
|
|
981
|
+
const markdown = renderRetroMarkdown({ project, retro, stats: stats?.days[0] ?? null, by, filed: filed.filed, runTraceId: runTrace });
|
|
982
|
+
const written = await retroDeps.writeWiki(project.path, wikiPath, markdown, by).catch((err) => {
|
|
983
|
+
this.logger.warn('Could not write the autopilot retro to the wiki', { projectId: project.id, error: err instanceof Error ? err.message : String(err) });
|
|
984
|
+
return false;
|
|
985
|
+
});
|
|
986
|
+
const counts = {};
|
|
987
|
+
for (const p of retro.problems)
|
|
988
|
+
counts[p.class] = (counts[p.class] ?? 0) + 1;
|
|
989
|
+
traceAutopilotAction(project, 'retro_filed', {
|
|
990
|
+
summary: `${by} filed the ${retro.day} retro of ${project.name}: ${retro.problems.length} problem${retro.problems.length === 1 ? '' : 's'}, ${filed.filed.length} harness-gap ticket${filed.filed.length === 1 ? '' : 's'}`,
|
|
991
|
+
outcome: 'ok',
|
|
992
|
+
...(caller.session ? { session: caller.session, actor: { kind: 'agent', session: caller.session } } : { actor: { kind: 'owner' } }),
|
|
993
|
+
data: { day: retro.day, wiki: written ? wikiPath : 'not written', ...counts, filed: filed.filed.length, duplicates: filed.duplicates.length, overCap: filed.overCap.length },
|
|
994
|
+
alsoTraceId: runTrace,
|
|
995
|
+
now,
|
|
996
|
+
});
|
|
997
|
+
this.logger.info('Autopilot retro filed', { projectId: project.id, day: retro.day, by, written, filed: filed.filed.map((t) => t.id) });
|
|
998
|
+
return { day: retro.day, wikiPath, written, ...filed };
|
|
999
|
+
}
|
|
1000
|
+
/**
|
|
1001
|
+
* File the retro's harness gaps on the Crewly project and ask the owner
|
|
1002
|
+
* one card for them.
|
|
1003
|
+
*
|
|
1004
|
+
* @param project - The reviewed project
|
|
1005
|
+
* @param retro - The retro
|
|
1006
|
+
* @param retroDeps - Side effects
|
|
1007
|
+
* @param now - Clock
|
|
1008
|
+
* @returns Filed, duplicate and over-cap gaps, and the card
|
|
1009
|
+
*/
|
|
1010
|
+
async fileHarnessGaps(project, retro, retroDeps, now) {
|
|
1011
|
+
const C = TICKET_AUTOPILOT_CONSTANTS;
|
|
1012
|
+
const gaps = retro.problems.filter((p) => p.class === 'harness_gap');
|
|
1013
|
+
const out = { filed: [], duplicates: [], overCap: [], decisionId: null };
|
|
1014
|
+
if (gaps.length === 0)
|
|
1015
|
+
return out;
|
|
1016
|
+
const target = await retroDeps.harnessProject();
|
|
1017
|
+
if (!target) {
|
|
1018
|
+
this.logger.warn('No harness project to file retro gaps on', { name: C.RETRO_HARNESS_PROJECT });
|
|
1019
|
+
out.overCap = gaps.map((g) => g.title);
|
|
1020
|
+
return out;
|
|
1021
|
+
}
|
|
1022
|
+
const state = await this.loadState();
|
|
1023
|
+
const today = localDateKey(now);
|
|
1024
|
+
const memory = now.getTime() - C.RETRO_GAP_MEMORY_DAYS * 24 * 3_600_000;
|
|
1025
|
+
state.retro.gaps = state.retro.gaps.filter((g) => g.at >= memory);
|
|
1026
|
+
const { tickets } = await this.deps.tickets.list(target.path);
|
|
1027
|
+
const known = [...tickets.filter((t) => t.status !== 'done' && t.status !== 'cancelled').map((t) => t.title), ...state.retro.gaps.map((g) => g.title)];
|
|
1028
|
+
for (const gap of gaps) {
|
|
1029
|
+
const dup = duplicateOf(gap.title, known);
|
|
1030
|
+
if (dup) {
|
|
1031
|
+
out.duplicates.push({ title: gap.title, duplicateOf: dup });
|
|
1032
|
+
continue;
|
|
1033
|
+
}
|
|
1034
|
+
if ((state.retro.gapDays[today] ?? 0) >= C.RETRO_MAX_GAPS_PER_DAY) {
|
|
1035
|
+
out.overCap.push(gap.title);
|
|
1036
|
+
continue;
|
|
1037
|
+
}
|
|
1038
|
+
const description = [
|
|
1039
|
+
`Found by the ${retro.day} autopilot retro of ${project.name}.`,
|
|
1040
|
+
'',
|
|
1041
|
+
gap.detail ?? '',
|
|
1042
|
+
'',
|
|
1043
|
+
gap.evidence ? `Evidence: ${gap.evidence}` : '',
|
|
1044
|
+
`Retro: ${project.name} wiki, ${C.RETRO_WIKI_DIR}/${retro.day}.md`,
|
|
1045
|
+
]
|
|
1046
|
+
.filter((l, i, all) => l !== '' || (i > 0 && all[i - 1] !== ''))
|
|
1047
|
+
.join('\n')
|
|
1048
|
+
.trim();
|
|
1049
|
+
const ticket = await retroDeps.createTicket(target, {
|
|
1050
|
+
title: gap.title,
|
|
1051
|
+
description,
|
|
1052
|
+
// Held until the owner approves: triage skips retro-pending tickets,
|
|
1053
|
+
// and nothing but this retro's card lifts the hold.
|
|
1054
|
+
labels: [...C.RETRO_GAP_LABELS, C.RETRO_PENDING_LABEL],
|
|
1055
|
+
source: `retro:${project.name}:${retro.day}`,
|
|
1056
|
+
});
|
|
1057
|
+
out.filed.push({ id: ticket.id, title: ticket.title });
|
|
1058
|
+
known.push(gap.title);
|
|
1059
|
+
state.retro.gaps.push({ title: gap.title, at: now.getTime() });
|
|
1060
|
+
state.retro.gapDays[today] = (state.retro.gapDays[today] ?? 0) + 1;
|
|
1061
|
+
traceAutopilotAction(project, 'retro_gap_ticket', {
|
|
1062
|
+
summary: `Harness gap filed on ${target.name} as ${ticket.id}: ${gap.title}`,
|
|
1063
|
+
outcome: 'queued',
|
|
1064
|
+
ticketId: ticket.id,
|
|
1065
|
+
data: { day: retro.day, harnessProject: target.name },
|
|
1066
|
+
now,
|
|
1067
|
+
});
|
|
1068
|
+
}
|
|
1069
|
+
for (const d of Object.keys(state.retro.gapDays))
|
|
1070
|
+
if (d < localDateKey(new Date(memory)))
|
|
1071
|
+
delete state.retro.gapDays[d];
|
|
1072
|
+
if (out.filed.length > 0) {
|
|
1073
|
+
const n = out.filed.length;
|
|
1074
|
+
try {
|
|
1075
|
+
const decision = await retroDeps.askOwner({
|
|
1076
|
+
key: `retro:${project.id}:${retro.day}`,
|
|
1077
|
+
title: `Harness gaps from the ${project.name} retro (${retro.day})`,
|
|
1078
|
+
question: `File ${n === 1 ? 'this harness gap' : `these ${n} harness gaps`} for the ${target.name} team?`,
|
|
1079
|
+
body: out.filed.map((t) => `• *${t.id}* ${t.title}`),
|
|
1080
|
+
approveLabel: C.RETRO_APPROVE_LABEL,
|
|
1081
|
+
skipLabel: C.RETRO_SKIP_LABEL,
|
|
1082
|
+
deadline: new Date(now.getTime() + C.RETRO_DECISION_DEADLINE_MS),
|
|
1083
|
+
});
|
|
1084
|
+
out.decisionId = decision.id;
|
|
1085
|
+
state.retro.decisions[decision.id] = { projectId: project.id, projectPath: target.path, ticketIds: out.filed.map((t) => t.id) };
|
|
1086
|
+
}
|
|
1087
|
+
catch (err) {
|
|
1088
|
+
// No card, no approval: the tickets must not wait on a question nobody asked.
|
|
1089
|
+
this.logger.warn('Could not ask the owner about the retro gaps; the tickets are cancelled', { error: err instanceof Error ? err.message : String(err) });
|
|
1090
|
+
for (const t of out.filed) {
|
|
1091
|
+
await retroDeps
|
|
1092
|
+
.applyGapDecision(target.path, t.id, false, `the owner could not be asked (${err instanceof Error ? err.message : String(err)})`)
|
|
1093
|
+
.catch(() => 'left');
|
|
1094
|
+
}
|
|
1095
|
+
out.unasked = out.filed.map((t) => t.id);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
await this.saveState();
|
|
1099
|
+
return out;
|
|
1100
|
+
}
|
|
1101
|
+
/**
|
|
1102
|
+
* Tell the lead of the harness project that the owner skipped a gap
|
|
1103
|
+
* ticket someone already started (a `notify` WorkItem: the normal
|
|
1104
|
+
* dispatch path, which also wakes a stopped lead).
|
|
1105
|
+
*
|
|
1106
|
+
* @param projectPath - Harness project root
|
|
1107
|
+
* @param ticketId - The started ticket
|
|
1108
|
+
* @param decisionId - The card
|
|
1109
|
+
*/
|
|
1110
|
+
async tellGapLead(projectPath, ticketId, decisionId) {
|
|
1111
|
+
const wanted = path.resolve(projectPath);
|
|
1112
|
+
const project = (await this.deps.directory.getProjects()).find((p) => !!p.path && path.resolve(p.path) === wanted);
|
|
1113
|
+
if (!project)
|
|
1114
|
+
return;
|
|
1115
|
+
const lead = this.resolveDriver(resolveTicketAutopilotSettings(project.ticketAutopilot), await this.projectTeams(project));
|
|
1116
|
+
if (!lead)
|
|
1117
|
+
return;
|
|
1118
|
+
const wi = createWorkItem({
|
|
1119
|
+
type: 'notify',
|
|
1120
|
+
owner: 'team_lead',
|
|
1121
|
+
target: lead.session,
|
|
1122
|
+
title: `Owner skipped harness gap ${ticketId}`,
|
|
1123
|
+
description: `The owner skipped harness-gap ticket ${ticketId} (decision ${decisionId}), but work on it has already started. Decide whether to stop it (cancel the ticket) or finish it, and note why on the ticket.`,
|
|
1124
|
+
metadata: { projectId: project.id, projectPath: project.path, teamId: lead.teamId, ticketId, requiresVerification: false },
|
|
1125
|
+
});
|
|
1126
|
+
wi.createdAt = this.now().toISOString();
|
|
1127
|
+
wi.targetSource = 'assigned';
|
|
1128
|
+
await this.deps.pool.addToPool(wi);
|
|
1129
|
+
this.logger.info('Told the lead about a skipped gap ticket already in progress', { ticketId, lead: lead.session });
|
|
1130
|
+
}
|
|
1131
|
+
/**
|
|
1132
|
+
* The owner answered a retro-gaps card: Approve releases its tickets
|
|
1133
|
+
* (needs-owner hold removed, `ready`); anything else (Skip, the default at
|
|
1134
|
+
* the deadline, a withdrawn card) cancels those that have not started.
|
|
1135
|
+
*
|
|
1136
|
+
* @param decision - The settled decision
|
|
1137
|
+
* @returns Nothing for an agent (no agent asked it)
|
|
1138
|
+
*/
|
|
1139
|
+
async onRetroDecision(decision) {
|
|
1140
|
+
if (!this.deps.retro)
|
|
1141
|
+
return null;
|
|
1142
|
+
const state = await this.loadState();
|
|
1143
|
+
const entry = state.retro.decisions[decision.id];
|
|
1144
|
+
if (!entry)
|
|
1145
|
+
return null;
|
|
1146
|
+
const approved = (decision.status === 'resolved' || decision.status === 'defaulted') &&
|
|
1147
|
+
decision.options.find((o) => o.key === decision.chosenKey)?.label === TICKET_AUTOPILOT_CONSTANTS.RETRO_APPROVE_LABEL;
|
|
1148
|
+
for (const id of entry.ticketIds) {
|
|
1149
|
+
const note = approved ? `owner approved (decision ${decision.id})` : `owner did not approve (decision ${decision.id}, ${decision.status})`;
|
|
1150
|
+
const outcome = await this.deps.retro
|
|
1151
|
+
.applyGapDecision(entry.projectPath, id, approved, note)
|
|
1152
|
+
.catch((err) => {
|
|
1153
|
+
this.logger.warn('Could not apply the retro decision to a ticket', { id, error: err instanceof Error ? err.message : String(err) });
|
|
1154
|
+
return null;
|
|
1155
|
+
});
|
|
1156
|
+
// Skipped, but someone already works on it: its lead decides what to do.
|
|
1157
|
+
if (!approved && outcome === 'left')
|
|
1158
|
+
await this.tellGapLead(entry.projectPath, id, decision.id).catch(() => undefined);
|
|
1159
|
+
}
|
|
1160
|
+
delete state.retro.decisions[decision.id];
|
|
1161
|
+
await this.saveState();
|
|
1162
|
+
this.logger.info('Retro harness gaps decided', { decisionId: decision.id, approved, tickets: entry.ticketIds });
|
|
1163
|
+
return null;
|
|
1164
|
+
}
|
|
1165
|
+
// ---------------------------------------------------------------------------
|
|
457
1166
|
// Helpers
|
|
458
1167
|
// ---------------------------------------------------------------------------
|
|
459
1168
|
/**
|
|
@@ -480,6 +1189,7 @@ export class TicketAutopilotService {
|
|
|
480
1189
|
pausedForToday: settings.enabled && spent >= budget.tokens,
|
|
481
1190
|
triageInFlight: live,
|
|
482
1191
|
lastTriageAt: ps?.lastTriageAt ? new Date(ps.lastTriageAt).toISOString() : null,
|
|
1192
|
+
retroOn: await this.retroOn(project),
|
|
483
1193
|
};
|
|
484
1194
|
}
|
|
485
1195
|
/**
|
|
@@ -648,6 +1358,11 @@ export class TicketAutopilotService {
|
|
|
648
1358
|
projects: raw.projects && typeof raw.projects === 'object' ? raw.projects : {},
|
|
649
1359
|
questions: { lastSentAt: raw.questions?.lastSentAt, sentKeys: Array.isArray(sentKeys) ? sentKeys : [] },
|
|
650
1360
|
digest: raw.digest && typeof raw.digest === 'object' ? raw.digest : {},
|
|
1361
|
+
retro: {
|
|
1362
|
+
gapDays: raw.retro?.gapDays && typeof raw.retro.gapDays === 'object' ? raw.retro.gapDays : {},
|
|
1363
|
+
gaps: Array.isArray(raw.retro?.gaps) ? raw.retro.gaps : [],
|
|
1364
|
+
decisions: raw.retro?.decisions && typeof raw.retro.decisions === 'object' ? raw.retro.decisions : {},
|
|
1365
|
+
},
|
|
651
1366
|
};
|
|
652
1367
|
return this.state;
|
|
653
1368
|
}
|
|
@@ -663,6 +1378,16 @@ export class TicketAutopilotService {
|
|
|
663
1378
|
}
|
|
664
1379
|
}
|
|
665
1380
|
}
|
|
1381
|
+
/**
|
|
1382
|
+
* Backoff after `failures` failed tries: RETRY_BACKOFF_MIN_MS doubling up to RETRY_BACKOFF_MAX_MS.
|
|
1383
|
+
*
|
|
1384
|
+
* @param failures - Failed tries so far (≥ 1)
|
|
1385
|
+
* @returns Milliseconds
|
|
1386
|
+
*/
|
|
1387
|
+
export function retryBackoffMs(failures) {
|
|
1388
|
+
const C = TICKET_AUTOPILOT_CONSTANTS;
|
|
1389
|
+
return Math.min(C.RETRY_BACKOFF_MAX_MS, C.RETRY_BACKOFF_MIN_MS * 2 ** Math.max(0, failures - 1));
|
|
1390
|
+
}
|
|
666
1391
|
/**
|
|
667
1392
|
* Keep a brief within the WorkItem brief budget.
|
|
668
1393
|
*
|