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,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Experiment Card
|
|
3
|
+
description: Attach an experiment to an optimisation ticket — hypothesis ("change X → metric Y from a to b"), a Search Console or GA4 metric (via seo-ops), an observation window (default 14 days). Crewly captures the baseline when the change ships, measures it when the window ends, labels it worked / didn't / inconclusive, resolves your prediction, writes the wiki experiment log and tells the owner.
|
|
4
|
+
version: 1.1.0
|
|
5
|
+
category: analysis
|
|
6
|
+
skillType: claude-skill
|
|
7
|
+
assignableRoles:
|
|
8
|
+
- marketing
|
|
9
|
+
- content-strategist
|
|
10
|
+
- generalist
|
|
11
|
+
- developer
|
|
12
|
+
- fullstack-dev
|
|
13
|
+
- product-manager
|
|
14
|
+
- team-leader
|
|
15
|
+
- orchestrator
|
|
16
|
+
triggers:
|
|
17
|
+
- experiment
|
|
18
|
+
- measure the impact
|
|
19
|
+
- did it work
|
|
20
|
+
- a/b
|
|
21
|
+
- hypothesis
|
|
22
|
+
tags:
|
|
23
|
+
- experiments
|
|
24
|
+
- seo
|
|
25
|
+
- analytics
|
|
26
|
+
- outcomes
|
|
27
|
+
execution:
|
|
28
|
+
type: script
|
|
29
|
+
script:
|
|
30
|
+
file: execute.sh
|
|
31
|
+
interpreter: bash
|
|
32
|
+
timeoutMs: 180000
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
# Experiment Card
|
|
36
|
+
|
|
37
|
+
A ticket that is meant to *move a number* (rewrite a title, add FAQ schema,
|
|
38
|
+
shorten the inquiry form) should carry an experiment, so we learn whether it
|
|
39
|
+
worked instead of assuming it did. Create the card **before** the change ships;
|
|
40
|
+
Crewly does the rest:
|
|
41
|
+
|
|
42
|
+
1. **Ship** — when the linked ticket reaches `done` (or you run `ship`), the
|
|
43
|
+
windows are fixed and the **baseline** is fetched right away: the
|
|
44
|
+
`windowDays` days that had settled before the ship day. The ship time is
|
|
45
|
+
the ticket's move to `done` in its log. If you link a ticket that is
|
|
46
|
+
already done and its log has no done time, `create` asks for
|
|
47
|
+
`--shipped-at` (when the change went live).
|
|
48
|
+
2. **Wait** — the observation window is the `windowDays` days after the ship
|
|
49
|
+
day. Nothing to do; don't re-check it by hand.
|
|
50
|
+
3. **Measure** — once those days have settled (Search Console +3 days, GA4
|
|
51
|
+
+2), Crewly fetches the result and labels it:
|
|
52
|
+
- **worked** — a real change in the hypothesis's direction (|z| ≥ 1.96);
|
|
53
|
+
- **didn't** — enough data, but no real change (or the wrong way);
|
|
54
|
+
- **inconclusive** — too little data (e.g. fewer than 10 form submissions
|
|
55
|
+
across both windows, fewer than 30 clicks/sessions).
|
|
56
|
+
4. **Learn** — your prediction (recorded at ship with `--confidence`) is
|
|
57
|
+
resolved, the result is appended to the wiki experiment log
|
|
58
|
+
(`llm-curated/experiments/log.md`), the owner gets it, and a project
|
|
59
|
+
ticket gets a log line. `show` has the whole timeline (the run's trace).
|
|
60
|
+
|
|
61
|
+
## Create
|
|
62
|
+
|
|
63
|
+
The metric comes from the seo-ops skill, so you need a seo-ops site config
|
|
64
|
+
(`--config`, absolute path; it names the GSC property / GA4 property and the
|
|
65
|
+
service-account credentials).
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Search Console: organic clicks to one page, on a project ticket
|
|
69
|
+
bash execute.sh create --hypothesis "FAQ schema on the H-1B guide → organic clicks from 120 to 160" \
|
|
70
|
+
--source gsc --measure clicks --page https://visa.careerengine.us/h1b-guide \
|
|
71
|
+
--from 120 --to 160 --config /abs/path/ce.seo-ops.json --project ce-site --ticket CE-31 --confidence 0.6
|
|
72
|
+
|
|
73
|
+
# GA4: inquiry-form submissions (all channels), on a harness ticket
|
|
74
|
+
bash execute.sh create --hypothesis "3-field inquiry form → submissions from 8 to 14 per two weeks" \
|
|
75
|
+
--source ga4 --measure events --event generate_lead --channel all \
|
|
76
|
+
--config /abs/path/ce.seo-ops.json --tkt TKT-212
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- gsc measures: `clicks`, `impressions`, `ctr`, `position` (lower is better;
|
|
80
|
+
direction defaults to `decrease`). Filters: `--page URL`, `--query Q`,
|
|
81
|
+
`--page-match` / `--query-match exact|contains`.
|
|
82
|
+
- ga4 measures: `sessions` (Organic Search unless `--channel all`),
|
|
83
|
+
`events` (`--event NAME`) and `conversions` (GA4 key events; `--event NAME`
|
|
84
|
+
for one of them). Filter: `--page /landing-path` (a full URL is reduced to
|
|
85
|
+
its path; the query string is dropped).
|
|
86
|
+
- `--window-days` 7–90, whole weeks preferred (default 14).
|
|
87
|
+
- One experiment per change: two changes on the same page in one window
|
|
88
|
+
can't be told apart.
|
|
89
|
+
|
|
90
|
+
## Follow it
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
bash execute.sh list --status running
|
|
94
|
+
bash execute.sh show --id EXP-3 # baseline, result, verdict, timeline
|
|
95
|
+
bash execute.sh ship --id EXP-3 # only if it has no ticket, or shipped before the ticket closed
|
|
96
|
+
bash execute.sh measure --id EXP-3 # only after dueAt; normally automatic
|
|
97
|
+
bash execute.sh cancel --id EXP-3 --reason "change reverted"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If a fetch keeps failing (credentials, property access) the owner is told
|
|
101
|
+
once with the error; after 6 failures in a row it retries once a day.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# experiment-card — attach an experiment to an optimisation ticket; Crewly
|
|
4
|
+
# captures the baseline when it ships and measures it when the window ends.
|
|
5
|
+
#
|
|
6
|
+
# Backed by /api/experiments (specs/experiment-cards.md, issue #986).
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# bash execute.sh create --hypothesis "…" --source gsc|ga4 --measure M --config /abs/seo-ops.config.json
|
|
10
|
+
# [--page P] [--page-match exact|contains] [--query Q] [--query-match exact|contains]
|
|
11
|
+
# [--event NAME] [--channel all] [--label "…"] [--title "…"]
|
|
12
|
+
# [--from A] [--to B] [--direction increase|decrease] [--window-days 14]
|
|
13
|
+
# [--confidence 0.6] [--project P --ticket ID | --tkt TKT-12] [--shipped-at ISO]
|
|
14
|
+
# bash execute.sh ship --id EXP-3 [--shipped-at ISO]
|
|
15
|
+
# bash execute.sh show --id EXP-3
|
|
16
|
+
# bash execute.sh list [--status planned|running|done|cancelled] [--ticket ID]
|
|
17
|
+
# bash execute.sh measure --id EXP-3
|
|
18
|
+
# bash execute.sh cancel --id EXP-3 [--reason "…"]
|
|
19
|
+
# bash execute.sh '{"action":"create","hypothesis":"…","metric":{…},"ticket":{…}}'
|
|
20
|
+
# =============================================================================
|
|
21
|
+
set -euo pipefail
|
|
22
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
+
source "${SCRIPT_DIR}/../../_common/lib.sh"
|
|
24
|
+
|
|
25
|
+
print_usage() {
|
|
26
|
+
cat <<'EOF_USAGE'
|
|
27
|
+
Usage:
|
|
28
|
+
bash execute.sh create --hypothesis "change X → metric Y from a to b" --source gsc|ga4 --measure M
|
|
29
|
+
--config /abs/path/seo-ops.config.json [filters] [--from A] [--to B]
|
|
30
|
+
[--window-days 14] [--confidence 0.6] [--project P --ticket ID | --tkt TKT-12]
|
|
31
|
+
[--shipped-at ISO] (required when the ticket is already done but has no recorded done time)
|
|
32
|
+
gsc measures: clicks impressions ctr position (filters: --page URL --query Q, --page-match/--query-match exact|contains)
|
|
33
|
+
ga4 measures: sessions events conversions (filters: --page /path, --event NAME, --channel all)
|
|
34
|
+
bash execute.sh ship --id EXP-3 [--shipped-at ISO] The change is live (automatic when the ticket is done)
|
|
35
|
+
bash execute.sh show --id EXP-3 Card, baseline, result and timeline
|
|
36
|
+
bash execute.sh list [--status S] [--ticket ID]
|
|
37
|
+
bash execute.sh measure --id EXP-3 Measure now (only once it is due)
|
|
38
|
+
bash execute.sh cancel --id EXP-3 [--reason "…"]
|
|
39
|
+
EOF_USAGE
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
ACTION=""; ID=""; JSON_BODY=""
|
|
43
|
+
HYPOTHESIS=""; TITLE=""; SOURCE=""; MEASURE=""; CONFIG=""; PAGE=""; PAGE_MATCH=""; QUERY=""; QUERY_MATCH=""
|
|
44
|
+
EVENT=""; CHANNEL=""; LABEL=""; FROM=""; TO=""; DIRECTION=""; WINDOW=""; CONFIDENCE=""; PROJECT=""; TICKET=""; TKT=""
|
|
45
|
+
SHIPPED_AT=""; STATUS=""; REASON=""
|
|
46
|
+
|
|
47
|
+
if [[ $# -gt 0 && ${1:0:1} == '{' ]]; then
|
|
48
|
+
J=$(read_json_input "$1"); shift
|
|
49
|
+
ACTION=$(printf '%s' "$J" | jq -r '.action // empty')
|
|
50
|
+
ID=$(printf '%s' "$J" | jq -r '.id // empty')
|
|
51
|
+
SHIPPED_AT=$(printf '%s' "$J" | jq -r '.shippedAt // empty')
|
|
52
|
+
STATUS=$(printf '%s' "$J" | jq -r '.status // empty')
|
|
53
|
+
REASON=$(printf '%s' "$J" | jq -r '.reason // empty')
|
|
54
|
+
TICKET=$(printf '%s' "$J" | jq -r 'if (.ticket|type) == "string" then .ticket else empty end')
|
|
55
|
+
JSON_BODY=$(printf '%s' "$J" | jq -c 'del(.action, .id, .status, .reason)')
|
|
56
|
+
fi
|
|
57
|
+
if [[ -z "$ACTION" && $# -gt 0 && ${1:0:1} != '-' ]]; then ACTION="$1"; shift; fi
|
|
58
|
+
|
|
59
|
+
while [[ $# -gt 0 ]]; do
|
|
60
|
+
case "$1" in
|
|
61
|
+
--id) [ $# -ge 2 ] || error_exit "--id requires a value"; ID="$2"; shift 2 ;;
|
|
62
|
+
--hypothesis) [ $# -ge 2 ] || error_exit "--hypothesis requires a value"; HYPOTHESIS="$2"; shift 2 ;;
|
|
63
|
+
--title) [ $# -ge 2 ] || error_exit "--title requires a value"; TITLE="$2"; shift 2 ;;
|
|
64
|
+
--source) [ $# -ge 2 ] || error_exit "--source requires a value"; SOURCE="$2"; shift 2 ;;
|
|
65
|
+
--measure) [ $# -ge 2 ] || error_exit "--measure requires a value"; MEASURE="$2"; shift 2 ;;
|
|
66
|
+
--config) [ $# -ge 2 ] || error_exit "--config requires a value"; CONFIG="$2"; shift 2 ;;
|
|
67
|
+
--page) [ $# -ge 2 ] || error_exit "--page requires a value"; PAGE="$2"; shift 2 ;;
|
|
68
|
+
--page-match) [ $# -ge 2 ] || error_exit "--page-match requires a value"; PAGE_MATCH="$2"; shift 2 ;;
|
|
69
|
+
--query) [ $# -ge 2 ] || error_exit "--query requires a value"; QUERY="$2"; shift 2 ;;
|
|
70
|
+
--query-match) [ $# -ge 2 ] || error_exit "--query-match requires a value"; QUERY_MATCH="$2"; shift 2 ;;
|
|
71
|
+
--event) [ $# -ge 2 ] || error_exit "--event requires a value"; EVENT="$2"; shift 2 ;;
|
|
72
|
+
--channel) [ $# -ge 2 ] || error_exit "--channel requires a value"; CHANNEL="$2"; shift 2 ;;
|
|
73
|
+
--label) [ $# -ge 2 ] || error_exit "--label requires a value"; LABEL="$2"; shift 2 ;;
|
|
74
|
+
--from) [ $# -ge 2 ] || error_exit "--from requires a value"; FROM="$2"; shift 2 ;;
|
|
75
|
+
--to) [ $# -ge 2 ] || error_exit "--to requires a value"; TO="$2"; shift 2 ;;
|
|
76
|
+
--direction) [ $# -ge 2 ] || error_exit "--direction requires a value"; DIRECTION="$2"; shift 2 ;;
|
|
77
|
+
--window-days) [ $# -ge 2 ] || error_exit "--window-days requires a value"; WINDOW="$2"; shift 2 ;;
|
|
78
|
+
--confidence) [ $# -ge 2 ] || error_exit "--confidence requires a value"; CONFIDENCE="$2"; shift 2 ;;
|
|
79
|
+
--project|-p) [ $# -ge 2 ] || error_exit "--project requires a value"; PROJECT="$2"; shift 2 ;;
|
|
80
|
+
--ticket) [ $# -ge 2 ] || error_exit "--ticket requires a value"; TICKET="$2"; shift 2 ;;
|
|
81
|
+
--tkt) [ $# -ge 2 ] || error_exit "--tkt requires a value"; TKT="$2"; shift 2 ;;
|
|
82
|
+
--shipped-at) [ $# -ge 2 ] || error_exit "--shipped-at requires a value"; SHIPPED_AT="$2"; shift 2 ;;
|
|
83
|
+
--status) [ $# -ge 2 ] || error_exit "--status requires a value"; STATUS="$2"; shift 2 ;;
|
|
84
|
+
--reason) [ $# -ge 2 ] || error_exit "--reason requires a value"; REASON="$2"; shift 2 ;;
|
|
85
|
+
--help|-h) print_usage; exit 0 ;;
|
|
86
|
+
*) error_exit "Unknown option: $1" ;;
|
|
87
|
+
esac
|
|
88
|
+
done
|
|
89
|
+
|
|
90
|
+
enc() { jq -rn --arg v "$1" '$v|@uri'; }
|
|
91
|
+
CARD='{id, status, title, hypothesis, metric: (.metric | {source, measure, page, query, event, label} | with_entries(select(.value != null))), windowDays, ticket, shippedAt, dueAt, baseline: (.baseline.total // null), result: (.result.total // null), verdict, verdictReason, lastError, traceId}'
|
|
92
|
+
|
|
93
|
+
case "$ACTION" in
|
|
94
|
+
create)
|
|
95
|
+
if [ -n "$JSON_BODY" ] && [ "$JSON_BODY" != "{}" ]; then
|
|
96
|
+
BODY="$JSON_BODY"
|
|
97
|
+
else
|
|
98
|
+
require_param "hypothesis (--hypothesis)" "$HYPOTHESIS"
|
|
99
|
+
require_param "source (--source gsc|ga4)" "$SOURCE"
|
|
100
|
+
require_param "measure (--measure)" "$MEASURE"
|
|
101
|
+
require_param "config (--config, the seo-ops site config)" "$CONFIG"
|
|
102
|
+
if [ -n "$TICKET" ] && [ -z "$PROJECT" ]; then error_exit "--ticket needs --project (or use --tkt TKT-n for a harness ticket)"; fi
|
|
103
|
+
BODY=$(jq -cn \
|
|
104
|
+
--arg h "$HYPOTHESIS" --arg t "$TITLE" --arg s "$SOURCE" --arg m "$MEASURE" --arg c "$CONFIG" \
|
|
105
|
+
--arg page "$PAGE" --arg pm "$PAGE_MATCH" --arg q "$QUERY" --arg qm "$QUERY_MATCH" --arg ev "$EVENT" \
|
|
106
|
+
--arg ch "$CHANNEL" --arg lb "$LABEL" --arg from "$FROM" --arg to "$TO" --arg dir "$DIRECTION" \
|
|
107
|
+
--arg win "$WINDOW" --arg conf "$CONFIDENCE" --arg proj "$PROJECT" --arg tic "$TICKET" --arg tkt "$TKT" '
|
|
108
|
+
def opt($k; $v): if $v == "" then {} else {($k): $v} end;
|
|
109
|
+
{hypothesis: $h}
|
|
110
|
+
+ opt("title"; $t)
|
|
111
|
+
+ {metric: ({source: $s, measure: $m, config: $c}
|
|
112
|
+
+ opt("page"; $page) + opt("pageMatch"; $pm) + opt("query"; $q) + opt("queryMatch"; $qm)
|
|
113
|
+
+ opt("event"; $ev) + opt("channel"; $ch) + opt("label"; $lb))}
|
|
114
|
+
+ (if $from == "" and $to == "" then {} else {expected: (opt("from"; $from) + opt("to"; $to))} end)
|
|
115
|
+
+ opt("direction"; $dir) + opt("windowDays"; $win) + opt("confidence"; $conf)
|
|
116
|
+
+ (if $tkt != "" then {ticket: {kind: "harness", id: $tkt}}
|
|
117
|
+
elif $tic != "" then {ticket: {kind: "project", project: $proj, id: $tic}}
|
|
118
|
+
else {} end)')
|
|
119
|
+
fi
|
|
120
|
+
if [ -n "$SHIPPED_AT" ]; then BODY=$(printf '%s' "$BODY" | jq -c --arg at "$SHIPPED_AT" '. + {shippedAt: $at}'); fi
|
|
121
|
+
api_call POST "/experiments" "$BODY" | jq "{success, experiment: (.data | ${CARD})}"
|
|
122
|
+
;;
|
|
123
|
+
ship)
|
|
124
|
+
require_param "id (--id EXP-n)" "$ID"
|
|
125
|
+
BODY=$(jq -cn --arg at "$SHIPPED_AT" 'if $at == "" then {} else {shippedAt: $at} end')
|
|
126
|
+
api_call POST "/experiments/$(enc "$ID")/ship" "$BODY" | jq "{success, experiment: (.data | ${CARD})}"
|
|
127
|
+
;;
|
|
128
|
+
show)
|
|
129
|
+
require_param "id (--id EXP-n)" "$ID"
|
|
130
|
+
api_call GET "/experiments/$(enc "$ID")" | jq "{success, experiment: (.data | ${CARD} + {timeline})}"
|
|
131
|
+
;;
|
|
132
|
+
list)
|
|
133
|
+
QS=""
|
|
134
|
+
[ -n "$STATUS" ] && QS="status=$(enc "$STATUS")"
|
|
135
|
+
[ -n "$TICKET" ] && QS="${QS:+$QS&}ticket=$(enc "$TICKET")"
|
|
136
|
+
api_call GET "/experiments${QS:+?$QS}" | jq "{success, experiments: [.data[] | ${CARD}]}"
|
|
137
|
+
;;
|
|
138
|
+
measure)
|
|
139
|
+
require_param "id (--id EXP-n)" "$ID"
|
|
140
|
+
api_call POST "/experiments/$(enc "$ID")/measure" '{}' | jq "{success, experiment: (.data | ${CARD})}"
|
|
141
|
+
;;
|
|
142
|
+
cancel)
|
|
143
|
+
require_param "id (--id EXP-n)" "$ID"
|
|
144
|
+
BODY=$(jq -cn --arg r "$REASON" 'if $r == "" then {} else {reason: $r} end')
|
|
145
|
+
api_call POST "/experiments/$(enc "$ID")/cancel" "$BODY" | jq "{success, experiment: (.data | ${CARD})}"
|
|
146
|
+
;;
|
|
147
|
+
""|help) print_usage; [ -n "$ACTION" ] || exit 1 ;;
|
|
148
|
+
*) error_exit "Unknown action: $ACTION (create, ship, show, list, measure, cancel)" ;;
|
|
149
|
+
esac
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for experiment-card — run with: bash execute.test.sh
|
|
3
|
+
# A python HTTP stub plays the backend; asserts the calls and the output.
|
|
4
|
+
set -u
|
|
5
|
+
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
EXEC="$HERE/execute.sh"
|
|
7
|
+
PASS=0; FAIL=0
|
|
8
|
+
check() {
|
|
9
|
+
local name="$1"; local got="$2"; local want="$3"
|
|
10
|
+
if [ "$got" = "$want" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $name"; echo " want: $want"; echo " got: $got"; fi
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
PORT=18853
|
|
14
|
+
STUB_LOG="$(mktemp)"; export STUB_LOG; export STUB_PORT="$PORT"
|
|
15
|
+
python3 -u <<'PY' >/dev/null 2>&1 &
|
|
16
|
+
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
17
|
+
import json, os
|
|
18
|
+
LOG = os.environ['STUB_LOG']; PORT = int(os.environ['STUB_PORT'])
|
|
19
|
+
E = {'id': 'EXP-1', 'traceId': 'exp:EXP-1', 'status': 'planned', 'title': 'T', 'hypothesis': 'H',
|
|
20
|
+
'metric': {'source': 'gsc', 'measure': 'clicks', 'config': '/c.json', 'page': 'https://x/'}, 'windowDays': 14,
|
|
21
|
+
'baseline': {'total': 100, 'days': [1, 2]}, 'timeline': [{'at': 'a', 'event': 'created'}], 'createdBy': 'ella'}
|
|
22
|
+
class H(BaseHTTPRequestHandler):
|
|
23
|
+
def reply(self, code, obj):
|
|
24
|
+
self.send_response(code); self.send_header('Content-Type', 'application/json'); self.end_headers()
|
|
25
|
+
self.wfile.write(json.dumps(obj).encode())
|
|
26
|
+
def record(self, body=None):
|
|
27
|
+
open(LOG, 'w').write(json.dumps({'method': self.command, 'path': self.path, 'body': body, 'agent': self.headers.get('X-Agent-Session')}))
|
|
28
|
+
def do_GET(self):
|
|
29
|
+
self.record()
|
|
30
|
+
if self.path.startswith('/api/experiments/'):
|
|
31
|
+
return self.reply(200, {'success': True, 'data': E})
|
|
32
|
+
return self.reply(200, {'success': True, 'data': [E, dict(E, id='EXP-2', status='done', verdict='worked')]})
|
|
33
|
+
def do_POST(self):
|
|
34
|
+
n = int(self.headers.get('content-length', '0')); body = json.loads(self.rfile.read(n).decode() or '{}')
|
|
35
|
+
self.record(body)
|
|
36
|
+
if self.path.endswith('/measure'):
|
|
37
|
+
return self.reply(409, {'success': False, 'error': 'EXP-1 is not due until 2026-10-28'})
|
|
38
|
+
return self.reply(200, {'success': True, 'data': E})
|
|
39
|
+
def log_message(self, *a, **k): pass
|
|
40
|
+
HTTPServer(('127.0.0.1', PORT), H).serve_forever()
|
|
41
|
+
PY
|
|
42
|
+
STUB_PID=$!
|
|
43
|
+
disown "$STUB_PID" 2>/dev/null || true
|
|
44
|
+
trap 'kill "$STUB_PID" >/dev/null 2>&1; rm -f "$STUB_LOG"' EXIT
|
|
45
|
+
for i in $(seq 1 30); do curl -s -o /dev/null -m 0.2 "http://127.0.0.1:${PORT}/" 2>/dev/null && break; sleep 0.1; done
|
|
46
|
+
|
|
47
|
+
run() { CREWLY_SESSION_NAME=ella CREWLY_API_URL="http://127.0.0.1:${PORT}" bash "$EXEC" "$@" 2>/dev/null; }
|
|
48
|
+
run_err() { CREWLY_SESSION_NAME=ella CREWLY_API_URL="http://127.0.0.1:${PORT}" bash "$EXEC" "$@" 2>&1 >/dev/null; }
|
|
49
|
+
last() { jq -r "$1" "$STUB_LOG"; }
|
|
50
|
+
|
|
51
|
+
# --- create on a project ticket: metric, expectation, window ---
|
|
52
|
+
OUT=$(run create --hypothesis "FAQ schema → clicks 100 to 140" --source gsc --measure clicks --config /c.json \
|
|
53
|
+
--page https://x/ --from 100 --to 140 --window-days 21 --project ce --ticket T-12)
|
|
54
|
+
check "create: path" "$(last .path)" "/api/experiments"
|
|
55
|
+
check "create: body" "$(last '.body | tostring')" '{"hypothesis":"FAQ schema → clicks 100 to 140","metric":{"source":"gsc","measure":"clicks","config":"/c.json","page":"https://x/"},"expected":{"from":"100","to":"140"},"windowDays":"21","ticket":{"kind":"project","project":"ce","id":"T-12"}}'
|
|
56
|
+
check "create: agent header" "$(last .agent)" "ella"
|
|
57
|
+
check "create: card" "$(printf '%s' "$OUT" | jq -c '.experiment | [.id, .baseline, .metric.page]')" '["EXP-1",100,"https://x/"]'
|
|
58
|
+
|
|
59
|
+
# --- create on a harness ticket with GA4 form events ---
|
|
60
|
+
run create --hypothesis "Shorter form" --source ga4 --measure events --event generate_lead --channel all --config /c.json --tkt TKT-40 >/dev/null
|
|
61
|
+
check "create ga4: body" "$(last '.body | tostring')" '{"hypothesis":"Shorter form","metric":{"source":"ga4","measure":"events","config":"/c.json","event":"generate_lead","channel":"all"},"ticket":{"kind":"harness","id":"TKT-40"}}'
|
|
62
|
+
|
|
63
|
+
# --- create from JSON passes the body through ---
|
|
64
|
+
run '{"action":"create","hypothesis":"J","metric":{"source":"gsc","measure":"ctr","config":"/c.json"}}' >/dev/null
|
|
65
|
+
check "create json: body" "$(last '.body | tostring')" '{"hypothesis":"J","metric":{"source":"gsc","measure":"ctr","config":"/c.json"}}'
|
|
66
|
+
|
|
67
|
+
# --- create on an already-done ticket with an explicit ship time ---
|
|
68
|
+
run create --hypothesis "Late card" --source gsc --measure clicks --config /c.json --project ce --ticket T-9 --shipped-at 2026-10-01T10:00:00Z >/dev/null
|
|
69
|
+
check "create shipped-at: body" "$(last '.body.shippedAt')" "2026-10-01T10:00:00Z"
|
|
70
|
+
run '{"action":"create","hypothesis":"J","metric":{"source":"gsc","measure":"ctr","config":"/c.json"},"shippedAt":"2026-10-01T10:00:00Z"}' >/dev/null
|
|
71
|
+
check "create json shipped-at: body" "$(last '.body.shippedAt')" "2026-10-01T10:00:00Z"
|
|
72
|
+
|
|
73
|
+
# --- missing params / a ticket without its project ---
|
|
74
|
+
check "create: missing" "$(run_err create --hypothesis h --source gsc --measure clicks | grep -c 'config')" "1"
|
|
75
|
+
check "create: ticket w/o project" "$(run_err create --hypothesis h --source gsc --measure clicks --config /c --ticket T-1 | grep -c 'needs --project')" "1"
|
|
76
|
+
|
|
77
|
+
# --- ship / show / list / cancel ---
|
|
78
|
+
run ship --id EXP-1 --shipped-at 2026-10-01T10:00:00Z >/dev/null
|
|
79
|
+
check "ship: path" "$(last .path)" "/api/experiments/EXP-1/ship"
|
|
80
|
+
check "ship: body" "$(last '.body | tostring')" '{"shippedAt":"2026-10-01T10:00:00Z"}'
|
|
81
|
+
OUT=$(run show --id EXP-1)
|
|
82
|
+
check "show: timeline" "$(printf '%s' "$OUT" | jq -c '.experiment.timeline | map(.event)')" '["created"]'
|
|
83
|
+
OUT=$(run list --status done --ticket TKT-40)
|
|
84
|
+
check "list: path" "$(last .path)" "/api/experiments?status=done&ticket=TKT-40"
|
|
85
|
+
check "list: rows" "$(printf '%s' "$OUT" | jq -c '[.experiments[] | [.id, .verdict]]')" '[["EXP-1",null],["EXP-2","worked"]]'
|
|
86
|
+
run cancel --id EXP-1 --reason dup >/dev/null
|
|
87
|
+
check "cancel: body" "$(last '.body | tostring')" '{"reason":"dup"}'
|
|
88
|
+
|
|
89
|
+
# --- measure refused before it is due: the error reaches the agent ---
|
|
90
|
+
check "measure: not due" "$(run_err measure --id EXP-1 | grep -c 'not due')" "1"
|
|
91
|
+
|
|
92
|
+
# --- unknown action / option ---
|
|
93
|
+
check "unknown action" "$(run_err frobnicate | grep -c 'Unknown action')" "1"
|
|
94
|
+
check "unknown option" "$(run_err list --nope | grep -c 'Unknown option')" "1"
|
|
95
|
+
|
|
96
|
+
echo "experiment-card: $PASS passed, $FAIL failed"
|
|
97
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -32,6 +32,9 @@ set -euo pipefail
|
|
|
32
32
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
33
33
|
LOG_DIR="${HOME}/.crewly/logs"
|
|
34
34
|
LOG_FILE="${LOG_DIR}/desktop-app-control.log"
|
|
35
|
+
# Where `scan` looks for installed apps. Overridable so the scan can be
|
|
36
|
+
# exercised against a fixture directory on machines without /Applications.
|
|
37
|
+
APPLICATIONS_DIR="${CREWLY_APPLICATIONS_DIR:-/Applications}"
|
|
35
38
|
|
|
36
39
|
# Ensure log directory exists
|
|
37
40
|
mkdir -p "$LOG_DIR"
|
|
@@ -108,7 +111,7 @@ do_scan() {
|
|
|
108
111
|
}
|
|
109
112
|
|
|
110
113
|
# Scan for Electron apps by checking framework directory
|
|
111
|
-
for app_dir in
|
|
114
|
+
for app_dir in "$APPLICATIONS_DIR"/*.app; do
|
|
112
115
|
[ ! -d "$app_dir" ] && continue
|
|
113
116
|
if [ -d "$app_dir/Contents/Frameworks/Electron Framework.framework" ]; then
|
|
114
117
|
local app_name
|
|
@@ -138,7 +141,7 @@ do_scan() {
|
|
|
138
141
|
local browser port
|
|
139
142
|
while IFS='|' read -r browser port; do
|
|
140
143
|
[ -z "$browser" ] && continue
|
|
141
|
-
if [ -d "
|
|
144
|
+
if [ -d "$APPLICATIONS_DIR/$browser.app" ]; then
|
|
142
145
|
local running="false"
|
|
143
146
|
if pgrep -f "$browser" > /dev/null 2>&1; then
|
|
144
147
|
running="true"
|
|
@@ -5,10 +5,27 @@ set -euo pipefail
|
|
|
5
5
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
6
|
source "${SCRIPT_DIR}/../_common/lib.sh"
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
# CLI flags (--session/--to, --message, --force) are accepted too: the Gemini
|
|
9
|
+
# safe-call guide shows the flag form.
|
|
10
|
+
if [ "${1:-}" != "" ] && [ "${1#--}" != "${1}" ]; then
|
|
11
|
+
FLAG_SESSION=""; FLAG_MESSAGE=""; FLAG_FORCE=""
|
|
12
|
+
while [ $# -gt 0 ]; do
|
|
13
|
+
case "$1" in
|
|
14
|
+
--session|--sessionName|--to) FLAG_SESSION="${2:-}"; shift 2 ;;
|
|
15
|
+
--message) FLAG_MESSAGE="${2:-}"; shift 2 ;;
|
|
16
|
+
--force) FLAG_FORCE="true"; shift ;;
|
|
17
|
+
*) error_exit "Unknown option: $1" ;;
|
|
18
|
+
esac
|
|
19
|
+
done
|
|
20
|
+
INPUT=$(jq -n --arg s "$FLAG_SESSION" --arg m "$FLAG_MESSAGE" --arg f "$FLAG_FORCE" \
|
|
21
|
+
'{sessionName: $s, message: $m} + (if $f == "true" then {force: true} else {} end)')
|
|
22
|
+
else
|
|
23
|
+
INPUT=$(read_json_input "${1:-}")
|
|
24
|
+
fi
|
|
9
25
|
[ -z "$INPUT" ] && error_exit "Usage: execute.sh '{\"sessionName\":\"agent-session\",\"message\":\"hello\"}' or echo '{...}' | execute.sh"
|
|
10
26
|
|
|
11
|
-
|
|
27
|
+
# `to` is accepted as an alias for `sessionName` (older prompt examples used it).
|
|
28
|
+
SESSION_NAME=$(printf '%s' "$INPUT" | jq -r '.sessionName // .to // empty')
|
|
12
29
|
MESSAGE=$(printf '%s' "$INPUT" | jq -r '.message // empty')
|
|
13
30
|
FORCE=$(printf '%s' "$INPUT" | jq -r '.force // empty')
|
|
14
31
|
require_param "sessionName" "$SESSION_NAME"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for the orchestrator send-message skill.
|
|
3
|
+
#
|
|
4
|
+
# Guards the input forms the orchestrator prompt teaches: JSON with
|
|
5
|
+
# `sessionName` (canonical), JSON with `to` (older examples), and the CLI
|
|
6
|
+
# flag form from the Gemini safe-call guide. `curl` is stubbed on PATH, so
|
|
7
|
+
# every case runs offline and records the real request the skill issues.
|
|
8
|
+
set -uo pipefail
|
|
9
|
+
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
PASS=0
|
|
12
|
+
FAIL=0
|
|
13
|
+
|
|
14
|
+
check() {
|
|
15
|
+
local name="$1" needle="$2" haystack="$3"
|
|
16
|
+
if printf '%s' "$haystack" | grep -qF -- "$needle"; then
|
|
17
|
+
PASS=$((PASS + 1)); echo " ✓ ${name}"
|
|
18
|
+
else
|
|
19
|
+
FAIL=$((FAIL + 1)); echo " ✗ ${name}"; echo " expected to contain: ${needle}"; echo " actual: ${haystack}"
|
|
20
|
+
fi
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
STUB_DIR="$(mktemp -d)"
|
|
24
|
+
cat > "$STUB_DIR/curl" << 'STUB_EOF'
|
|
25
|
+
#!/bin/bash
|
|
26
|
+
URL=""; BODY=""
|
|
27
|
+
while [ $# -gt 0 ]; do
|
|
28
|
+
case "$1" in
|
|
29
|
+
-d) BODY="$2"; shift 2 ;;
|
|
30
|
+
-X|-H|-w) shift 2 ;;
|
|
31
|
+
-s) shift ;;
|
|
32
|
+
*) URL="$1"; shift ;;
|
|
33
|
+
esac
|
|
34
|
+
done
|
|
35
|
+
printf '%s %s\n' "$URL" "$(printf '%s' "$BODY" | tr -d '\n ')" >> "$CURL_LOG"
|
|
36
|
+
printf '{"success":true}\n200'
|
|
37
|
+
STUB_EOF
|
|
38
|
+
chmod +x "$STUB_DIR/curl"
|
|
39
|
+
export PATH="$STUB_DIR:$PATH" CREWLY_API_URL="http://stub.invalid" CREWLY_SESSION_NAME="crewly-orc"
|
|
40
|
+
|
|
41
|
+
# Runs the skill; sets OUT (stdout+stderr) and REQ (requests sent).
|
|
42
|
+
run() {
|
|
43
|
+
CURL_LOG="$(mktemp)"; export CURL_LOG
|
|
44
|
+
OUT="$(bash "$SCRIPT_DIR/execute.sh" "$@" </dev/null 2>&1)" || true
|
|
45
|
+
REQ="$(cat "$CURL_LOG")"; rm -f "$CURL_LOG"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
echo "=== orchestrator send-message tests ==="
|
|
49
|
+
|
|
50
|
+
run '{"sessionName":"dev-1","message":"hi"}'
|
|
51
|
+
check "sessionName JSON reaches /deliver for that session" "http://stub.invalid/api/terminal/dev-1/deliver" "$REQ"
|
|
52
|
+
check "readiness-aware delivery by default" '"waitForReady":true' "$REQ"
|
|
53
|
+
|
|
54
|
+
run '{"to":"dev-2","message":"hi"}'
|
|
55
|
+
check "'to' is accepted as an alias for sessionName" "/api/terminal/dev-2/deliver" "$REQ"
|
|
56
|
+
|
|
57
|
+
run --to dev-3 --message "hello there"
|
|
58
|
+
check "--to/--message flags work" "/api/terminal/dev-3/deliver" "$REQ"
|
|
59
|
+
check "flag message is sent" '"message":"hellothere"' "$REQ"
|
|
60
|
+
|
|
61
|
+
run --session dev-4 --message hi --force
|
|
62
|
+
check "--session and --force flags work" "/api/terminal/dev-4/deliver" "$REQ"
|
|
63
|
+
check "--force sends force:true" '"force":true' "$REQ"
|
|
64
|
+
|
|
65
|
+
run '{"message":"no target"}'
|
|
66
|
+
check "missing session is reported" "sessionName" "$OUT"
|
|
67
|
+
# (lib.sh sends a skill-start heartbeat; what must not happen is a delivery.)
|
|
68
|
+
if printf '%s' "$REQ" | grep -q "/deliver"; then
|
|
69
|
+
FAIL=$((FAIL + 1)); echo " ✗ missing session must not deliver anything"
|
|
70
|
+
else
|
|
71
|
+
PASS=$((PASS + 1)); echo " ✓ missing session delivers nothing"
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
run --bogus x
|
|
75
|
+
check "unknown flag is refused" "Unknown option: --bogus" "$OUT"
|
|
76
|
+
|
|
77
|
+
rm -rf "$STUB_DIR"
|
|
78
|
+
echo ""
|
|
79
|
+
echo "=== Results: ${PASS} passed, ${FAIL} failed ==="
|
|
80
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
|
-
"lastUpdated": "2026-
|
|
3
|
+
"lastUpdated": "2026-10-03T01:12:43.309Z",
|
|
4
4
|
"cdnBaseUrl": "https://raw.githubusercontent.com/stevehuang0115/crewly/main",
|
|
5
5
|
"source": "github",
|
|
6
6
|
"items": [
|
|
@@ -1412,7 +1412,7 @@
|
|
|
1412
1412
|
"name": "SEO Ops",
|
|
1413
1413
|
"description": "Search Console-driven SEO operations for any site: query patterns (low-CTR top-3, near-miss 4-20, rising queries, keyword cannibalization), per-URL report cards, pre-publish SEO/AEO checks, a gated programmatic-page queue, and a live-diff gate that stops agents from removing things from live pages. Use when auditing organic search, deciding what to rewrite, or before changing a live page. For writing posts use seo-blog-writer instead.",
|
|
1414
1414
|
"author": "Crewly",
|
|
1415
|
-
"version": "1.
|
|
1415
|
+
"version": "1.2.0",
|
|
1416
1416
|
"category": "development",
|
|
1417
1417
|
"tags": [
|
|
1418
1418
|
"seo",
|
|
@@ -1425,12 +1425,12 @@
|
|
|
1425
1425
|
"downloads": 0,
|
|
1426
1426
|
"rating": 0,
|
|
1427
1427
|
"createdAt": "2026-09-29T01:43:29.904Z",
|
|
1428
|
-
"updatedAt": "2026-
|
|
1428
|
+
"updatedAt": "2026-10-03T01:12:43.309Z",
|
|
1429
1429
|
"source": "config/skills/agent/marketplace/seo-ops",
|
|
1430
1430
|
"assets": {
|
|
1431
1431
|
"archive": "config/skills/agent/marketplace/seo-ops",
|
|
1432
1432
|
"checksum": "",
|
|
1433
|
-
"sizeBytes":
|
|
1433
|
+
"sizeBytes": 149452
|
|
1434
1434
|
},
|
|
1435
1435
|
"metadata": {
|
|
1436
1436
|
"skillType": "claude-skill",
|
|
@@ -1447,7 +1447,9 @@
|
|
|
1447
1447
|
"keyword cannibalization",
|
|
1448
1448
|
"pre-publish seo check",
|
|
1449
1449
|
"programmatic seo pages",
|
|
1450
|
-
"live page diff"
|
|
1450
|
+
"live page diff",
|
|
1451
|
+
"experiment metric",
|
|
1452
|
+
"url inspection"
|
|
1451
1453
|
],
|
|
1452
1454
|
"files": [
|
|
1453
1455
|
"execute.sh",
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Signal Digest
|
|
3
|
+
description: "Daily signal digest for a site you own as team lead: GA4 traffic and key events, Search Console opportunities (low-CTR top-3, near-miss 4-20, rising, cannibalization), the site's inbound mail and broken pages / JS errors, minus what was already tried — turned into 3-5 ranked actions the owner answers Do / Skip on one Slack card. Do opens an experiment ticket."
|
|
4
|
+
version: 1.1.0
|
|
5
|
+
category: productivity
|
|
6
|
+
skillType: claude-skill
|
|
7
|
+
assignableRoles:
|
|
8
|
+
- team-leader
|
|
9
|
+
triggers:
|
|
10
|
+
- daily signal digest
|
|
11
|
+
- daily signals
|
|
12
|
+
- what should we try on the site
|
|
13
|
+
- site opportunities
|
|
14
|
+
tags:
|
|
15
|
+
- seo
|
|
16
|
+
- analytics
|
|
17
|
+
- experiments
|
|
18
|
+
- owner-decisions
|
|
19
|
+
execution:
|
|
20
|
+
type: script
|
|
21
|
+
script:
|
|
22
|
+
file: execute.sh
|
|
23
|
+
interpreter: bash
|
|
24
|
+
timeoutMs: 180000
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# Signal Digest (team lead)
|
|
28
|
+
|
|
29
|
+
One run per site per day (#987, `specs/2026-10-03-signal-digest.md`):
|
|
30
|
+
|
|
31
|
+
1. **collect** — gathers the signals and drafts actions.
|
|
32
|
+
2. **you decide** — keep the 3–5 actions most worth the owner's tap, rewrite them in plain words,
|
|
33
|
+
add your own (e.g. a question the inbox keeps asking → an FAQ section).
|
|
34
|
+
3. **propose** — the owner gets **one card**: each action with **Do** / **Skip**.
|
|
35
|
+
- **Do** opens an experiment ticket in the site's project and, when the action names an
|
|
36
|
+
`experiment` metric, an **experiment card** (#986) linked to it: the baseline is captured when
|
|
37
|
+
the ticket is done and the result is measured after 14 days, automatically. You get a
|
|
38
|
+
`[SIGNAL DIGEST]` message with both ids. Ship it and close the ticket.
|
|
39
|
+
- **Skip** keeps that action off your list for 30 days. A Do keeps it off for 90.
|
|
40
|
+
- Unanswered actions are replaced by your next digest (you may propose them again).
|
|
41
|
+
|
|
42
|
+
## Setup (once per site)
|
|
43
|
+
|
|
44
|
+
The config is the site's **seo-ops** config plus a `signalDigest` section — copy
|
|
45
|
+
`signal-digest.config.example.json`. Google access is seo-ops's service account
|
|
46
|
+
(`SEO_OPS_GOOGLE_CREDENTIALS`, read-only: Search Console user + GA4 Viewer).
|
|
47
|
+
|
|
48
|
+
| `signalDigest` key | Meaning |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `site` | Site name on the card and in the history (default: host of `siteUrl`) |
|
|
51
|
+
| `project` | Project the Do tickets go into (name or id). Without it a Do opens no ticket |
|
|
52
|
+
| `days` | Window, compared with the window before it (default 7) |
|
|
53
|
+
| `ga4.conversionEvents` | Key events that count as conversions (default: all key events) |
|
|
54
|
+
| `inbox.query` / `.account` / `.max` | Gmail search for the site's inbound requests (Google connector) |
|
|
55
|
+
| `errors.checkSitemap` / `.maxUrls` | Fetch up to N sitemap pages and report the ones not answering 200 (default on, 60) |
|
|
56
|
+
| `errors.url` or `errors.command` | JS errors as JSON: `[{"message","count","url"}]` or `{"errors":[…]}` |
|
|
57
|
+
| `experimentLog` | Extra Markdown experiment log; a draft whose query/page it mentions is dropped (experiment cards are always checked) |
|
|
58
|
+
| `thresholds` | `ga4DropPct` (20), `ga4MinPrevSessions` (50), `ga4MinPrevKeyEvents` (5) |
|
|
59
|
+
|
|
60
|
+
Daily run: `bash execute.sh schedule --config <file> [--cron "0 8 * * *"] [--timezone America/New_York]`
|
|
61
|
+
prints the cron task; hand it to the orchestrator to create with `create-cron`.
|
|
62
|
+
|
|
63
|
+
## Commands
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
bash execute.sh collect --config ce.signal.json # JSON: signals, alreadyTried, candidates
|
|
67
|
+
bash execute.sh propose --config ce.signal.json --actions actions.json
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`collect` prints `sources` (ok / not configured / error: why), the signals (`ga4`, `gsc`,
|
|
71
|
+
`inbox`, `errors`), `alreadyTried` (dropped drafts and why: the owner's earlier Do / Skip, an
|
|
72
|
+
experiment card on the same query or page, or the experiment log), `pendingOnOwner` and up to 10
|
|
73
|
+
`candidates`, best first. GA4 respects seo-ops' `ga4HostName`. The sitemap check takes a different
|
|
74
|
+
slice of `errors.maxUrls` pages each day, so the whole sitemap is covered over a few days.
|
|
75
|
+
|
|
76
|
+
`collect` also reports the source statuses to Crewly (`sourceReport` in the output). The owner is
|
|
77
|
+
told **once** when a source starts failing and once when it works again; the digest card shows
|
|
78
|
+
each source's status. So never post about a failing source yourself. Exit `1` when no source
|
|
79
|
+
could be examined: stop there and do not propose from nothing.
|
|
80
|
+
|
|
81
|
+
`--actions` is a JSON array (file or inline) of 3–5 actions, best first:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
[{"key":"gsc:low-ctr:h1b visa fee","source":"gsc",
|
|
85
|
+
"signal":"'h1b visa fee' ranks #2 with 4% CTR on 900 impressions (7 days)",
|
|
86
|
+
"proposal":"Rewrite the title and description of /h1b-fee to answer the fee question",
|
|
87
|
+
"expectedEffect":"CTR 4% → ~16%: about +100 clicks a week",
|
|
88
|
+
"effort":"S — 1 h","metric":"GSC CTR for 'h1b visa fee'",
|
|
89
|
+
"experiment":{"source":"gsc","measure":"ctr","query":"h1b visa fee","page":"https://visa.careerengine.us/h1b-fee"}}]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- `key` is the action's identity across days. Keep the draft's key when you keep its action;
|
|
93
|
+
for your own, use `<source>:<kind>:<subject>`.
|
|
94
|
+
- `source`: `ga4` | `gsc` | `inbox` | `errors` | `other`.
|
|
95
|
+
- Lengths: signal ≤ 400, proposal ≤ 200, expectedEffect ≤ 240, effort ≤ 60 characters.
|
|
96
|
+
- `experiment` (optional, keep the draft's): the seo-ops metric that measures it —
|
|
97
|
+
`source` gsc (`clicks` / `impressions` / `ctr` / `position`, filters `query`, `page`) or
|
|
98
|
+
ga4 (`sessions` / `events`, `event`, `channel`). Leave it out for fixes that move no metric
|
|
99
|
+
(a broken page, a JS error).
|
|
100
|
+
|
|
101
|
+
`propose` answers `{"success":true,"digestId":"SD-4","card":"posted"}`. A `409` lists actions
|
|
102
|
+
the owner already decided — replace them and propose again. One card a day: while today's
|
|
103
|
+
digest (the last 20 hours) still has open actions, proposing the same actions returns it and
|
|
104
|
+
different ones get a `409` — do not post a second card.
|
|
105
|
+
|
|
106
|
+
## Rules
|
|
107
|
+
|
|
108
|
+
- Never propose what `alreadyTried` lists, and never more than 5 actions.
|
|
109
|
+
- Each action states signal → proposal → expected effect → effort, with a number when there is one.
|
|
110
|
+
- This skill only reads Google and Gmail; it never changes the site.
|