@cohortapp/agent-sdk 2.17.0 → 2.18.4
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/.claude/settings.json +18 -0
- package/.env.example +18 -5
- package/README.md +1 -0
- package/bin/maestro.mjs +62 -0
- package/docs/guides/billing-console-keys.md +60 -0
- package/docs/guides/front-door-session.md +54 -9
- package/docs/guides/mac-mini.md +20 -25
- package/docs/guides/setup-wizard.md +1 -1
- package/docs/runbooks/fleet-rollout.md +156 -0
- package/docs/runbooks/mac-mini-bootstrap.md +12 -14
- package/lib/action-executor.js +19 -3
- package/lib/budget-guard.mjs +279 -3
- package/lib/channels/base-adapter.mjs +3 -1
- package/lib/channels/contract.mjs +2 -1
- package/lib/channels/inbox-item.mjs +8 -0
- package/lib/claude-bin.mjs +5 -6
- package/lib/cli/doctor-checks.mjs +141 -10
- package/lib/cli/global-setup-extras.mjs +5 -1
- package/lib/cli/inbox.mjs +100 -15
- package/lib/cli/seat-auth.mjs +463 -0
- package/lib/cli/session.mjs +80 -12
- package/lib/collective/capture.mjs +8 -6
- package/lib/collective/global-config.mjs +63 -1
- package/lib/collective/presence.mjs +142 -5
- package/lib/comms/send-gate.mjs +559 -1
- package/lib/diagnostics/alerts.mjs +49 -0
- package/lib/diagnostics/cadence-output-freshness.mjs +288 -0
- package/lib/engine/agents/definitions.mjs +343 -0
- package/lib/engine/agents/persist.mjs +275 -0
- package/lib/engine/agents/runtime.mjs +748 -0
- package/lib/engine/agents/usage.mjs +95 -0
- package/lib/engine/auth-status.mjs +139 -0
- package/lib/engine/budget.mjs +194 -0
- package/lib/engine/cli.mjs +1204 -0
- package/lib/engine/commands/index.mjs +269 -0
- package/lib/engine/context/budget.mjs +219 -0
- package/lib/engine/context/cache.mjs +125 -0
- package/lib/engine/context/child-env.mjs +215 -0
- package/lib/engine/context/compaction.mjs +342 -0
- package/lib/engine/context/images.mjs +90 -0
- package/lib/engine/context/instructions.mjs +327 -0
- package/lib/engine/context/lazy-instructions.mjs +169 -0
- package/lib/engine/context/manager.mjs +182 -0
- package/lib/engine/context/real-path.mjs +91 -0
- package/lib/engine/context/secret-values.mjs +163 -0
- package/lib/engine/context/settings.mjs +274 -0
- package/lib/engine/context/stream-input.mjs +159 -0
- package/lib/engine/guard.mjs +152 -0
- package/lib/engine/hooks.mjs +713 -0
- package/lib/engine/loop.mjs +560 -0
- package/lib/engine/mcp/client.mjs +254 -0
- package/lib/engine/mcp/config.mjs +301 -0
- package/lib/engine/mcp/http.mjs +201 -0
- package/lib/engine/mcp/index.mjs +146 -0
- package/lib/engine/mcp/jsonrpc.mjs +147 -0
- package/lib/engine/mcp/naming.mjs +66 -0
- package/lib/engine/mcp/resources.mjs +89 -0
- package/lib/engine/mcp/results.mjs +133 -0
- package/lib/engine/mcp/stdio.mjs +137 -0
- package/lib/engine/mcp/supervisor.mjs +116 -0
- package/lib/engine/messages.mjs +104 -0
- package/lib/engine/output/json.mjs +164 -0
- package/lib/engine/output/stream-json.mjs +266 -0
- package/lib/engine/permissions.mjs +845 -0
- package/lib/engine/process-identity.mjs +164 -0
- package/lib/engine/process-tree.mjs +551 -0
- package/lib/engine/prompt.mjs +60 -0
- package/lib/engine/session/store.mjs +299 -0
- package/lib/engine/session-runtime/args.mjs +97 -0
- package/lib/engine/session-runtime/host.mjs +143 -0
- package/lib/engine/session-runtime/inbox.mjs +122 -0
- package/lib/engine/session-runtime/notifications.mjs +129 -0
- package/lib/engine/session-runtime/registry.mjs +328 -0
- package/lib/engine/session-runtime/runner.mjs +344 -0
- package/lib/engine/session-runtime/socket.mjs +212 -0
- package/lib/engine/session-runtime/wakeup.mjs +115 -0
- package/lib/engine/skills/index.mjs +321 -0
- package/lib/engine/tools/bash-background.mjs +533 -0
- package/lib/engine/tools/bash.mjs +216 -0
- package/lib/engine/tools/edit.mjs +97 -0
- package/lib/engine/tools/glob.mjs +81 -0
- package/lib/engine/tools/grep.mjs +224 -0
- package/lib/engine/tools/index.mjs +84 -0
- package/lib/engine/tools/list-agents.mjs +32 -0
- package/lib/engine/tools/ls.mjs +127 -0
- package/lib/engine/tools/monitor.mjs +82 -0
- package/lib/engine/tools/notebook-edit.mjs +218 -0
- package/lib/engine/tools/read.mjs +103 -0
- package/lib/engine/tools/schedule-wakeup.mjs +45 -0
- package/lib/engine/tools/schema.mjs +144 -0
- package/lib/engine/tools/send-message.mjs +77 -0
- package/lib/engine/tools/session.mjs +70 -0
- package/lib/engine/tools/todo.mjs +144 -0
- package/lib/engine/tools/toolsearch.mjs +217 -0
- package/lib/engine/tools/walk.mjs +193 -0
- package/lib/engine/tools/web-switch.mjs +31 -0
- package/lib/engine/tools/webfetch-html.mjs +387 -0
- package/lib/engine/tools/webfetch-net.mjs +340 -0
- package/lib/engine/tools/webfetch.mjs +198 -0
- package/lib/engine/tools/websearch.mjs +91 -0
- package/lib/engine/tools/workflow.mjs +95 -0
- package/lib/engine/tools/write.mjs +76 -0
- package/lib/engine/tui/line-editor.mjs +137 -0
- package/lib/engine/tui/render.mjs +86 -0
- package/lib/engine/tui/tui.mjs +274 -0
- package/lib/engine/wire/anthropic-messages.mjs +263 -0
- package/lib/engine/wire/effort.mjs +36 -0
- package/lib/engine/wire/errors.mjs +496 -0
- package/lib/engine/wire/http.mjs +441 -0
- package/lib/engine/wire/index.mjs +76 -0
- package/lib/engine/wire/openai-chat.mjs +332 -0
- package/lib/engine/wire/prompt-cache.mjs +79 -0
- package/lib/engine/wire/search.mjs +140 -0
- package/lib/engine/wire/sse.mjs +114 -0
- package/lib/engine/wire/stall.mjs +349 -0
- package/lib/engine/wire/token-provider.mjs +175 -0
- package/lib/engine/wire/usage.mjs +192 -0
- package/lib/engine/workflow/host.mjs +524 -0
- package/lib/engine/workflow/journal.mjs +188 -0
- package/lib/engine/workflow/json-schema.mjs +171 -0
- package/lib/engine/workflow/meta.mjs +329 -0
- package/lib/engine/workflow/notifications.mjs +52 -0
- package/lib/engine/workflow/runtime.mjs +447 -0
- package/lib/engine/workflow/sandbox.mjs +534 -0
- package/lib/engine/workflow/worker.mjs +141 -0
- package/lib/engine/workflow/worktree.mjs +74 -0
- package/lib/execution/disposition.mjs +1 -1
- package/lib/execution/intake.mjs +10 -0
- package/lib/execution/surface-policy.mjs +15 -0
- package/lib/learning/curator.mjs +8 -6
- package/lib/learning/reflect.mjs +8 -6
- package/lib/model-router/catalog/cohort.yaml +137 -0
- package/lib/model-router/catalog.mjs +118 -1
- package/lib/model-router/failover.mjs +67 -16
- package/lib/model-router/llm-task.mjs +39 -3
- package/lib/model-router/resolve.mjs +89 -3
- package/lib/model-router/spawn.mjs +46 -47
- package/lib/model-router/taxonomy.mjs +126 -4
- package/lib/org/cost-sync.mjs +141 -11
- package/lib/org/inbound/broadcast.mjs +289 -0
- package/lib/org/inbound/collective.mjs +375 -0
- package/lib/org/inbound/directedness.mjs +96 -8
- package/lib/org/inbound/facts.mjs +78 -2
- package/lib/org/inbound/project.mjs +22 -0
- package/lib/org/inbound/surfaces.mjs +14 -0
- package/lib/org/llm-token.mjs +879 -0
- package/lib/org/mesh.mjs +61 -0
- package/lib/org/messaging.mjs +3 -1
- package/lib/org/protocol.checksum +1 -1
- package/lib/org/protocol.mjs +15 -0
- package/lib/org/quota.mjs +520 -0
- package/lib/org/tool-surface.mjs +104 -16
- package/lib/org/ui-parity.mjs +16 -1
- package/lib/org/work-ledger.mjs +37 -6
- package/lib/rate-guard.mjs +114 -1
- package/lib/resource-governor.mjs +41 -6
- package/lib/runtime/adapter.mjs +823 -0
- package/lib/runtime/child-env.mjs +191 -0
- package/lib/runtime/legacy-shell-guard.mjs +97 -0
- package/lib/runtime/seat-engine.mjs +162 -0
- package/lib/session/ask-ledger.mjs +271 -0
- package/lib/session/current-work.mjs +676 -0
- package/lib/session/feed-core.mjs +40 -3
- package/lib/session/launch-args.mjs +56 -4
- package/lib/session/status-summary.mjs +26 -9
- package/lib/session/upgrade-notice.mjs +42 -0
- package/lib/setup/claude-probe.mjs +117 -13
- package/lib/setup/enrich.mjs +13 -10
- package/lib/setup/sections/model.mjs +39 -13
- package/lib/telemetry/collect.mjs +208 -9
- package/lib/upgrade/ignored-drift.mjs +105 -0
- package/lib/voice/post-call-brief.mjs +30 -17
- package/package.json +13 -3
- package/plugins/maestro-skills/skills/board-work.md +5 -0
- package/plugins/maestro-skills/skills/inbound-triage.md +56 -15
- package/plugins/maestro-skills/skills/main-session.md +18 -7
- package/scripts/ci/check-tarball-fidelity.mjs +126 -2
- package/scripts/ci/run-tests.mjs +47 -19
- package/scripts/cohort-llm/api-key-helper.mjs +92 -0
- package/scripts/collective/hook-runner.mjs +29 -2
- package/scripts/continuous-monitor.sh +13 -0
- package/scripts/cost/track-claude-usage.mjs +15 -0
- package/scripts/daemon/agent-daemon.mjs +408 -20
- package/scripts/daemon/assurance.mjs +48 -12
- package/scripts/daemon/cadence-consumer.mjs +218 -68
- package/scripts/daemon/cadence-handlers.mjs +73 -4
- package/scripts/daemon/classifier.mjs +75 -26
- package/scripts/daemon/context-compiler.mjs +51 -37
- package/scripts/daemon/deliver.mjs +30 -1
- package/scripts/daemon/dispatcher.mjs +595 -149
- package/scripts/daemon/health.mjs +14 -1
- package/scripts/daemon/maestro-daemon.mjs +11 -0
- package/scripts/daemon/prompt-builder.mjs +24 -0
- package/scripts/daemon/responder.mjs +246 -79
- package/scripts/daemon/sdk-version.mjs +98 -16
- package/scripts/eval/probe-gateway.mjs +635 -0
- package/scripts/eval/replay/extract.mjs +270 -0
- package/scripts/eval/replay/grade.mjs +260 -0
- package/scripts/eval/replay/lib/config.mjs +50 -0
- package/scripts/eval/replay/lib/effects.mjs +65 -0
- package/scripts/eval/replay/lib/fixture.mjs +188 -0
- package/scripts/eval/replay/lib/judge.mjs +72 -0
- package/scripts/eval/replay/lib/redact.mjs +136 -0
- package/scripts/eval/replay/lib/sandbox.mjs +170 -0
- package/scripts/eval/replay/lib/schema-check.mjs +63 -0
- package/scripts/eval/replay/lib/transcript.mjs +76 -0
- package/scripts/eval/replay/mcp-replay-stub.mjs +101 -0
- package/scripts/eval/replay/report.mjs +185 -0
- package/scripts/eval/replay/run.mjs +404 -0
- package/scripts/fleet/rollout.mjs +1094 -0
- package/scripts/hooks/pre-send-audit.sh +36 -245
- package/scripts/hooks/pre-write-yaml-validate.mjs +275 -0
- package/scripts/hooks/validate-state-yaml.sh +190 -0
- package/scripts/huddle/huddle-llm.mjs +361 -0
- package/scripts/huddle/huddle-server.mjs +46 -121
- package/scripts/local-triggers/autoupdate.sh +448 -78
- package/scripts/local-triggers/run-trigger.sh +13 -0
- package/scripts/maintenance/pin-integrity.mjs +364 -0
- package/scripts/poll-slack-events.sh +41 -9
- package/scripts/poller/slack-socket-mode.mjs +28 -3
- package/scripts/session/supervisor.mjs +80 -13
- package/scripts/spawn-session.sh +13 -0
- package/bin/maestro.test.mjs +0 -1574
- package/lib/action-executor.test.mjs +0 -871
- package/lib/archetype.test.mjs +0 -132
- package/lib/assurance/plan-note.test.mjs +0 -234
- package/lib/assurance/room-budget.test.mjs +0 -486
- package/lib/assurance/tier.test.mjs +0 -174
- package/lib/autonomy.test.mjs +0 -66
- package/lib/backlog.test.mjs +0 -302
- package/lib/backup/policy.test.mjs +0 -305
- package/lib/budget-escalate.test.mjs +0 -232
- package/lib/budget-guard.envelope.test.mjs +0 -476
- package/lib/budget-guard.test.mjs +0 -427
- package/lib/cadence-bus-requeue.test.mjs +0 -83
- package/lib/cadence-bus-schedule.test.mjs +0 -194
- package/lib/cadence-bus.test.mjs +0 -720
- package/lib/cadences.test.mjs +0 -230
- package/lib/capability/inventory.test.mjs +0 -232
- package/lib/capability.test.mjs +0 -78
- package/lib/channels/base-adapter.test.mjs +0 -590
- package/lib/channels/channels.test.mjs +0 -371
- package/lib/channels/contract.test.mjs +0 -162
- package/lib/channels/inbox-item.test.mjs +0 -368
- package/lib/channels/orgmail/adapter.test.mjs +0 -448
- package/lib/channels/pairing.test.mjs +0 -270
- package/lib/channels/repeat-suppressor.test.mjs +0 -134
- package/lib/channels/slack-adapter.test.mjs +0 -212
- package/lib/channels/telegram-adapter.test.mjs +0 -306
- package/lib/channels/voice/adapter.test.mjs +0 -278
- package/lib/channels/whatsapp/adapter-baileys.test.mjs +0 -359
- package/lib/channels/whatsapp/baileys-typing.test.mjs +0 -154
- package/lib/charter.test.mjs +0 -89
- package/lib/claude-bin.test.mjs +0 -131
- package/lib/cli/board.test.mjs +0 -227
- package/lib/cli/design.test.mjs +0 -270
- package/lib/cli/doctor-checks.test.mjs +0 -336
- package/lib/cli/global-setup-extras.test.mjs +0 -462
- package/lib/cli/inbox.test.mjs +0 -230
- package/lib/cli/session-ack.test.mjs +0 -63
- package/lib/cli/session.test.mjs +0 -613
- package/lib/collective/capture.test.mjs +0 -121
- package/lib/collective/cards.test.mjs +0 -114
- package/lib/collective/config.test.mjs +0 -123
- package/lib/collective/global-config.test.mjs +0 -220
- package/lib/collective/global-skills.test.mjs +0 -126
- package/lib/collective/presence.test.mjs +0 -95
- package/lib/collective/recall.test.mjs +0 -116
- package/lib/collective/vendor-skills.test.mjs +0 -306
- package/lib/comms/send-gate.test.mjs +0 -770
- package/lib/comms.test.mjs +0 -41
- package/lib/context/budget.test.mjs +0 -252
- package/lib/context/history-scope.test.mjs +0 -79
- package/lib/cost/ledger-row.test.mjs +0 -183
- package/lib/design/design-md.test.mjs +0 -318
- package/lib/design/fixtures/DESIGN.golden.md +0 -238
- package/lib/design/fixtures/PRODUCT.golden.md +0 -67
- package/lib/design/fixtures/foundation.json +0 -133
- package/lib/design/refresh-gate.test.mjs +0 -144
- package/lib/design/write.test.mjs +0 -241
- package/lib/diagnostics/alerts.test.mjs +0 -318
- package/lib/diagnostics/backup-freshness.test.mjs +0 -185
- package/lib/diagnostics/counters.test.mjs +0 -206
- package/lib/diagnostics/events.test.mjs +0 -290
- package/lib/diagnostics/otel.test.mjs +0 -196
- package/lib/diagnostics/trace.test.mjs +0 -251
- package/lib/env-compat.test.mjs +0 -104
- package/lib/execution/disposition.test.mjs +0 -553
- package/lib/execution/drive.test.mjs +0 -270
- package/lib/execution/effects.test.mjs +0 -344
- package/lib/execution/intake.test.mjs +0 -389
- package/lib/execution/journal.test.mjs +0 -261
- package/lib/execution/match.test.mjs +0 -235
- package/lib/execution/pipeline.test.mjs +0 -392
- package/lib/execution/route.test.mjs +0 -186
- package/lib/execution/surface-policy.test.mjs +0 -162
- package/lib/fs-atomic.test.mjs +0 -72
- package/lib/fs-ownership.test.mjs +0 -158
- package/lib/goals/admission.test.mjs +0 -164
- package/lib/goals/classify.test.mjs +0 -167
- package/lib/goals/collaborate.test.mjs +0 -336
- package/lib/goals/gaps.test.mjs +0 -284
- package/lib/goals/loop.test.mjs +0 -845
- package/lib/hooks/bus.test.mjs +0 -387
- package/lib/identity/persona.test.mjs +0 -142
- package/lib/kpi-sensors.test.mjs +0 -278
- package/lib/kpi.test.mjs +0 -244
- package/lib/learning/config.test.mjs +0 -75
- package/lib/learning/counters.test.mjs +0 -69
- package/lib/learning/curator-consolidate.test.mjs +0 -238
- package/lib/learning/curator.test.mjs +0 -106
- package/lib/learning/reflect.test.mjs +0 -0
- package/lib/learning/session-index.test.mjs +0 -125
- package/lib/learning/skill-writer.test.mjs +0 -210
- package/lib/mandate/audit.test.mjs +0 -195
- package/lib/mandate/contract.test.mjs +0 -185
- package/lib/mandate/derive.test.mjs +0 -274
- package/lib/mandate/model.test.mjs +0 -164
- package/lib/mandate/refresh.test.mjs +0 -389
- package/lib/mcp/server.test.mjs +0 -426
- package/lib/model-router/auth-profiles.test.mjs +0 -580
- package/lib/model-router/catalog.test.mjs +0 -385
- package/lib/model-router/economics.test.mjs +0 -438
- package/lib/model-router/failover.test.mjs +0 -439
- package/lib/model-router/health.test.mjs +0 -338
- package/lib/model-router/integration-coverage.test.mjs +0 -831
- package/lib/model-router/integration.test.mjs +0 -564
- package/lib/model-router/ledger.test.mjs +0 -415
- package/lib/model-router/llm-task.test.mjs +0 -392
- package/lib/model-router/org-credentials.test.mjs +0 -265
- package/lib/model-router/pricing-refresh.test.mjs +0 -286
- package/lib/model-router/reconcile.test.mjs +0 -316
- package/lib/model-router/repair.test.mjs +0 -180
- package/lib/model-router/spawn.test.mjs +0 -446
- package/lib/model-router/taxonomy.test.mjs +0 -410
- package/lib/model-router.test.mjs +0 -1207
- package/lib/org/activity.test.mjs +0 -134
- package/lib/org/approvals.test.mjs +0 -216
- package/lib/org/awareness.test.mjs +0 -159
- package/lib/org/board-mine-cache.test.mjs +0 -53
- package/lib/org/board.test.mjs +0 -187
- package/lib/org/bootstrap-context.test.mjs +0 -153
- package/lib/org/client.test.mjs +0 -1206
- package/lib/org/cohort-client.test.mjs +0 -126
- package/lib/org/cost-sync.test.mjs +0 -153
- package/lib/org/doctor.test.mjs +0 -346
- package/lib/org/engagement-ledger.test.mjs +0 -112
- package/lib/org/engagement.test.mjs +0 -739
- package/lib/org/handoff.test.mjs +0 -269
- package/lib/org/inbound/directedness.test.mjs +0 -668
- package/lib/org/inbound/facts.test.mjs +0 -471
- package/lib/org/inbound/hydrate.test.mjs +0 -908
- package/lib/org/inbound/index.test.mjs +0 -429
- package/lib/org/inbound/project.test.mjs +0 -287
- package/lib/org/integration-tools.test.mjs +0 -160
- package/lib/org/keys.test.mjs +0 -92
- package/lib/org/knowledge.test.mjs +0 -326
- package/lib/org/leases.test.mjs +0 -235
- package/lib/org/mesh-directives.test.mjs +0 -110
- package/lib/org/mesh-integration.test.mjs +0 -127
- package/lib/org/mesh.test.mjs +0 -400
- package/lib/org/messaging.test.mjs +0 -471
- package/lib/org/param-contract.test.mjs +0 -477
- package/lib/org/policy.test.mjs +0 -237
- package/lib/org/protocol.checksum.test.mjs +0 -90
- package/lib/org/protocol.test.mjs +0 -323
- package/lib/org/push.test.mjs +0 -792
- package/lib/org/registry.test.mjs +0 -100
- package/lib/org/resource-tools.test.mjs +0 -361
- package/lib/org/tool-access.test.mjs +0 -144
- package/lib/org/tool-surface-integration.test.mjs +0 -120
- package/lib/org/tool-surface.test.mjs +0 -1268
- package/lib/org/typing.test.mjs +0 -291
- package/lib/org/ui-parity.test.mjs +0 -560
- package/lib/org/verify.test.mjs +0 -194
- package/lib/org/work-ledger.test.mjs +0 -273
- package/lib/plan/adoption-e2e.test.mjs +0 -366
- package/lib/plan/budget-enforcement.test.mjs +0 -400
- package/lib/plan/compile.test.mjs +0 -382
- package/lib/plan/emit.test.mjs +0 -269
- package/lib/plan/explain.test.mjs +0 -188
- package/lib/prompts/parallelism.test.mjs +0 -177
- package/lib/rag/rag.test.mjs +0 -505
- package/lib/rate-guard.test.mjs +0 -272
- package/lib/reactive-gate.test.mjs +0 -57
- package/lib/render.test.mjs +0 -68
- package/lib/resource-governor.test.mjs +0 -488
- package/lib/scheduling/dynamic-jobs.test.mjs +0 -344
- package/lib/scheduling/jitter.test.mjs +0 -140
- package/lib/secrets/broker.test.mjs +0 -280
- package/lib/secrets/providers.test.mjs +0 -274
- package/lib/security/audit-engine.test.mjs +0 -424
- package/lib/security/coerce-args.test.mjs +0 -281
- package/lib/security/dangerous-tools.test.mjs +0 -68
- package/lib/security/external-content.test.mjs +0 -84
- package/lib/security/redact.test.mjs +0 -441
- package/lib/security/secret-equal.test.mjs +0 -55
- package/lib/session/config.test.mjs +0 -92
- package/lib/session/feed-core.test.mjs +0 -198
- package/lib/session/first-run.test.mjs +0 -121
- package/lib/session/frontdoor.test.mjs +0 -205
- package/lib/session/handoffs.test.mjs +0 -183
- package/lib/session/identity.test.mjs +0 -180
- package/lib/session/inbox-claims.test.mjs +0 -286
- package/lib/session/launch-args.test.mjs +0 -157
- package/lib/session/liveness.test.mjs +0 -100
- package/lib/session/status-summary.test.mjs +0 -118
- package/lib/session-permissions.test.mjs +0 -120
- package/lib/setup/claude-probe.test.mjs +0 -187
- package/lib/setup/completeness.test.mjs +0 -110
- package/lib/setup/context-pack.test.mjs +0 -89
- package/lib/setup/enrich.test.mjs +0 -115
- package/lib/setup/enroll-from-cohort.test.mjs +0 -300
- package/lib/setup/integration.test.mjs +0 -162
- package/lib/setup/io.test.mjs +0 -77
- package/lib/setup/runner.test.mjs +0 -132
- package/lib/setup/sections/identity.test.mjs +0 -234
- package/lib/setup/sections/inventory.test.mjs +0 -198
- package/lib/setup/sections/learning.test.mjs +0 -81
- package/lib/setup/sections/mandate.test.mjs +0 -388
- package/lib/setup/sections/messaging.test.mjs +0 -127
- package/lib/setup/sections/model.test.mjs +0 -240
- package/lib/setup/sections/org.test.mjs +0 -346
- package/lib/setup/sections/orgmail.test.mjs +0 -118
- package/lib/setup/sections/recovery.test.mjs +0 -98
- package/lib/setup/sections/subagents.test.mjs +0 -429
- package/lib/setup/sections/verify.test.mjs +0 -175
- package/lib/setup/sot.test.mjs +0 -81
- package/lib/setup/state.test.mjs +0 -115
- package/lib/singleton.test.mjs +0 -151
- package/lib/subagents/cli.test.mjs +0 -389
- package/lib/subagents/client.test.mjs +0 -309
- package/lib/subagents/gap.test.mjs +0 -234
- package/lib/subagents/lock.test.mjs +0 -248
- package/lib/subagents/manifest.test.mjs +0 -175
- package/lib/subagents/refs.test.mjs +0 -204
- package/lib/subagents/resolve.test.mjs +0 -422
- package/lib/subagents/schema.test.mjs +0 -328
- package/lib/telemetry/alerts.test.mjs +0 -109
- package/lib/telemetry/collect.test.mjs +0 -1274
- package/lib/tool-definitions-integration.test.mjs +0 -83
- package/lib/tool-definitions.test.mjs +0 -437
- package/lib/upgrade/global-refresh.test.mjs +0 -65
- package/lib/upgrade/launchd-reconcile.test.mjs +0 -272
- package/lib/upgrade/post-steps.test.mjs +0 -200
- package/lib/upgrade/verify.test.mjs +0 -164
- package/lib/util/fetch-timeout.test.mjs +0 -202
- package/lib/util/reconnect.test.mjs +0 -369
- package/lib/util/unhandled.test.mjs +0 -216
- package/lib/voice/outbound.test.mjs +0 -69
- package/lib/voice/session-rotation.test.mjs +0 -114
- package/lib/voice/stt.test.mjs +0 -226
- package/lib/voice/voice.test.mjs +0 -990
- package/scripts/cadence/enqueue-cadence-tick.test.mjs +0 -187
- package/scripts/ci/check-docs-accuracy.test.mjs +0 -409
- package/scripts/ci/check-durable-write-seam.test.mjs +0 -90
- package/scripts/ci/check-no-build-artifacts.test.mjs +0 -71
- package/scripts/ci/check-no-residual-identity.test.mjs +0 -202
- package/scripts/ci/check-skill-packs.test.mjs +0 -495
- package/scripts/ci/check-subagent-frontmatter.test.mjs +0 -124
- package/scripts/ci/check.test.mjs +0 -194
- package/scripts/ci/conformance-org-api.test.mjs +0 -425
- package/scripts/cloud-relay/voice/relay-identity.test.mjs +0 -96
- package/scripts/collective/hook-runner.test.mjs +0 -173
- package/scripts/cost/fleet-digest.test.mjs +0 -207
- package/scripts/cost/track-claude-usage-pricing.test.mjs +0 -183
- package/scripts/cost/track-claude-usage.test.mjs +0 -148
- package/scripts/daemon/agent-daemon-board-mine.test.mjs +0 -96
- package/scripts/daemon/agent-daemon-design.test.mjs +0 -238
- package/scripts/daemon/agent-daemon-frontdoor.test.mjs +0 -60
- package/scripts/daemon/agent-daemon.test.mjs +0 -995
- package/scripts/daemon/assurance-e2e.test.mjs +0 -613
- package/scripts/daemon/assurance.test.mjs +0 -1791
- package/scripts/daemon/board-mirror.test.mjs +0 -165
- package/scripts/daemon/cadence-consumer-frontdoor.test.mjs +0 -393
- package/scripts/daemon/cadence-consumer-governance.test.mjs +0 -276
- package/scripts/daemon/cadence-consumer.test.mjs +0 -776
- package/scripts/daemon/cadence-handlers.test.mjs +0 -837
- package/scripts/daemon/classifier-identity.test.mjs +0 -137
- package/scripts/daemon/classifier.test.mjs +0 -266
- package/scripts/daemon/classify-kind.test.mjs +0 -40
- package/scripts/daemon/context-compiler.test.mjs +0 -406
- package/scripts/daemon/deliver.test.mjs +0 -564
- package/scripts/daemon/dispatcher-cooldown.test.mjs +0 -122
- package/scripts/daemon/dispatcher-governance.test.mjs +0 -1013
- package/scripts/daemon/dispatcher-resume.test.mjs +0 -166
- package/scripts/daemon/dispatcher-session-continuity.test.mjs +0 -365
- package/scripts/daemon/execution-ladder.test.mjs +0 -470
- package/scripts/daemon/goal-steward-cadence.test.mjs +0 -312
- package/scripts/daemon/inbox-deferral-session.test.mjs +0 -49
- package/scripts/daemon/inbox-deferral.test.mjs +0 -336
- package/scripts/daemon/inbox-wake.test.mjs +0 -199
- package/scripts/daemon/integration.test.mjs +0 -149
- package/scripts/daemon/lib/self-echo.test.mjs +0 -153
- package/scripts/daemon/lib/session-router.test.mjs +0 -554
- package/scripts/daemon/prompt-builder-preamble.test.mjs +0 -210
- package/scripts/daemon/prompt-builder.test.mjs +0 -556
- package/scripts/daemon/responder-cost.test.mjs +0 -68
- package/scripts/daemon/responder-history.test.mjs +0 -221
- package/scripts/daemon/sdk-version.test.mjs +0 -31
- package/scripts/daemon/session-lock.test.mjs +0 -252
- package/scripts/daemon/session-outcomes.test.mjs +0 -533
- package/scripts/daemon/typing-registry.test.mjs +0 -102
- package/scripts/hooks/pre-send-audit.test.mjs +0 -354
- package/scripts/huddle/huddle-prompt.test.mjs +0 -176
- package/scripts/local-triggers/autoupdate.test.mjs +0 -518
- package/scripts/local-triggers/generate-plists.test.mjs +0 -456
- package/scripts/media-generation/brand-clause.test.mjs +0 -135
- package/scripts/org/send-orgmail.first-contact.test.mjs +0 -102
- package/scripts/poller/inbox-privilege-injection.test.mjs +0 -167
- package/scripts/poller/inbox-scan-poller.test.mjs +0 -295
- package/scripts/poller/lib/cloud-relay-dedup.test.mjs +0 -133
- package/scripts/poller/slack-socket-mode.test.mjs +0 -805
- package/scripts/poller-launchd/install.test.mjs +0 -243
- package/scripts/restore-from-backup.test.mjs +0 -181
- package/scripts/session/feed.test.mjs +0 -196
- package/scripts/session/supervisor-sh.test.mjs +0 -218
- package/scripts/session/supervisor.test.mjs +0 -482
- package/scripts/setup/configure-macos.test.mjs +0 -306
- package/scripts/setup/gen-subagent-manifest.test.mjs +0 -124
- package/scripts/setup/generate-agent-package-json.test.mjs +0 -143
- package/scripts/setup/generate-capability.test.mjs +0 -134
- package/scripts/setup/init-agent.test.mjs +0 -370
- package/scripts/setup/init-skill-marketplace.test.mjs +0 -193
- package/scripts/vendor/sync-skill-packs.test.mjs +0 -103
- package/scripts/watchdog/memory-watchdog.test.mjs +0 -64
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/session/ask-ledger.mjs — the ask ledger, owned by the lane that ACCEPTS
|
|
3
|
+
* the ask rather than by the lane that dispatches it.
|
|
4
|
+
*
|
|
5
|
+
* ── THE THIRTEEN-DAY BLACKOUT THIS EXISTS FOR ────────────────────────────────
|
|
6
|
+
*
|
|
7
|
+
* Every automatic board row for an inbound ask was written from ONE place:
|
|
8
|
+
* `scripts/daemon/agent-daemon.mjs#answerItem`, which calls `trackWorkStep` at
|
|
9
|
+
* accepted / working / done / failed. `answerItem` is reachable only from
|
|
10
|
+
* `pollService`, and on 2026-09-08 `de35690` put a gate in front of
|
|
11
|
+
* `pollService`:
|
|
12
|
+
*
|
|
13
|
+
* const fd = _frontDoorGate.check(svc.name);
|
|
14
|
+
* if (!fd.dispatch) return 0; // ← the live session owns intake
|
|
15
|
+
*
|
|
16
|
+
* That gate is correct — two lanes answering the same room in the seat's voice
|
|
17
|
+
* is the failure it was written for. But the ledger rode along inside the lane
|
|
18
|
+
* it switched off. From the moment a seat's front-door session came up, the
|
|
19
|
+
* daemon stopped dispatching, `answerItem` stopped running, and with it every
|
|
20
|
+
* `accepted`, every `working`, every `done` and every channel tag. The last
|
|
21
|
+
* automatic row in the org's ledger is 2026-09-10; the last `item.tagged` event
|
|
22
|
+
* is the same day. Boards kept moving the whole time (295 `item.moved`, 8457
|
|
23
|
+
* `item.commented`) because the SESSION works boards through its tools — so
|
|
24
|
+
* nothing looked broken. The ask path was simply gone.
|
|
25
|
+
*
|
|
26
|
+
* The session lane had the capability all along: `maestro board track <id>
|
|
27
|
+
* --stage accepted` exists, and `plugins/maestro-skills/skills/inbound-triage.md`
|
|
28
|
+
* tells the session to run it. Thirteen days and several thousand tool calls
|
|
29
|
+
* produced zero rows. That is the whole lesson, and hq's own
|
|
30
|
+
* `llm-responder/responder.ts` had already written it down:
|
|
31
|
+
*
|
|
32
|
+
* "the failure it exists for is an agent that goes quiet, and an agent that
|
|
33
|
+
* has gone quiet is exactly the one that will not remember to file a task
|
|
34
|
+
* about it."
|
|
35
|
+
*
|
|
36
|
+
* ── THE RULE THIS MODULE ENFORCES ────────────────────────────────────────────
|
|
37
|
+
*
|
|
38
|
+
* A lane that ACCEPTS an ask owns its ledger, and the acceptance is what writes
|
|
39
|
+
* it — not a later dispatch step that some future gate can stand down. The two
|
|
40
|
+
* lanes now write from their two acceptance points:
|
|
41
|
+
*
|
|
42
|
+
* daemon lane `answerItem` (unchanged — it IS its own acceptance)
|
|
43
|
+
* session lane `maestro inbox claim` (this module, via lib/cli/inbox.mjs)
|
|
44
|
+
* `… reply | done | defer`
|
|
45
|
+
*
|
|
46
|
+
* Both reach the SAME `lib/org/work-ledger.mjs#recordWorkStep`, which reaches
|
|
47
|
+
* the same `board.track` wire method and the same `hq/src/server/work/
|
|
48
|
+
* threshold.ts` gate. There is still exactly one implementation of "does this
|
|
49
|
+
* ask deserve a row"; this adds a second CALLER, not a second answer. A future
|
|
50
|
+
* step-back in either lane cannot silence the ledger, because it can only stand
|
|
51
|
+
* down a lane that is no longer accepting anything.
|
|
52
|
+
*
|
|
53
|
+
* ── WHY THE STAGES ARE WHAT THEY ARE ─────────────────────────────────────────
|
|
54
|
+
*
|
|
55
|
+
* `deferred` means "this could not be answered inside the turn". At claim time
|
|
56
|
+
* nobody knows that yet, and claiming is not evidence of it — the session
|
|
57
|
+
* claims a one-line question and a week of work identically. So the session
|
|
58
|
+
* lane reports `deferred:false` and lets the server's gate judge from the text,
|
|
59
|
+
* which is the same verdict the daemon's quick-reply path gets. A chatty claim
|
|
60
|
+
* is refused `answerable-in-turn` and mints nothing; a work ask is tracked
|
|
61
|
+
* `asks-for-work`. Neither lane decides; the shared gate does.
|
|
62
|
+
*
|
|
63
|
+
* `claim` chains `accepted` → `working` for the reason the daemon does: `running`
|
|
64
|
+
* is the only column hq's "On now" banner reads, and a row parked in `triage` is
|
|
65
|
+
* a row that surface will never show. A session claim IS the assertion that the
|
|
66
|
+
* seat is on it now — that is what the `.dispatched` marker and the 20-minute
|
|
67
|
+
* reopen sweep already mean.
|
|
68
|
+
*
|
|
69
|
+
* A REPLY closes the row, because in this lane the reply is the delivery. `done`
|
|
70
|
+
* after a reply would say the same thing twice, so it is skipped; `done` without
|
|
71
|
+
* one closes the row itself. `defer` parks it in `blocked` with the reason,
|
|
72
|
+
* which is the truthful reading of an item nobody is working right now.
|
|
73
|
+
*
|
|
74
|
+
* ── WHAT THIS LANE STILL DOES NOT COVER ─────────────────────────────────────
|
|
75
|
+
*
|
|
76
|
+
* Stated here rather than discovered later, and pinned by the negative cases in
|
|
77
|
+
* `lib/cli/inbox-ledger-wiring.test.mjs`:
|
|
78
|
+
*
|
|
79
|
+
* 1. A WORK-SHAPED BROADCAST OPENS NO ROW. `lib/org/work-ledger.mjs` reports
|
|
80
|
+
* `directed` from `priority_signals.mentions_agent`, which
|
|
81
|
+
* `lib/org/inbound/project.mjs` sets only for the reasons `mention`,
|
|
82
|
+
* `named`, `dm` and `direct`. A post addressed to a room — "Everyone, please
|
|
83
|
+
* review the binder by Friday" — carries none of them, and hq's gate refuses
|
|
84
|
+
* it `not-directed` (`src/server/work/threshold.ts`). Claiming it does not
|
|
85
|
+
* change that: the gate judges the MESSAGE's addressing, not the claim.
|
|
86
|
+
* That is the same addressing gap that leaves a broadcast unanswered in the
|
|
87
|
+
* first place (`lib/org/inbound/directedness.mjs` has no broadcast concept
|
|
88
|
+
* at all), and it closes in one place — when the ingest layer learns a
|
|
89
|
+
* `collective` verdict and `project.mjs` counts it as a genuine address.
|
|
90
|
+
* When it does, the negative test here goes red and becomes a positive one.
|
|
91
|
+
*
|
|
92
|
+
* 2. A REPLY WITHOUT A CLAIM STILL WRITES `done`. `reply` records its step on
|
|
93
|
+
* delivery, whether or not the item was ever claimed, so an ask answered
|
|
94
|
+
* straight out of the inbox reaches hq with no row yet open. hq does NOT
|
|
95
|
+
* mint a closed row for it: `ledger.ts`'s born-closed rule downgrades a
|
|
96
|
+
* first-touch `done` to `accepted`, so the room is told the ask was picked
|
|
97
|
+
* up, not that it was completed, and the row stays open for whatever
|
|
98
|
+
* genuinely finishes it. Truthful, but new and channel-visible, so it is
|
|
99
|
+
* pinned on both sides rather than left to be rediscovered.
|
|
100
|
+
*
|
|
101
|
+
* Pure core + one injected effect. {@link ledgerStepsFor} is a total function
|
|
102
|
+
* over plain data with no clock, no fs and no network; {@link runAskLedger} is
|
|
103
|
+
* the only thing here that does I/O and it cannot throw into its caller.
|
|
104
|
+
*
|
|
105
|
+
* @module lib/session/ask-ledger
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
const NOTE_MAX = 2000;
|
|
109
|
+
|
|
110
|
+
/** Actions the session lane can take on an inbox item. */
|
|
111
|
+
export const LEDGER_ACTIONS = ["claim", "reply", "done", "defer"];
|
|
112
|
+
|
|
113
|
+
/** Collapse whitespace and clip — a note is a board comment, not a transcript. */
|
|
114
|
+
function note(text, max = NOTE_MAX) {
|
|
115
|
+
const one = String(text == null ? "" : text).replace(/\s+/g, " ").trim();
|
|
116
|
+
return one.length > max ? `${one.slice(0, max - 1)}…` : one;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The ledger steps ONE session-lane action owes, in order. Pure and total: any
|
|
121
|
+
* unknown action, or an action whose facts say the step would be a duplicate,
|
|
122
|
+
* yields `[]` rather than throwing.
|
|
123
|
+
*
|
|
124
|
+
* Chained, never parallel: `triage` is not terminal, so an `accepted` that
|
|
125
|
+
* commits after a `working` drags the row back out of `running` for good. The
|
|
126
|
+
* caller awaits each step before the next.
|
|
127
|
+
*
|
|
128
|
+
* @param {object} a
|
|
129
|
+
* @param {string} a.action one of {@link LEDGER_ACTIONS}
|
|
130
|
+
* @param {{repliedAt?:string}} [a.markers] session markers already on the item
|
|
131
|
+
* @param {string} [a.text] the reply text (`reply`)
|
|
132
|
+
* @param {string} [a.until] ISO the item is parked until (`defer`)
|
|
133
|
+
* @param {string} [a.reason] why it was parked (`defer`)
|
|
134
|
+
* @returns {Array<{stage:string, deferred:boolean, note?:string}>}
|
|
135
|
+
*/
|
|
136
|
+
export function ledgerStepsFor(a = {}) {
|
|
137
|
+
const action = String(a.action || "").trim();
|
|
138
|
+
const markers = a.markers && typeof a.markers === "object" ? a.markers : {};
|
|
139
|
+
|
|
140
|
+
if (action === "claim") {
|
|
141
|
+
return [
|
|
142
|
+
{
|
|
143
|
+
stage: "accepted",
|
|
144
|
+
deferred: false,
|
|
145
|
+
note: "Picked this up — working on it now.",
|
|
146
|
+
},
|
|
147
|
+
{ stage: "working", deferred: false },
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (action === "reply") {
|
|
152
|
+
const body = note(a.text);
|
|
153
|
+
return [
|
|
154
|
+
{
|
|
155
|
+
stage: "done",
|
|
156
|
+
deferred: false,
|
|
157
|
+
note: body ? `Answered in the conversation: ${body}` : "Answered in the conversation.",
|
|
158
|
+
},
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (action === "done") {
|
|
163
|
+
// The reply already closed the row and said what was delivered. Saying it
|
|
164
|
+
// again adds a second comment that carries no new fact.
|
|
165
|
+
if (markers.repliedAt) return [];
|
|
166
|
+
return [{ stage: "done", deferred: false, note: "Marked finished from the inbox." }];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (action === "defer") {
|
|
170
|
+
const until = String(a.until || "").trim();
|
|
171
|
+
const why = note(a.reason, 400);
|
|
172
|
+
return [
|
|
173
|
+
{
|
|
174
|
+
stage: "blocked",
|
|
175
|
+
deferred: false,
|
|
176
|
+
note:
|
|
177
|
+
`Parked${until ? ` until ${until}` : ""}.` + (why ? ` ${why}` : ""),
|
|
178
|
+
},
|
|
179
|
+
];
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return [];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Write the steps one session-lane action owes, against the org board.
|
|
187
|
+
*
|
|
188
|
+
* FAIL-OPEN, NEVER SILENT — the same contract the daemon's `trackWorkStep`
|
|
189
|
+
* carries. A ledger write must never cost the human their reply or fail the
|
|
190
|
+
* command that already had its effect, so every path returns a result and
|
|
191
|
+
* nothing throws past this boundary. But every refusal comes back with a
|
|
192
|
+
* reason, because a process going quiet is the bug this workstream exists to
|
|
193
|
+
* remove.
|
|
194
|
+
*
|
|
195
|
+
* AWAITED, not fire-and-forget. The daemon is a long-lived process and can let
|
|
196
|
+
* a promise settle after the fact; the CLI is a short one whose caller exits the
|
|
197
|
+
* moment this returns, so an un-awaited write is a write that never leaves the
|
|
198
|
+
* machine. It is awaited AFTER the action's own effect has landed, so a slow or
|
|
199
|
+
* dead server delays the JSON on stdout and changes nothing else.
|
|
200
|
+
*
|
|
201
|
+
* @param {object} a
|
|
202
|
+
* @param {object} a.item the enriched inbox item (carries `service`)
|
|
203
|
+
* @param {string} a.action one of {@link LEDGER_ACTIONS}
|
|
204
|
+
* @param {object} [a.cfg] agent org config; `{}` reads as org-disabled
|
|
205
|
+
* @param {object} [a.markers]
|
|
206
|
+
* @param {string} [a.text]
|
|
207
|
+
* @param {string} [a.until]
|
|
208
|
+
* @param {string} [a.reason]
|
|
209
|
+
* @param {string} [a.title] row title, sent with the OPENING step only
|
|
210
|
+
* @param {string} [a.why] why the row was opened, sent with the OPENING step only
|
|
211
|
+
* @param {object} [a.source] free provenance stamped into the row's `why`
|
|
212
|
+
* @param {Function} [a.recordImpl] injected `recordWorkStep` (test seam)
|
|
213
|
+
* @param {Function} [a.trackImpl] injected `board.track` (test seam)
|
|
214
|
+
* @param {Function} [a.fetchImpl] injected fetch (test seam)
|
|
215
|
+
* @returns {Promise<{steps:Array<object>, results:Array<object>}>}
|
|
216
|
+
*/
|
|
217
|
+
export async function runAskLedger(a = {}) {
|
|
218
|
+
const steps = ledgerStepsFor(a);
|
|
219
|
+
const results = [];
|
|
220
|
+
if (steps.length === 0) return { steps, results };
|
|
221
|
+
try {
|
|
222
|
+
const record = a.recordImpl || (await import("../org/work-ledger.mjs")).recordWorkStep;
|
|
223
|
+
for (const [i, step] of steps.entries()) {
|
|
224
|
+
const res = await record({
|
|
225
|
+
item: a.item,
|
|
226
|
+
stage: step.stage,
|
|
227
|
+
deferred: step.deferred,
|
|
228
|
+
note: step.note,
|
|
229
|
+
cfg: a.cfg,
|
|
230
|
+
// ONLY THE FIRST STEP CAN OPEN THE ROW — a refused step breaks the loop
|
|
231
|
+
// below, so nothing after index 0 ever reaches hq's `if (!taskId)`
|
|
232
|
+
// branch. `title` and `why` are read there and nowhere else, so sending
|
|
233
|
+
// them on a later step would be a write that is accepted and ignored.
|
|
234
|
+
...(i === 0 && a.title ? { title: a.title } : {}),
|
|
235
|
+
...(i === 0 && a.why ? { why: a.why } : {}),
|
|
236
|
+
source: { lane: "session", action: a.action, ...(a.source || {}) },
|
|
237
|
+
trackImpl: a.trackImpl,
|
|
238
|
+
fetchImpl: a.fetchImpl,
|
|
239
|
+
});
|
|
240
|
+
results.push(res || { tracked: false, reason: "no-result" });
|
|
241
|
+
// A refused step refuses every step after it for the same reason (the
|
|
242
|
+
// gate is pure over the same facts), so stop rather than repeat the call.
|
|
243
|
+
if (!res || !res.tracked) break;
|
|
244
|
+
}
|
|
245
|
+
} catch (err) {
|
|
246
|
+
results.push({ tracked: false, reason: `error: ${err && err.message ? err.message : String(err)}`.slice(0, 200) });
|
|
247
|
+
}
|
|
248
|
+
return { steps, results };
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* One log line per action, for the session lane's own stdout. Pure.
|
|
253
|
+
* @param {string} action
|
|
254
|
+
* @param {{steps:Array<object>, results:Array<object>}} outcome
|
|
255
|
+
* @returns {string|null} null when the action owed no steps at all
|
|
256
|
+
*/
|
|
257
|
+
export function formatLedgerOutcome(action, outcome) {
|
|
258
|
+
const steps = (outcome && outcome.steps) || [];
|
|
259
|
+
const results = (outcome && outcome.results) || [];
|
|
260
|
+
if (steps.length === 0) return null;
|
|
261
|
+
const parts = steps.map((s, i) => {
|
|
262
|
+
const r = results[i];
|
|
263
|
+
if (!r) return `${s.stage}: not attempted`;
|
|
264
|
+
return r.tracked
|
|
265
|
+
? `${s.stage} → task ${r.taskId || "?"}${r.col ? ` [${r.col}]` : ""}${r.tagged ? ` tagged=${r.tagged}` : ""}`
|
|
266
|
+
: `${s.stage}: ${r.reason || "unknown"}`;
|
|
267
|
+
});
|
|
268
|
+
return `[board] ${action}: ${parts.join("; ")}`;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export default { LEDGER_ACTIONS, ledgerStepsFor, runAskLedger, formatLedgerOutcome };
|