crewly 1.20.193 → 1.20.195
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/roles/auditor/prompt.md +2 -2
- package/config/roles/orchestrator/fragments/communication.md +1 -1
- package/config/roles/orchestrator/prompt.md +15 -505
- package/config/skills/agent/computer-use/SKILL.md +6 -0
- package/config/skills/agent/core/experiment-card/SKILL.md +101 -0
- package/config/skills/agent/core/experiment-card/execute.sh +149 -0
- package/config/skills/agent/core/experiment-card/execute.test.sh +97 -0
- package/config/skills/agent/desktop-app-control/execute.sh +5 -2
- package/config/skills/orchestrator/send-message/execute.sh +19 -2
- package/config/skills/orchestrator/send-message/execute.test.sh +80 -0
- package/config/skills/registry.json +7 -5
- 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 +191 -1
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +194 -1
- package/dist/backend/backend/src/constants.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 +6 -0
- 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/experiments/experiments.routes.d.ts +27 -0
- package/dist/backend/backend/src/controllers/experiments/experiments.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/experiments/experiments.routes.js +96 -0
- package/dist/backend/backend/src/controllers/experiments/experiments.routes.js.map +1 -0
- 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/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/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/trace/trace.controller.d.ts +47 -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 +169 -0
- package/dist/backend/backend/src/controllers/trace/trace.controller.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +66 -20
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +14 -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 +6 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/auditor-scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/auditor-scheduler.service.js +3 -0
- package/dist/backend/backend/src/services/agent/auditor-scheduler.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/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/canva/canva-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/canva/canva-token.service.js +5 -0
- package/dist/backend/backend/src/services/canva/canva-token.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat/chat.service.d.ts +78 -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 +210 -26
- 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 +14 -3
- 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 +28 -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/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 +88 -0
- package/dist/backend/backend/src/services/experiments/experiment-verdict.d.ts.map +1 -0
- package/dist/backend/backend/src/services/experiments/experiment-verdict.js +226 -0
- package/dist/backend/backend/src/services/experiments/experiment-verdict.js.map +1 -0
- package/dist/backend/backend/src/services/experiments/experiment.service.d.ts +350 -0
- package/dist/backend/backend/src/services/experiments/experiment.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/experiments/experiment.service.js +908 -0
- package/dist/backend/backend/src/services/experiments/experiment.service.js.map +1 -0
- package/dist/backend/backend/src/services/experiments/experiment.wiring.d.ts +88 -0
- package/dist/backend/backend/src/services/experiments/experiment.wiring.d.ts.map +1 -0
- package/dist/backend/backend/src/services/experiments/experiment.wiring.js +162 -0
- package/dist/backend/backend/src/services/experiments/experiment.wiring.js.map +1 -0
- package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.d.ts +67 -0
- package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.d.ts.map +1 -0
- package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.js +133 -0
- package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.js.map +1 -0
- package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/google-workspace-token.service.js +5 -0
- package/dist/backend/backend/src/services/google/google-workspace-token.service.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/queue-processor.service.d.ts +11 -3
- package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js +24 -7
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js.map +1 -1
- package/dist/backend/backend/src/services/microsoft/microsoft-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/microsoft/microsoft-token.service.js +5 -0
- package/dist/backend/backend/src/services/microsoft/microsoft-token.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/orc/orc-status-router.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orc/orc-status-router.service.js +12 -3
- 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/people/acting-for.service.d.ts +42 -5
- package/dist/backend/backend/src/services/people/acting-for.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/people/acting-for.service.js +80 -5
- package/dist/backend/backend/src/services/people/acting-for.service.js.map +1 -1
- package/dist/backend/backend/src/services/people/grant-sharing.d.ts +5 -4
- package/dist/backend/backend/src/services/people/grant-sharing.d.ts.map +1 -1
- package/dist/backend/backend/src/services/people/grant-sharing.js +12 -4
- package/dist/backend/backend/src/services/people/grant-sharing.js.map +1 -1
- package/dist/backend/backend/src/services/people/people-directory.service.d.ts +71 -13
- package/dist/backend/backend/src/services/people/people-directory.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/people/people-directory.service.js +164 -27
- package/dist/backend/backend/src/services/people/people-directory.service.js.map +1 -1
- 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 +2 -0
- package/dist/backend/backend/src/services/project-tickets/project-ticket.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/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-bot-ids.d.ts +33 -0
- package/dist/backend/backend/src/services/slack/slack-bot-ids.d.ts.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-bot-ids.js +56 -0
- package/dist/backend/backend/src/services/slack/slack-bot-ids.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +14 -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 +30 -10
- 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.service.d.ts +31 -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 +52 -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-context.service.d.ts +195 -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 +432 -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 +42 -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 +146 -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-recorder.d.ts +290 -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 +669 -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 +269 -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 +602 -0
- package/dist/backend/backend/src/services/trace/trace-store.js.map +1 -0
- package/dist/backend/backend/src/services/trace/trace.types.d.ts +118 -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 +85 -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.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/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/workitem-dispatch.subscriber.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js +22 -2
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.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/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/experiment.types.d.ts +155 -0
- package/dist/backend/backend/src/types/experiment.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/experiment.types.js +32 -0
- package/dist/backend/backend/src/types/experiment.types.js.map +1 -0
- package/dist/backend/backend/src/types/messaging.types.d.ts +6 -0
- package/dist/backend/backend/src/types/messaging.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/messaging.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/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 +4 -0
- 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/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/cli/backend/src/constants.d.ts +191 -1
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +194 -1
- 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 +6 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/auditor-scheduler.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/auditor-scheduler.service.js +3 -0
- package/dist/cli/backend/src/services/agent/auditor-scheduler.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-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 +185 -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 +558 -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 +14 -3
- 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 +28 -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/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/queue-processor.service.d.ts +11 -3
- package/dist/cli/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/queue-processor.service.js +24 -7
- package/dist/cli/backend/src/services/messaging/queue-processor.service.js.map +1 -1
- 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/people/acting-for.service.d.ts +42 -5
- package/dist/cli/backend/src/services/people/acting-for.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/people/acting-for.service.js +80 -5
- package/dist/cli/backend/src/services/people/acting-for.service.js.map +1 -1
- package/dist/cli/backend/src/services/people/people-directory.service.d.ts +71 -13
- package/dist/cli/backend/src/services/people/people-directory.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/people/people-directory.service.js +164 -27
- package/dist/cli/backend/src/services/people/people-directory.service.js.map +1 -1
- 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 +2 -0
- package/dist/cli/backend/src/services/project-tickets/project-ticket.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-orchestrator-bridge.d.ts +14 -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 +30 -10
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack.service.d.ts +31 -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 +52 -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 +195 -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 +432 -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 +290 -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 +669 -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 +269 -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 +602 -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 +118 -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 +85 -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/messaging.types.d.ts +6 -0
- package/dist/cli/backend/src/types/messaging.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/messaging.types.js.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 +4 -0
- 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/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/frontend/dist/assets/{index-465d1f8f.js → index-800118ca.js} +274 -274
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signal digest card (#987, specs/2026-10-03-signal-digest.md §3): one
|
|
3
|
+
* Slack message, one section per action with its own Do / Skip buttons.
|
|
4
|
+
* Pure: same digest, same blocks.
|
|
5
|
+
*
|
|
6
|
+
* ```
|
|
7
|
+
* [header] Daily signals · visa.careerengine.us
|
|
8
|
+
* [context] Owen · Fri 10/2 · Do opens an experiment ticket · SD-3
|
|
9
|
+
* [context] Sources: GA4 ✓ · Search Console ✗ HTTP 403 · Inbox — not set up
|
|
10
|
+
* [section] *1. Rewrite the /h1b-fee title*
|
|
11
|
+
* Signal: 'h1b visa fee' ranks #2 with 4% CTR on 900 impressions
|
|
12
|
+
* Expected: about +70 clicks a week · Effort: S — 1 h
|
|
13
|
+
* [actions] [Do] [Skip] (or, once answered: ✔ Do → CE-12)
|
|
14
|
+
* …
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @module services/signal-digest/signal-digest-card
|
|
18
|
+
*/
|
|
19
|
+
import { SIGNAL_DIGEST_CONSTANTS } from '../../constants.js';
|
|
20
|
+
import { isSignalChoice } from '../../types/signal-digest.types.js';
|
|
21
|
+
const WEEKDAY_SHORT = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
22
|
+
/**
|
|
23
|
+
* Escape the characters Slack reserves in mrkdwn.
|
|
24
|
+
*
|
|
25
|
+
* @param text - Plain text
|
|
26
|
+
* @returns Safe mrkdwn
|
|
27
|
+
*/
|
|
28
|
+
export function escapeMrkdwn(text) {
|
|
29
|
+
return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Button value JSON.
|
|
33
|
+
*
|
|
34
|
+
* @param digestId - Digest id
|
|
35
|
+
* @param n - Item number
|
|
36
|
+
* @param choice - do / skip
|
|
37
|
+
* @param instanceId - This instance (Cloud routes the click by it)
|
|
38
|
+
* @returns JSON string
|
|
39
|
+
*/
|
|
40
|
+
export function signalButtonValue(digestId, n, choice, instanceId) {
|
|
41
|
+
const v = { s: digestId, n, o: choice, i: instanceId };
|
|
42
|
+
return JSON.stringify(v);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Parse a digest button value.
|
|
46
|
+
*
|
|
47
|
+
* @param raw - `value` of the clicked button
|
|
48
|
+
* @returns The value, or null when it is not a digest button
|
|
49
|
+
*/
|
|
50
|
+
export function parseSignalButtonValue(raw) {
|
|
51
|
+
if (typeof raw !== 'string' || !raw.startsWith('{'))
|
|
52
|
+
return null;
|
|
53
|
+
try {
|
|
54
|
+
const v = JSON.parse(raw);
|
|
55
|
+
if (typeof v.s !== 'string' || typeof v.n !== 'number' || !Number.isInteger(v.n) || !isSignalChoice(v.o))
|
|
56
|
+
return null;
|
|
57
|
+
return { s: v.s, n: v.n, o: v.o, i: typeof v.i === 'string' ? v.i : '' };
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The line an answered (or expired) action shows instead of its buttons.
|
|
65
|
+
*
|
|
66
|
+
* @param item - Item
|
|
67
|
+
* @returns mrkdwn line, or null while open
|
|
68
|
+
*/
|
|
69
|
+
export function itemOutcomeLine(item) {
|
|
70
|
+
switch (item.status) {
|
|
71
|
+
case 'do':
|
|
72
|
+
if (item.ticketId)
|
|
73
|
+
return `✔ Do → ${escapeMrkdwn(item.ticketId)}${item.experimentId ? ` · ${escapeMrkdwn(item.experimentId)}` : ''}`;
|
|
74
|
+
return `✔ Do — no ticket: ${escapeMrkdwn(item.ticketError ?? 'not created')}`;
|
|
75
|
+
case 'skip':
|
|
76
|
+
return '⤼ Skipped';
|
|
77
|
+
case 'expired':
|
|
78
|
+
return 'No answer — replaced by a newer digest';
|
|
79
|
+
default:
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The card's source line: what the run could and could not examine.
|
|
85
|
+
*
|
|
86
|
+
* @param sources - Statuses
|
|
87
|
+
* @returns mrkdwn line, or null when there are none
|
|
88
|
+
*/
|
|
89
|
+
export function sourcesLine(sources) {
|
|
90
|
+
if (!sources || sources.length === 0)
|
|
91
|
+
return null;
|
|
92
|
+
const parts = sources.map((s) => {
|
|
93
|
+
const label = escapeMrkdwn(SIGNAL_DIGEST_CONSTANTS.SOURCE_LABELS[s.name] ?? s.name);
|
|
94
|
+
if (s.state === 'ok')
|
|
95
|
+
return `${label} ✓`;
|
|
96
|
+
if (s.state === 'not_configured')
|
|
97
|
+
return `${label} — not set up`;
|
|
98
|
+
return `${label} ✗ ${escapeMrkdwn((s.detail ?? 'failed').slice(0, 80))}`;
|
|
99
|
+
});
|
|
100
|
+
return `Sources: ${parts.join(' · ')}`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* `Fri 10/2` for an instant, in the machine's zone.
|
|
104
|
+
*
|
|
105
|
+
* @param iso - Instant
|
|
106
|
+
* @returns Date label
|
|
107
|
+
*/
|
|
108
|
+
function dateLabel(iso) {
|
|
109
|
+
const d = new Date(iso);
|
|
110
|
+
return `${WEEKDAY_SHORT[d.getDay()]} ${d.getMonth() + 1}/${d.getDate()}`;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The card's blocks.
|
|
114
|
+
*
|
|
115
|
+
* @param digest - Digest
|
|
116
|
+
* @param instanceId - This instance id (button values)
|
|
117
|
+
* @param askerName - Team lead's display name, when known
|
|
118
|
+
* @returns Blocks
|
|
119
|
+
*/
|
|
120
|
+
export function renderDigestCard(digest, instanceId, askerName) {
|
|
121
|
+
const blocks = [
|
|
122
|
+
{ type: 'header', text: { type: 'plain_text', text: `Daily signals · ${digest.site}`.slice(0, 150), emoji: true } },
|
|
123
|
+
{
|
|
124
|
+
type: 'context',
|
|
125
|
+
elements: [
|
|
126
|
+
{
|
|
127
|
+
type: 'mrkdwn',
|
|
128
|
+
text: [askerName ? escapeMrkdwn(askerName) : null, dateLabel(digest.createdAt), 'Do opens an experiment ticket · Skip keeps it off the list for 30 days', digest.id]
|
|
129
|
+
.filter(Boolean)
|
|
130
|
+
.join(' · '),
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
const sources = sourcesLine(digest.sources);
|
|
136
|
+
if (sources)
|
|
137
|
+
blocks.push({ type: 'context', elements: [{ type: 'mrkdwn', text: sources }] });
|
|
138
|
+
for (const item of digest.items) {
|
|
139
|
+
blocks.push({
|
|
140
|
+
type: 'section',
|
|
141
|
+
text: {
|
|
142
|
+
type: 'mrkdwn',
|
|
143
|
+
text: [
|
|
144
|
+
`*${item.n}. ${escapeMrkdwn(item.proposal)}*`,
|
|
145
|
+
`Signal: ${escapeMrkdwn(item.signal)}`,
|
|
146
|
+
`Expected: ${escapeMrkdwn(item.expectedEffect)} · Effort: ${escapeMrkdwn(item.effort)}`,
|
|
147
|
+
].join('\n'),
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
const outcome = itemOutcomeLine(item);
|
|
151
|
+
if (outcome) {
|
|
152
|
+
blocks.push({ type: 'context', elements: [{ type: 'mrkdwn', text: outcome }] });
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
blocks.push({
|
|
156
|
+
type: 'actions',
|
|
157
|
+
block_id: `signal:${digest.id}:${item.n}`,
|
|
158
|
+
elements: [
|
|
159
|
+
{
|
|
160
|
+
type: 'button',
|
|
161
|
+
action_id: `${SIGNAL_DIGEST_CONSTANTS.ACTION_PREFIX}${item.n}:do`,
|
|
162
|
+
text: { type: 'plain_text', text: 'Do', emoji: true },
|
|
163
|
+
style: 'primary',
|
|
164
|
+
value: signalButtonValue(digest.id, item.n, 'do', instanceId),
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
type: 'button',
|
|
168
|
+
action_id: `${SIGNAL_DIGEST_CONSTANTS.ACTION_PREFIX}${item.n}:skip`,
|
|
169
|
+
text: { type: 'plain_text', text: 'Skip', emoji: true },
|
|
170
|
+
value: signalButtonValue(digest.id, item.n, 'skip', instanceId),
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
return blocks;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Notification text of the card (shown in the push / when blocks fail).
|
|
179
|
+
*
|
|
180
|
+
* @param digest - Digest
|
|
181
|
+
* @returns Plain text
|
|
182
|
+
*/
|
|
183
|
+
export function digestFallbackText(digest) {
|
|
184
|
+
const open = digest.items.filter((i) => i.status === 'open').length;
|
|
185
|
+
return `Daily signals · ${digest.site}: ${digest.items.length} actions${open < digest.items.length ? ` (${open} waiting)` : ''}`;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=signal-digest-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-digest-card.js","sourceRoot":"","sources":["../../../../../../backend/src/services/signal-digest/signal-digest-card.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signal digest contract (#987, specs/2026-10-03-signal-digest.md §2):
|
|
3
|
+
* validate a team lead's proposal and work out which actions the site's
|
|
4
|
+
* history blocks. Pure.
|
|
5
|
+
*
|
|
6
|
+
* Every rejection says what to fix, because the reader is an agent that will
|
|
7
|
+
* retry with whatever the error tells it.
|
|
8
|
+
*
|
|
9
|
+
* @module services/signal-digest/signal-digest-contract
|
|
10
|
+
*/
|
|
11
|
+
import type { CreateSignalDigestInput, SignalActionInput, SignalDigest, SignalHistoryEntry, SignalSourceStatus } from '../../types/signal-digest.types.js';
|
|
12
|
+
/** A rejected proposal. */
|
|
13
|
+
export declare class SignalDigestError extends Error {
|
|
14
|
+
readonly status: number;
|
|
15
|
+
/**
|
|
16
|
+
* @param status - HTTP status to answer with
|
|
17
|
+
* @param message - What to fix
|
|
18
|
+
*/
|
|
19
|
+
constructor(status: number, message: string);
|
|
20
|
+
}
|
|
21
|
+
/** Appended to contract errors. */
|
|
22
|
+
export declare const SIGNAL_DIGEST_EXAMPLE = "Example item: {\"key\":\"gsc:low-ctr:h1b visa fee\",\"source\":\"gsc\",\"signal\":\"'h1b visa fee' ranks #2 with 4% CTR on 900 impressions (7 d)\",\"proposal\":\"Rewrite the title and description of /h1b-fee to answer the fee question\",\"expectedEffect\":\"CTR 4% \u2192 ~12%: about +70 clicks a week\",\"effort\":\"S \u2014 1 h\",\"metric\":\"GSC clicks for 'h1b visa fee'\"}";
|
|
23
|
+
/** A validated proposal. */
|
|
24
|
+
export interface ValidatedSignalDigest {
|
|
25
|
+
site: string;
|
|
26
|
+
project?: string;
|
|
27
|
+
config?: string;
|
|
28
|
+
items: SignalActionInput[];
|
|
29
|
+
/** Source statuses, when the proposal carries them */
|
|
30
|
+
sources?: SignalSourceStatus[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Normalised identity of an action key (case and spacing do not matter).
|
|
34
|
+
*
|
|
35
|
+
* @param key - Key as sent
|
|
36
|
+
* @returns Comparable key
|
|
37
|
+
*/
|
|
38
|
+
export declare function normalizeKey(key: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Source statuses as `collect` prints them (`{"ga4":"ok","gsc":"error: HTTP 403"}`)
|
|
41
|
+
* or as a list of `{name, state, detail?}`.
|
|
42
|
+
*
|
|
43
|
+
* @param raw - Body field
|
|
44
|
+
* @returns Statuses (sorted by name), or undefined when absent
|
|
45
|
+
* @throws SignalDigestError(400)
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseSourceStatuses(raw: unknown): SignalSourceStatus[] | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Validate a proposal: a site, an optional project, and 3–5 distinct actions,
|
|
50
|
+
* each with key, source, signal, proposal, expected effect and effort.
|
|
51
|
+
*
|
|
52
|
+
* @param input - Request body
|
|
53
|
+
* @returns The proposal
|
|
54
|
+
* @throws SignalDigestError(400) naming what to fix
|
|
55
|
+
*/
|
|
56
|
+
export declare function validateSignalDigest(input: CreateSignalDigestInput): ValidatedSignalDigest;
|
|
57
|
+
/**
|
|
58
|
+
* Validate a site name.
|
|
59
|
+
*
|
|
60
|
+
* @param raw - Body field
|
|
61
|
+
* @returns The site
|
|
62
|
+
* @throws SignalDigestError(400)
|
|
63
|
+
*/
|
|
64
|
+
export declare function validateSite(raw: unknown): string;
|
|
65
|
+
/**
|
|
66
|
+
* The keys a site's history blocks right now, newest first per key:
|
|
67
|
+
* - a Do blocks its key for {@link SIGNAL_DIGEST_CONSTANTS.DO_BLOCK_MS} (it was tried);
|
|
68
|
+
* - a Skip blocks it for {@link SIGNAL_DIGEST_CONSTANTS.SKIP_BLOCK_MS};
|
|
69
|
+
* - an open item blocks it while it is open.
|
|
70
|
+
* Expired items (replaced unanswered) block nothing.
|
|
71
|
+
*
|
|
72
|
+
* @param digests - All stored digests
|
|
73
|
+
* @param site - Site
|
|
74
|
+
* @param now - Clock
|
|
75
|
+
* @returns Blocked entries, one per key
|
|
76
|
+
*/
|
|
77
|
+
export declare function siteHistory(digests: readonly SignalDigest[], site: string, now: Date): SignalHistoryEntry[];
|
|
78
|
+
/**
|
|
79
|
+
* Explain which proposed actions the history blocks.
|
|
80
|
+
*
|
|
81
|
+
* @param items - Proposed actions
|
|
82
|
+
* @param history - {@link siteHistory} of the site
|
|
83
|
+
* @returns One line per blocked action (empty when none)
|
|
84
|
+
*/
|
|
85
|
+
export declare function blockedLines(items: readonly SignalActionInput[], history: readonly SignalHistoryEntry[]): string[];
|
|
86
|
+
//# sourceMappingURL=signal-digest-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-digest-contract.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/signal-digest/signal-digest-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EACV,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EAEZ,kBAAkB,EAGlB,kBAAkB,EACnB,MAAM,oCAAoC,CAAC;AAE5C,2BAA2B;AAC3B,qBAAa,iBAAkB,SAAQ,KAAK;IAMxC,QAAQ,CAAC,MAAM,EAAE,MAAM;IALzB;;;OAGG;gBAEQ,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM;CAKlB;AAED,mCAAmC;AACnC,eAAO,MAAM,qBAAqB,8XACyT,CAAC;AAE5V,4BAA4B;AAC5B,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,sDAAsD;IACtD,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAChC;AAYD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAmFD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,EAAE,GAAG,SAAS,CAelF;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,uBAAuB,GAAG,qBAAqB,CA4C1F;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAKjD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,kBAAkB,EAAE,CA6B3G;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,EAAE,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG,MAAM,EAAE,CAYlH"}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signal digest contract (#987, specs/2026-10-03-signal-digest.md §2):
|
|
3
|
+
* validate a team lead's proposal and work out which actions the site's
|
|
4
|
+
* history blocks. Pure.
|
|
5
|
+
*
|
|
6
|
+
* Every rejection says what to fix, because the reader is an agent that will
|
|
7
|
+
* retry with whatever the error tells it.
|
|
8
|
+
*
|
|
9
|
+
* @module services/signal-digest/signal-digest-contract
|
|
10
|
+
*/
|
|
11
|
+
import { SIGNAL_DIGEST_CONSTANTS } from '../../constants.js';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
/** A rejected proposal. */
|
|
14
|
+
export class SignalDigestError extends Error {
|
|
15
|
+
status;
|
|
16
|
+
/**
|
|
17
|
+
* @param status - HTTP status to answer with
|
|
18
|
+
* @param message - What to fix
|
|
19
|
+
*/
|
|
20
|
+
constructor(status, message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.status = status;
|
|
23
|
+
this.name = 'SignalDigestError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Appended to contract errors. */
|
|
27
|
+
export const SIGNAL_DIGEST_EXAMPLE = 'Example item: {"key":"gsc:low-ctr:h1b visa fee","source":"gsc","signal":"\'h1b visa fee\' ranks #2 with 4% CTR on 900 impressions (7 d)","proposal":"Rewrite the title and description of /h1b-fee to answer the fee question","expectedEffect":"CTR 4% → ~12%: about +70 clicks a week","effort":"S — 1 h","metric":"GSC clicks for \'h1b visa fee\'"}';
|
|
28
|
+
/**
|
|
29
|
+
* Collapse whitespace.
|
|
30
|
+
*
|
|
31
|
+
* @param s - Text
|
|
32
|
+
* @returns One trimmed line
|
|
33
|
+
*/
|
|
34
|
+
function oneLine(s) {
|
|
35
|
+
return s.replace(/\s+/g, ' ').trim();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Normalised identity of an action key (case and spacing do not matter).
|
|
39
|
+
*
|
|
40
|
+
* @param key - Key as sent
|
|
41
|
+
* @returns Comparable key
|
|
42
|
+
*/
|
|
43
|
+
export function normalizeKey(key) {
|
|
44
|
+
return oneLine(key).toLowerCase();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A required one-line text field.
|
|
48
|
+
*
|
|
49
|
+
* @param item - Raw item
|
|
50
|
+
* @param field - Field name
|
|
51
|
+
* @param max - Max characters
|
|
52
|
+
* @param n - Item number (for the error)
|
|
53
|
+
* @returns The text
|
|
54
|
+
* @throws SignalDigestError(400)
|
|
55
|
+
*/
|
|
56
|
+
function textField(item, field, max, n) {
|
|
57
|
+
const raw = item[field];
|
|
58
|
+
const text = typeof raw === 'string' ? oneLine(raw) : '';
|
|
59
|
+
if (!text)
|
|
60
|
+
throw new SignalDigestError(400, `item ${n}: "${field}" is required. ${SIGNAL_DIGEST_EXAMPLE}`);
|
|
61
|
+
if (text.length > max)
|
|
62
|
+
throw new SignalDigestError(400, `item ${n}: "${field}" is too long (max ${max} characters, got ${text.length}). Say it shorter.`);
|
|
63
|
+
return text;
|
|
64
|
+
}
|
|
65
|
+
/** Experiment spec fields kept (strings). */
|
|
66
|
+
const EXPERIMENT_TEXT_FIELDS = ['page', 'query', 'event', 'channel'];
|
|
67
|
+
/**
|
|
68
|
+
* An action's optional experiment spec. Only the shape is checked here; the
|
|
69
|
+
* experiment service validates the measure and filters when a Do creates it.
|
|
70
|
+
*
|
|
71
|
+
* @param raw - `experiment` as sent
|
|
72
|
+
* @param n - Item number (for the error)
|
|
73
|
+
* @returns Spec, or undefined when absent
|
|
74
|
+
* @throws SignalDigestError(400)
|
|
75
|
+
*/
|
|
76
|
+
function experimentSpec(raw, n) {
|
|
77
|
+
if (raw === undefined || raw === null)
|
|
78
|
+
return undefined;
|
|
79
|
+
if (typeof raw !== 'object')
|
|
80
|
+
throw new SignalDigestError(400, `item ${n}: "experiment" must be an object like {"source":"gsc","measure":"clicks","query":"…"}.`);
|
|
81
|
+
const e = raw;
|
|
82
|
+
if (e.source !== 'gsc' && e.source !== 'ga4')
|
|
83
|
+
throw new SignalDigestError(400, `item ${n}: experiment.source must be gsc or ga4.`);
|
|
84
|
+
const measure = typeof e.measure === 'string' ? e.measure.trim() : '';
|
|
85
|
+
if (!measure)
|
|
86
|
+
throw new SignalDigestError(400, `item ${n}: experiment.measure is required (gsc: clicks / impressions / ctr / position; ga4: sessions / events).`);
|
|
87
|
+
const spec = { source: e.source, measure };
|
|
88
|
+
for (const f of EXPERIMENT_TEXT_FIELDS) {
|
|
89
|
+
const v = typeof e[f] === 'string' ? oneLine(e[f]) : '';
|
|
90
|
+
if (v)
|
|
91
|
+
spec[f] = v.slice(0, SIGNAL_DIGEST_CONSTANTS.METRIC_MAX_CHARS);
|
|
92
|
+
}
|
|
93
|
+
return spec;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* One source status from `collect`'s wording: `ok`, `not configured`, or
|
|
97
|
+
* `error: <why>`.
|
|
98
|
+
*
|
|
99
|
+
* @param name - Source name
|
|
100
|
+
* @param raw - Status text, or `{state, detail}`
|
|
101
|
+
* @returns The status
|
|
102
|
+
* @throws SignalDigestError(400)
|
|
103
|
+
*/
|
|
104
|
+
function sourceStatus(name, raw) {
|
|
105
|
+
const C = SIGNAL_DIGEST_CONSTANTS;
|
|
106
|
+
const n = oneLine(name).toLowerCase().slice(0, C.SOURCE_NAME_MAX_CHARS);
|
|
107
|
+
if (!n)
|
|
108
|
+
throw new SignalDigestError(400, 'every source needs a name (ga4, gsc, inbox, errors).');
|
|
109
|
+
let state;
|
|
110
|
+
let detail = '';
|
|
111
|
+
if (raw && typeof raw === 'object') {
|
|
112
|
+
const o = raw;
|
|
113
|
+
const s = typeof o.state === 'string' ? o.state.trim().toLowerCase().replace(/\s+/g, '_') : '';
|
|
114
|
+
if (s !== 'ok' && s !== 'not_configured' && s !== 'error')
|
|
115
|
+
throw new SignalDigestError(400, `source ${n}: "state" must be ok, not_configured or error.`);
|
|
116
|
+
state = s;
|
|
117
|
+
detail = typeof o.detail === 'string' ? oneLine(o.detail) : '';
|
|
118
|
+
}
|
|
119
|
+
else if (typeof raw === 'string') {
|
|
120
|
+
const text = oneLine(raw);
|
|
121
|
+
const lower = text.toLowerCase();
|
|
122
|
+
if (lower === 'ok')
|
|
123
|
+
state = 'ok';
|
|
124
|
+
else if (lower === 'not configured' || lower === 'not_configured')
|
|
125
|
+
state = 'not_configured';
|
|
126
|
+
else if (lower.startsWith('error')) {
|
|
127
|
+
state = 'error';
|
|
128
|
+
detail = text.replace(/^error:?\s*/i, '');
|
|
129
|
+
}
|
|
130
|
+
else
|
|
131
|
+
throw new SignalDigestError(400, `source ${n}: status must be "ok", "not configured" or "error: why" (got "${text.slice(0, 40)}").`);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
throw new SignalDigestError(400, `source ${n}: status must be "ok", "not configured" or "error: why".`);
|
|
135
|
+
}
|
|
136
|
+
return { name: n, state, ...(state === 'error' ? { detail: (detail || 'failed').slice(0, C.SOURCE_DETAIL_MAX_CHARS) } : {}) };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Source statuses as `collect` prints them (`{"ga4":"ok","gsc":"error: HTTP 403"}`)
|
|
140
|
+
* or as a list of `{name, state, detail?}`.
|
|
141
|
+
*
|
|
142
|
+
* @param raw - Body field
|
|
143
|
+
* @returns Statuses (sorted by name), or undefined when absent
|
|
144
|
+
* @throws SignalDigestError(400)
|
|
145
|
+
*/
|
|
146
|
+
export function parseSourceStatuses(raw) {
|
|
147
|
+
if (raw === undefined || raw === null)
|
|
148
|
+
return undefined;
|
|
149
|
+
const entries = Array.isArray(raw)
|
|
150
|
+
? raw.map((x) => [typeof x?.name === 'string' ? x.name : '', x])
|
|
151
|
+
: typeof raw === 'object'
|
|
152
|
+
? Object.entries(raw)
|
|
153
|
+
: [];
|
|
154
|
+
if (!Array.isArray(raw) && typeof raw !== 'object')
|
|
155
|
+
throw new SignalDigestError(400, '"sources" must be an object like {"ga4":"ok","gsc":"error: why"}.');
|
|
156
|
+
if (entries.length > SIGNAL_DIGEST_CONSTANTS.MAX_SOURCES)
|
|
157
|
+
throw new SignalDigestError(400, `"sources" lists too many sources (max ${SIGNAL_DIGEST_CONSTANTS.MAX_SOURCES}).`);
|
|
158
|
+
const out = new Map();
|
|
159
|
+
for (const [name, value] of entries) {
|
|
160
|
+
const st = sourceStatus(name, value);
|
|
161
|
+
out.set(st.name, st);
|
|
162
|
+
}
|
|
163
|
+
return [...out.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Validate a proposal: a site, an optional project, and 3–5 distinct actions,
|
|
167
|
+
* each with key, source, signal, proposal, expected effect and effort.
|
|
168
|
+
*
|
|
169
|
+
* @param input - Request body
|
|
170
|
+
* @returns The proposal
|
|
171
|
+
* @throws SignalDigestError(400) naming what to fix
|
|
172
|
+
*/
|
|
173
|
+
export function validateSignalDigest(input) {
|
|
174
|
+
const site = typeof input.site === 'string' ? oneLine(input.site) : '';
|
|
175
|
+
if (!site)
|
|
176
|
+
throw new SignalDigestError(400, '"site" is required (e.g. "visa.careerengine.us").');
|
|
177
|
+
if (site.length > SIGNAL_DIGEST_CONSTANTS.SITE_MAX_CHARS)
|
|
178
|
+
throw new SignalDigestError(400, `"site" is too long (max ${SIGNAL_DIGEST_CONSTANTS.SITE_MAX_CHARS} characters).`);
|
|
179
|
+
const project = typeof input.project === 'string' && oneLine(input.project) ? oneLine(input.project) : undefined;
|
|
180
|
+
const config = typeof input.config === 'string' && input.config.trim() ? input.config.trim() : undefined;
|
|
181
|
+
if (config && !path.isAbsolute(config))
|
|
182
|
+
throw new SignalDigestError(400, '"config" must be the absolute path of the seo-ops site config.');
|
|
183
|
+
const raw = input.items;
|
|
184
|
+
const { MIN_ITEMS, MAX_ITEMS } = SIGNAL_DIGEST_CONSTANTS;
|
|
185
|
+
if (!Array.isArray(raw) || raw.length < MIN_ITEMS || raw.length > MAX_ITEMS) {
|
|
186
|
+
const got = Array.isArray(raw) ? raw.length : 0;
|
|
187
|
+
throw new SignalDigestError(400, `give ${MIN_ITEMS}–${MAX_ITEMS} actions (got ${got}): pick the ones worth the owner's tap, ranked best first. ${SIGNAL_DIGEST_EXAMPLE}`);
|
|
188
|
+
}
|
|
189
|
+
const seen = new Set();
|
|
190
|
+
const items = raw.map((value, i) => {
|
|
191
|
+
const n = i + 1;
|
|
192
|
+
if (!value || typeof value !== 'object')
|
|
193
|
+
throw new SignalDigestError(400, `item ${n} must be an object. ${SIGNAL_DIGEST_EXAMPLE}`);
|
|
194
|
+
const item = value;
|
|
195
|
+
const key = textField(item, 'key', SIGNAL_DIGEST_CONSTANTS.KEY_MAX_CHARS, n);
|
|
196
|
+
const source = typeof item.source === 'string' ? item.source.trim().toLowerCase() : '';
|
|
197
|
+
if (!SIGNAL_DIGEST_CONSTANTS.SOURCES.includes(source)) {
|
|
198
|
+
throw new SignalDigestError(400, `item ${n}: "source" must be one of ${SIGNAL_DIGEST_CONSTANTS.SOURCES.join(', ')}.`);
|
|
199
|
+
}
|
|
200
|
+
const norm = normalizeKey(key);
|
|
201
|
+
if (seen.has(norm))
|
|
202
|
+
throw new SignalDigestError(400, `item ${n}: key "${key}" is used twice; each action needs its own key.`);
|
|
203
|
+
seen.add(norm);
|
|
204
|
+
const metricRaw = typeof item.metric === 'string' ? oneLine(item.metric) : '';
|
|
205
|
+
if (metricRaw.length > SIGNAL_DIGEST_CONSTANTS.METRIC_MAX_CHARS) {
|
|
206
|
+
throw new SignalDigestError(400, `item ${n}: "metric" is too long (max ${SIGNAL_DIGEST_CONSTANTS.METRIC_MAX_CHARS} characters).`);
|
|
207
|
+
}
|
|
208
|
+
const experiment = experimentSpec(item.experiment, n);
|
|
209
|
+
return {
|
|
210
|
+
key,
|
|
211
|
+
source: source,
|
|
212
|
+
signal: textField(item, 'signal', SIGNAL_DIGEST_CONSTANTS.SIGNAL_MAX_CHARS, n),
|
|
213
|
+
proposal: textField(item, 'proposal', SIGNAL_DIGEST_CONSTANTS.PROPOSAL_MAX_CHARS, n),
|
|
214
|
+
expectedEffect: textField(item, 'expectedEffect', SIGNAL_DIGEST_CONSTANTS.EXPECTED_MAX_CHARS, n),
|
|
215
|
+
effort: textField(item, 'effort', SIGNAL_DIGEST_CONSTANTS.EFFORT_MAX_CHARS, n),
|
|
216
|
+
...(metricRaw ? { metric: metricRaw } : {}),
|
|
217
|
+
...(experiment ? { experiment } : {}),
|
|
218
|
+
};
|
|
219
|
+
});
|
|
220
|
+
const sources = parseSourceStatuses(input.sources);
|
|
221
|
+
return { site, ...(project ? { project } : {}), ...(config ? { config } : {}), items, ...(sources ? { sources } : {}) };
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Validate a site name.
|
|
225
|
+
*
|
|
226
|
+
* @param raw - Body field
|
|
227
|
+
* @returns The site
|
|
228
|
+
* @throws SignalDigestError(400)
|
|
229
|
+
*/
|
|
230
|
+
export function validateSite(raw) {
|
|
231
|
+
const site = typeof raw === 'string' ? oneLine(raw) : '';
|
|
232
|
+
if (!site)
|
|
233
|
+
throw new SignalDigestError(400, '"site" is required (e.g. "visa.careerengine.us").');
|
|
234
|
+
if (site.length > SIGNAL_DIGEST_CONSTANTS.SITE_MAX_CHARS)
|
|
235
|
+
throw new SignalDigestError(400, `"site" is too long (max ${SIGNAL_DIGEST_CONSTANTS.SITE_MAX_CHARS} characters).`);
|
|
236
|
+
return site;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* The keys a site's history blocks right now, newest first per key:
|
|
240
|
+
* - a Do blocks its key for {@link SIGNAL_DIGEST_CONSTANTS.DO_BLOCK_MS} (it was tried);
|
|
241
|
+
* - a Skip blocks it for {@link SIGNAL_DIGEST_CONSTANTS.SKIP_BLOCK_MS};
|
|
242
|
+
* - an open item blocks it while it is open.
|
|
243
|
+
* Expired items (replaced unanswered) block nothing.
|
|
244
|
+
*
|
|
245
|
+
* @param digests - All stored digests
|
|
246
|
+
* @param site - Site
|
|
247
|
+
* @param now - Clock
|
|
248
|
+
* @returns Blocked entries, one per key
|
|
249
|
+
*/
|
|
250
|
+
export function siteHistory(digests, site, now) {
|
|
251
|
+
const want = site.trim().toLowerCase();
|
|
252
|
+
const byKey = new Map();
|
|
253
|
+
const ordered = [...digests].filter((d) => d.site.trim().toLowerCase() === want).sort((a, b) => Date.parse(b.createdAt) - Date.parse(a.createdAt));
|
|
254
|
+
for (const d of ordered) {
|
|
255
|
+
for (const item of d.items) {
|
|
256
|
+
const norm = normalizeKey(item.key);
|
|
257
|
+
if (byKey.has(norm))
|
|
258
|
+
continue;
|
|
259
|
+
if (item.status === 'open') {
|
|
260
|
+
byKey.set(norm, { key: item.key, status: 'open', at: d.createdAt, proposal: item.proposal, digestId: d.id });
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (item.status !== 'do' && item.status !== 'skip')
|
|
264
|
+
continue;
|
|
265
|
+
const at = item.answeredAt ?? d.updatedAt;
|
|
266
|
+
const span = item.status === 'do' ? SIGNAL_DIGEST_CONSTANTS.DO_BLOCK_MS : SIGNAL_DIGEST_CONSTANTS.SKIP_BLOCK_MS;
|
|
267
|
+
const until = Date.parse(at) + span;
|
|
268
|
+
if (until <= now.getTime())
|
|
269
|
+
continue;
|
|
270
|
+
byKey.set(norm, {
|
|
271
|
+
key: item.key,
|
|
272
|
+
status: item.status,
|
|
273
|
+
at,
|
|
274
|
+
proposal: item.proposal,
|
|
275
|
+
digestId: d.id,
|
|
276
|
+
...(item.ticketId ? { ticketId: item.ticketId } : {}),
|
|
277
|
+
blockedUntil: new Date(until).toISOString(),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return [...byKey.values()];
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Explain which proposed actions the history blocks.
|
|
285
|
+
*
|
|
286
|
+
* @param items - Proposed actions
|
|
287
|
+
* @param history - {@link siteHistory} of the site
|
|
288
|
+
* @returns One line per blocked action (empty when none)
|
|
289
|
+
*/
|
|
290
|
+
export function blockedLines(items, history) {
|
|
291
|
+
const byKey = new Map(history.map((h) => [normalizeKey(h.key), h]));
|
|
292
|
+
const lines = [];
|
|
293
|
+
for (const item of items) {
|
|
294
|
+
const h = byKey.get(normalizeKey(item.key));
|
|
295
|
+
if (!h)
|
|
296
|
+
continue;
|
|
297
|
+
const when = h.at.slice(0, 10);
|
|
298
|
+
if (h.status === 'do')
|
|
299
|
+
lines.push(`"${item.key}": the owner chose Do on ${when} (${h.digestId}${h.ticketId ? `, ${h.ticketId}` : ''}) — it is being tried`);
|
|
300
|
+
else if (h.status === 'skip')
|
|
301
|
+
lines.push(`"${item.key}": the owner skipped it on ${when} (${h.digestId}); not before ${h.blockedUntil?.slice(0, 10)}`);
|
|
302
|
+
else
|
|
303
|
+
lines.push(`"${item.key}": still waiting on the owner in ${h.digestId}`);
|
|
304
|
+
}
|
|
305
|
+
return lines;
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=signal-digest-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-digest-contract.js","sourceRoot":"","sources":["../../../../../../backend/src/services/signal-digest/signal-digest-contract.ts"],"names":[],"mappings":"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"}
|