@cohortapp/agent-sdk 2.16.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 +23 -7
- 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/poller-daemon-setup.md +4 -1
- 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/context/budget.mjs +327 -0
- package/lib/context/history-scope.mjs +138 -0
- 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/economics.mjs +9 -0
- package/lib/model-router/failover.mjs +67 -16
- package/lib/model-router/llm-task.mjs +39 -3
- package/lib/model-router/resolve.mjs +95 -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 +82 -4
- package/lib/org/inbound/hydrate.mjs +555 -51
- 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 +15 -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 +104 -59
- package/scripts/daemon/deliver.mjs +30 -1
- package/scripts/daemon/dispatcher.mjs +804 -157
- package/scripts/daemon/health.mjs +14 -1
- package/scripts/daemon/lib/session-router.mjs +310 -42
- package/scripts/daemon/maestro-daemon.mjs +11 -0
- package/scripts/daemon/prompt-builder.mjs +121 -12
- package/scripts/daemon/responder.mjs +315 -146
- 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/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 -453
- 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 -300
- 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/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 -295
- package/scripts/daemon/prompt-builder-preamble.test.mjs +0 -210
- package/scripts/daemon/prompt-builder.test.mjs +0 -344
- package/scripts/daemon/responder-cost.test.mjs +0 -68
- package/scripts/daemon/responder-history.test.mjs +0 -185
- 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
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: "Northwind"
|
|
3
|
-
version: "bv_01HQZ"
|
|
4
|
-
generatedAt: "2026-09-08T12:00:00.000Z"
|
|
5
|
-
source: "cohort · branding.getFoundation"
|
|
6
|
-
colors:
|
|
7
|
-
ink: "#0d0d0d"
|
|
8
|
-
paper: "#ffffff"
|
|
9
|
-
primary-moss: "#2d5be3"
|
|
10
|
-
muted: "#6b7280"
|
|
11
|
-
accent-amber: "#c9851f"
|
|
12
|
-
line: "#e7e5e4"
|
|
13
|
-
primary: "#2d5be3"
|
|
14
|
-
accent: "#c9851f"
|
|
15
|
-
success: "#177245"
|
|
16
|
-
warning: "#c9851f"
|
|
17
|
-
danger: "#a11d1d"
|
|
18
|
-
neutral-100: "#f5f5f4"
|
|
19
|
-
neutral-500: "#78716c"
|
|
20
|
-
neutral-900: "#1c1917"
|
|
21
|
-
colorsDark:
|
|
22
|
-
ink: "#f5f5f4"
|
|
23
|
-
paper: "#0b0b0c"
|
|
24
|
-
primary-moss: "#7ea0ff"
|
|
25
|
-
line: "#26262a"
|
|
26
|
-
primary: "#7ea0ff"
|
|
27
|
-
typography:
|
|
28
|
-
display: "Outfit"
|
|
29
|
-
body: "Inter"
|
|
30
|
-
mono: "JetBrains Mono"
|
|
31
|
-
heading: "Outfit"
|
|
32
|
-
scale:
|
|
33
|
-
display: { size: "76px", weight: 600, leading: 1.05, tracking: -0.02 }
|
|
34
|
-
heading: { size: "38px", weight: 600, leading: 1.15, tracking: -0.01 }
|
|
35
|
-
body: { size: "14px", weight: 400, leading: 1.5 }
|
|
36
|
-
small: { size: "11.5px", weight: 500 }
|
|
37
|
-
caption: { size: "11px", weight: 500, leading: 1.4, tracking: 0.04 }
|
|
38
|
-
rounded:
|
|
39
|
-
chip: "8px"
|
|
40
|
-
field: "9px"
|
|
41
|
-
card: "13px"
|
|
42
|
-
modal: "14px"
|
|
43
|
-
pill: "999px"
|
|
44
|
-
spacing:
|
|
45
|
-
xs: "4px"
|
|
46
|
-
sm: "8px"
|
|
47
|
-
md: "12px"
|
|
48
|
-
lg: "16px"
|
|
49
|
-
xl: "22px"
|
|
50
|
-
shadow:
|
|
51
|
-
sm: "0 1px 2px rgba(13,13,13,0.06)"
|
|
52
|
-
md: "0 18px 50px rgba(13,13,13,0.13)"
|
|
53
|
-
border:
|
|
54
|
-
hairline: "1px solid #e7e5e4"
|
|
55
|
-
strong: "1px solid #d6d3d1"
|
|
56
|
-
components:
|
|
57
|
-
button:
|
|
58
|
-
background: "{colors.primary}"
|
|
59
|
-
foreground: "{colors.paper}"
|
|
60
|
-
radius: "{rounded.pill}"
|
|
61
|
-
padding: "{spacing.sm} {spacing.lg}"
|
|
62
|
-
font: "{typography.body}"
|
|
63
|
-
card:
|
|
64
|
-
background: "{colors.paper}"
|
|
65
|
-
foreground: "{colors.ink}"
|
|
66
|
-
border: "{border.hairline}"
|
|
67
|
-
radius: "{rounded.card}"
|
|
68
|
-
padding: "{spacing.xl}"
|
|
69
|
-
shadow: "{shadow.md}"
|
|
70
|
-
input:
|
|
71
|
-
background: "{colors.paper}"
|
|
72
|
-
border: "{border.hairline}"
|
|
73
|
-
radius: "{rounded.field}"
|
|
74
|
-
padding: "{spacing.sm} {spacing.md}"
|
|
75
|
-
font: "{typography.body}"
|
|
76
|
-
surface:
|
|
77
|
-
background: "{colors.paper}"
|
|
78
|
-
foreground: "{colors.ink}"
|
|
79
|
-
muted: "{colors.muted}"
|
|
80
|
-
radius: "{rounded.modal}"
|
|
81
|
-
---
|
|
82
|
-
|
|
83
|
-
# Northwind — design system
|
|
84
|
-
|
|
85
|
-
The frontmatter above is the token contract: it is generated from the workspace's
|
|
86
|
-
saved brand foundation and is the source of truth for colour, type, radius and
|
|
87
|
-
spacing. Read it before you pick a value. Component entries are written as
|
|
88
|
-
`{group.key}` refs, so changing a token changes every component that names it.
|
|
89
|
-
|
|
90
|
-
This file is GENERATED — edits here are overwritten on the next sync. To change
|
|
91
|
-
the foundation itself, propose the change (`design_propose_change`); a human
|
|
92
|
-
reviews and applies it, and the next sync brings it back down.
|
|
93
|
-
|
|
94
|
-
## Palette
|
|
95
|
-
|
|
96
|
-
- `{colors.ink}` — #0d0d0d (dark #f5f5f4)
|
|
97
|
-
- `{colors.paper}` — #ffffff (dark #0b0b0c)
|
|
98
|
-
- `{colors.primary-moss}` — #2d5be3 (dark #7ea0ff)
|
|
99
|
-
- `{colors.muted}` — #6b7280
|
|
100
|
-
- `{colors.accent-amber}` — #c9851f
|
|
101
|
-
- `{colors.line}` — #e7e5e4 (dark #26262a)
|
|
102
|
-
- `{colors.primary}` — #2d5be3 (dark #7ea0ff)
|
|
103
|
-
- `{colors.accent}` — #c9851f
|
|
104
|
-
- `{colors.success}` — #177245
|
|
105
|
-
- `{colors.warning}` — #c9851f
|
|
106
|
-
- `{colors.danger}` — #a11d1d
|
|
107
|
-
- `{colors.neutral-100}` — #f5f5f4
|
|
108
|
-
- `{colors.neutral-500}` — #78716c
|
|
109
|
-
- `{colors.neutral-900}` — #1c1917
|
|
110
|
-
|
|
111
|
-
## Typography
|
|
112
|
-
|
|
113
|
-
- **display:** Outfit
|
|
114
|
-
- **body:** Inter
|
|
115
|
-
- **mono:** JetBrains Mono
|
|
116
|
-
- **heading:** Outfit
|
|
117
|
-
|
|
118
|
-
- `{typography.scale.display}` — 76px · weight 600 · leading 1.05 · tracking -0.02
|
|
119
|
-
- `{typography.scale.heading}` — 38px · weight 600 · leading 1.15 · tracking -0.01
|
|
120
|
-
- `{typography.scale.body}` — 14px · weight 400 · leading 1.5
|
|
121
|
-
- `{typography.scale.small}` — 11.5px · weight 500
|
|
122
|
-
- `{typography.scale.caption}` — 11px · weight 500 · leading 1.4 · tracking 0.04
|
|
123
|
-
|
|
124
|
-
### Type rules
|
|
125
|
-
|
|
126
|
-
One geometric face for structure, one humanist face for reading.
|
|
127
|
-
|
|
128
|
-
- Display only above 32px.
|
|
129
|
-
- Never set body copy below 13px.
|
|
130
|
-
|
|
131
|
-
### Colour rules
|
|
132
|
-
|
|
133
|
-
- One primary per view.
|
|
134
|
-
- Semantic colour is for state, never decoration.
|
|
135
|
-
|
|
136
|
-
## Visual language
|
|
137
|
-
|
|
138
|
-
### Imagery
|
|
139
|
-
|
|
140
|
-
- **Uses imagery:** yes
|
|
141
|
-
- **Medium:** photography
|
|
142
|
-
- **Secondary media:** diagram
|
|
143
|
-
- **Grade:** natural
|
|
144
|
-
- **Grain:** fine
|
|
145
|
-
- **Crop:** wide
|
|
146
|
-
- **Aspect ratios:** 16/9, 1/1
|
|
147
|
-
- **Subjects:** hands at work, quiet rooms
|
|
148
|
-
- **Mood:** calm, considered
|
|
149
|
-
- **Composition:** off-centre, generous negative space
|
|
150
|
-
- **Duotone:** shadow #12213f · highlight #f3ede1
|
|
151
|
-
|
|
152
|
-
### Imagery (brand system)
|
|
153
|
-
|
|
154
|
-
- **Medium:** documentary photography
|
|
155
|
-
- **Style:** unstaged
|
|
156
|
-
- **Treatment:** warm highlights, cool shadows
|
|
157
|
-
- **Mood:** assured
|
|
158
|
-
- **Subjects:** workshops, field crews
|
|
159
|
-
- **Avoid:** stock handshakes, isolated laptops
|
|
160
|
-
|
|
161
|
-
### Iconography
|
|
162
|
-
|
|
163
|
-
- **Style:** line
|
|
164
|
-
- **Weight:** 1.5px
|
|
165
|
-
- **Corner:** rounded
|
|
166
|
-
- **Grid:** 24
|
|
167
|
-
|
|
168
|
-
### Motion
|
|
169
|
-
|
|
170
|
-
- **Character:** settled
|
|
171
|
-
- **Easing:** cubic-bezier(0.2, 0, 0, 1)
|
|
172
|
-
- **Duration (ms):** 220
|
|
173
|
-
- **Principles:** Move once, arrive., Never animate what a person is reading.
|
|
174
|
-
|
|
175
|
-
### Texture
|
|
176
|
-
|
|
177
|
-
- **Surfaces:** paper, frosted glass
|
|
178
|
-
- **Background:** flat
|
|
179
|
-
- **Notes:** No gradients behind text.
|
|
180
|
-
|
|
181
|
-
### Guardrails
|
|
182
|
-
|
|
183
|
-
Do:
|
|
184
|
-
|
|
185
|
-
- Let type carry the page.
|
|
186
|
-
- Use one accent per view.
|
|
187
|
-
|
|
188
|
-
Do not:
|
|
189
|
-
|
|
190
|
-
- No stock handshakes.
|
|
191
|
-
- No drop shadows on text.
|
|
192
|
-
|
|
193
|
-
### Generation seeds
|
|
194
|
-
|
|
195
|
-
- **Prompt seed:** quiet rooms, natural light, fine grain
|
|
196
|
-
- **Seed locked:** yes
|
|
197
|
-
- **Negative seed:** neon, lens flare
|
|
198
|
-
- **References:** moodboard/2026-03
|
|
199
|
-
- **Source:** generated
|
|
200
|
-
- **Schema version:** 2
|
|
201
|
-
|
|
202
|
-
## Layout principles
|
|
203
|
-
|
|
204
|
-
- Left-align everything that reads.
|
|
205
|
-
- One idea per band.
|
|
206
|
-
|
|
207
|
-
## Marks
|
|
208
|
-
|
|
209
|
-
- `brandIcon` — set
|
|
210
|
-
- `wordmark` — set
|
|
211
|
-
|
|
212
|
-
Fetch the bytes with `design_export_kit`; never inline them here.
|
|
213
|
-
|
|
214
|
-
## Additional tokens
|
|
215
|
-
|
|
216
|
-
Keys the renderer does not model yet, carried through verbatim so nothing is
|
|
217
|
-
lost between an hq that added a token and an SDK that has not learned it.
|
|
218
|
-
|
|
219
|
-
```json
|
|
220
|
-
{
|
|
221
|
-
"elevationCurve": {
|
|
222
|
-
"0": "none",
|
|
223
|
-
"1": "0 1px 2px rgba(0,0,0,0.05)"
|
|
224
|
-
},
|
|
225
|
-
"examples": {
|
|
226
|
-
"hero": "A crew at first light.",
|
|
227
|
-
"cta": "Start the walkthrough"
|
|
228
|
-
},
|
|
229
|
-
"gridUnit": 4
|
|
230
|
-
}
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
## Provenance
|
|
234
|
-
|
|
235
|
-
- **Version:** V2.7
|
|
236
|
-
- **Version id:** bv_01HQZ
|
|
237
|
-
- **Synced:** 2026-09-08T12:00:00.000Z
|
|
238
|
-
- **Source:** cohort · branding.getFoundation
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: "Northwind"
|
|
3
|
-
version: "bv_01HQZ"
|
|
4
|
-
generatedAt: "2026-09-08T12:00:00.000Z"
|
|
5
|
-
source: "cohort · branding.getFoundation"
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Northwind — product voice
|
|
9
|
-
|
|
10
|
-
Generated from the workspace's saved brand foundation. It says how this
|
|
11
|
-
product sounds; `DESIGN.md` beside it says how it looks. Read both before
|
|
12
|
-
writing anything a customer sees. Edits here are overwritten on the next
|
|
13
|
-
sync — propose foundation changes with `design_propose_change`.
|
|
14
|
-
|
|
15
|
-
## Positioning
|
|
16
|
-
|
|
17
|
-
The operating system for companies that run on agents as well as people.
|
|
18
|
-
|
|
19
|
-
## Taglines
|
|
20
|
-
|
|
21
|
-
- Work that runs itself.
|
|
22
|
-
- One company, many hands.
|
|
23
|
-
|
|
24
|
-
## Voice
|
|
25
|
-
|
|
26
|
-
Concise, specific, accountable. Write like a capable peer — no hype, no emoji, no hedging.
|
|
27
|
-
|
|
28
|
-
## Tone
|
|
29
|
-
|
|
30
|
-
- Plain
|
|
31
|
-
- Exact
|
|
32
|
-
- Unhurried
|
|
33
|
-
- Direct
|
|
34
|
-
|
|
35
|
-
## Lexicon
|
|
36
|
-
|
|
37
|
-
Say:
|
|
38
|
-
|
|
39
|
-
- decide
|
|
40
|
-
- ship
|
|
41
|
-
- owe
|
|
42
|
-
|
|
43
|
-
Avoid:
|
|
44
|
-
|
|
45
|
-
- leverage
|
|
46
|
-
- synergy
|
|
47
|
-
- unlock
|
|
48
|
-
|
|
49
|
-
## In practice
|
|
50
|
-
|
|
51
|
-
Two invoices need a decision today. Both are under £5,000.
|
|
52
|
-
|
|
53
|
-
## Motifs
|
|
54
|
-
|
|
55
|
-
- A single hairline rule.
|
|
56
|
-
- Numbers set in the mono face.
|
|
57
|
-
|
|
58
|
-
## Iconography
|
|
59
|
-
|
|
60
|
-
Line icons on a 24px grid, 1.5px stroke.
|
|
61
|
-
|
|
62
|
-
## Provenance
|
|
63
|
-
|
|
64
|
-
- **Version:** V2.7
|
|
65
|
-
- **Version id:** bv_01HQZ
|
|
66
|
-
- **Synced:** 2026-09-08T12:00:00.000Z
|
|
67
|
-
- **Source:** cohort · branding.getFoundation
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"v": 2,
|
|
3
|
-
"colors": [
|
|
4
|
-
{ "name": "Ink", "value": "#0d0d0d", "dark": "#f5f5f4" },
|
|
5
|
-
{ "name": "Paper", "value": "#ffffff", "dark": "#0b0b0c" },
|
|
6
|
-
{ "name": "Primary · Moss", "value": "#2d5be3", "dark": "#7ea0ff" },
|
|
7
|
-
{ "name": "Muted", "value": "#6b7280" },
|
|
8
|
-
{ "name": "Accent · Amber", "value": "#c9851f" },
|
|
9
|
-
{ "name": "Line", "value": "#e7e5e4", "dark": "#26262a" }
|
|
10
|
-
],
|
|
11
|
-
"fonts": { "display": "Outfit", "body": "Inter", "mono": "JetBrains Mono" },
|
|
12
|
-
"type": [
|
|
13
|
-
{ "role": "Display", "size": 76, "weight": 600 },
|
|
14
|
-
{ "role": "Heading", "size": 38, "weight": 600 },
|
|
15
|
-
{ "role": "Body", "size": 14, "weight": 400 },
|
|
16
|
-
{ "role": "Small", "size": 11.5, "weight": 500 }
|
|
17
|
-
],
|
|
18
|
-
"space": [
|
|
19
|
-
{ "name": "xs", "value": 4 },
|
|
20
|
-
{ "name": "sm", "value": 8 },
|
|
21
|
-
{ "name": "md", "value": 12 },
|
|
22
|
-
{ "name": "lg", "value": 16 },
|
|
23
|
-
{ "name": "xl", "value": 22 }
|
|
24
|
-
],
|
|
25
|
-
"radii": [
|
|
26
|
-
{ "name": "chip", "value": 8 },
|
|
27
|
-
{ "name": "field", "value": 9 },
|
|
28
|
-
{ "name": "card", "value": 13 },
|
|
29
|
-
{ "name": "modal", "value": 14 },
|
|
30
|
-
{ "name": "pill", "value": 999 }
|
|
31
|
-
],
|
|
32
|
-
"shadow": [
|
|
33
|
-
{ "name": "sm", "value": "0 1px 2px rgba(13,13,13,0.06)" },
|
|
34
|
-
{ "name": "md", "value": "0 18px 50px rgba(13,13,13,0.13)" }
|
|
35
|
-
],
|
|
36
|
-
"border": [
|
|
37
|
-
{ "name": "hairline", "value": "1px solid #e7e5e4" },
|
|
38
|
-
{ "name": "strong", "value": "1px solid #d6d3d1" }
|
|
39
|
-
],
|
|
40
|
-
"voice": "Concise, specific, accountable. Write like a capable peer — no hype, no emoji, no hedging.",
|
|
41
|
-
"positioning": "The operating system for companies that run on agents as well as people.",
|
|
42
|
-
"taglines": ["Work that runs itself.", "One company, many hands."],
|
|
43
|
-
"toneTraits": ["Plain", "Exact", "Unhurried"],
|
|
44
|
-
"logos": {
|
|
45
|
-
"brandIcon": "https://assets.example.test/icon.png",
|
|
46
|
-
"wordmark": "https://assets.example.test/wordmark.svg",
|
|
47
|
-
"favicon": null
|
|
48
|
-
},
|
|
49
|
-
"examples": { "hero": "A crew at first light.", "cta": "Start the walkthrough" },
|
|
50
|
-
"visualLanguage": {
|
|
51
|
-
"v": 2,
|
|
52
|
-
"source": "generated",
|
|
53
|
-
"imagery": {
|
|
54
|
-
"needsImagery": true,
|
|
55
|
-
"medium": "photography",
|
|
56
|
-
"secondaryMedia": ["diagram"],
|
|
57
|
-
"colorGrade": "natural",
|
|
58
|
-
"grain": "fine",
|
|
59
|
-
"crop": "wide",
|
|
60
|
-
"aspectRatios": ["16/9", "1/1"],
|
|
61
|
-
"subjects": ["hands at work", "quiet rooms"],
|
|
62
|
-
"mood": ["calm", "considered"],
|
|
63
|
-
"composition": "off-centre, generous negative space",
|
|
64
|
-
"duotone": { "shadow": "#12213f", "highlight": "#f3ede1" }
|
|
65
|
-
},
|
|
66
|
-
"iconography": { "style": "line", "weight": "1.5px", "corner": "rounded", "grid": 24 },
|
|
67
|
-
"motion": {
|
|
68
|
-
"character": "settled",
|
|
69
|
-
"easing": "cubic-bezier(0.2, 0, 0, 1)",
|
|
70
|
-
"durationMs": 220,
|
|
71
|
-
"principles": ["Move once, arrive.", "Never animate what a person is reading."]
|
|
72
|
-
},
|
|
73
|
-
"texture": { "surfaces": ["paper", "frosted glass"], "background": "flat", "notes": "No gradients behind text." },
|
|
74
|
-
"guardrails": {
|
|
75
|
-
"dos": ["Let type carry the page.", "Use one accent per view."],
|
|
76
|
-
"donts": ["No stock handshakes.", "No drop shadows on text."]
|
|
77
|
-
},
|
|
78
|
-
"promptSeed": "quiet rooms, natural light, fine grain",
|
|
79
|
-
"seedLocked": true,
|
|
80
|
-
"negativeSeed": "neon, lens flare",
|
|
81
|
-
"references": ["moodboard/2026-03"]
|
|
82
|
-
},
|
|
83
|
-
"system": {
|
|
84
|
-
"typography": {
|
|
85
|
-
"families": {
|
|
86
|
-
"display": { "family": "Outfit", "category": "sans", "weights": [500, 600] },
|
|
87
|
-
"heading": { "family": "Outfit", "category": "sans", "weights": [600] },
|
|
88
|
-
"body": { "family": "Inter", "category": "sans", "weights": [400, 500] },
|
|
89
|
-
"mono": { "family": "JetBrains Mono", "category": "mono", "weights": [400] }
|
|
90
|
-
},
|
|
91
|
-
"scale": [
|
|
92
|
-
{ "role": "Display", "size": 76, "weight": 600, "leading": 1.05, "tracking": -0.02 },
|
|
93
|
-
{ "role": "Heading", "size": 38, "weight": 600, "leading": 1.15, "tracking": -0.01 },
|
|
94
|
-
{ "role": "Body", "size": 14, "weight": 400, "leading": 1.5 },
|
|
95
|
-
{ "role": "Caption", "size": 11, "weight": 500, "leading": 1.4, "tracking": 0.04 }
|
|
96
|
-
],
|
|
97
|
-
"pairingRationale": "One geometric face for structure, one humanist face for reading.",
|
|
98
|
-
"usageRules": ["Display only above 32px.", "Never set body copy below 13px."]
|
|
99
|
-
},
|
|
100
|
-
"color": {
|
|
101
|
-
"roles": {
|
|
102
|
-
"primary": { "name": "Signal Blue", "value": "#2d5be3", "dark": "#7ea0ff" },
|
|
103
|
-
"accent": { "name": "Amber", "value": "#c9851f" }
|
|
104
|
-
},
|
|
105
|
-
"neutralRamp": [
|
|
106
|
-
{ "step": 100, "value": "#f5f5f4" },
|
|
107
|
-
{ "step": 500, "value": "#78716c" },
|
|
108
|
-
{ "step": 900, "value": "#1c1917" }
|
|
109
|
-
],
|
|
110
|
-
"semantic": { "success": "#177245", "warning": "#c9851f", "danger": "#a11d1d" },
|
|
111
|
-
"usageRules": ["One primary per view.", "Semantic colour is for state, never decoration."]
|
|
112
|
-
},
|
|
113
|
-
"imagery": {
|
|
114
|
-
"medium": "documentary photography",
|
|
115
|
-
"style": "unstaged",
|
|
116
|
-
"treatment": "warm highlights, cool shadows",
|
|
117
|
-
"mood": "assured",
|
|
118
|
-
"subjects": ["workshops", "field crews"],
|
|
119
|
-
"donts": ["stock handshakes", "isolated laptops"]
|
|
120
|
-
},
|
|
121
|
-
"motifs": ["A single hairline rule.", "Numbers set in the mono face."],
|
|
122
|
-
"iconography": "Line icons on a 24px grid, 1.5px stroke.",
|
|
123
|
-
"layoutPrinciples": ["Left-align everything that reads.", "One idea per band."],
|
|
124
|
-
"voice": {
|
|
125
|
-
"voice": "Concise, specific, accountable.",
|
|
126
|
-
"toneTraits": ["Plain", "Direct"],
|
|
127
|
-
"lexicon": { "use": ["decide", "ship", "owe"], "avoid": ["leverage", "synergy", "unlock"] },
|
|
128
|
-
"exampleCopy": "Two invoices need a decision today. Both are under £5,000."
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
"elevationCurve": { "0": "none", "1": "0 1px 2px rgba(0,0,0,0.05)" },
|
|
132
|
-
"gridUnit": 4
|
|
133
|
-
}
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* refresh-gate.test.mjs — WHEN a seat re-syncs its brand foundation
|
|
3
|
-
* (WP-M7 mechanic 4). The gate is pure, so every case here is a table row.
|
|
4
|
-
*
|
|
5
|
-
* The two rules worth stating in prose because they are the ones a reader
|
|
6
|
-
* would get wrong:
|
|
7
|
-
*
|
|
8
|
-
* · An UNKNOWN current version is not a change. The daemon asks the gate
|
|
9
|
-
* twice per tick — before the read (version unknown) and after it — and if
|
|
10
|
-
* "unknown" counted as a new version, the pre-read call would say yes on
|
|
11
|
-
* every tick and the interval would mean nothing.
|
|
12
|
-
* · A `lastAt` in the FUTURE refreshes. A clock that jumped backwards (or a
|
|
13
|
-
* state file copied from another box) must not be able to freeze DESIGN.md
|
|
14
|
-
* on disk until the wall clock catches up.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { test } from "node:test";
|
|
18
|
-
import assert from "node:assert/strict";
|
|
19
|
-
|
|
20
|
-
import {
|
|
21
|
-
isUnversionedFoundation,
|
|
22
|
-
shouldRefreshDesign,
|
|
23
|
-
foundationVersion,
|
|
24
|
-
foundationVersionLabel,
|
|
25
|
-
DESIGN_REFRESH_INTERVAL_MS,
|
|
26
|
-
DESIGN_STATE_REL,
|
|
27
|
-
DESIGN_FILES,
|
|
28
|
-
} from "./refresh-gate.mjs";
|
|
29
|
-
|
|
30
|
-
const NOW = Date.parse("2026-09-08T12:00:00Z");
|
|
31
|
-
|
|
32
|
-
test("the interval is 15 minutes and the paths are the ones the CLI and daemon write", () => {
|
|
33
|
-
assert.equal(DESIGN_REFRESH_INTERVAL_MS, 15 * 60_000);
|
|
34
|
-
assert.equal(DESIGN_STATE_REL, "state/design/foundation.json");
|
|
35
|
-
assert.deepEqual(DESIGN_FILES, ["DESIGN.md", "PRODUCT.md"]);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test("never synced → refresh", () => {
|
|
39
|
-
assert.deepEqual(shouldRefreshDesign({ now: NOW }), { refresh: true, reason: "never" });
|
|
40
|
-
assert.deepEqual(shouldRefreshDesign({ lastAt: null, now: NOW }), { refresh: true, reason: "never" });
|
|
41
|
-
assert.deepEqual(shouldRefreshDesign({ lastAt: "not a date", now: NOW }), { refresh: true, reason: "never" });
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test("inside the interval with an unchanged version → no refresh", () => {
|
|
45
|
-
assert.deepEqual(
|
|
46
|
-
shouldRefreshDesign({ lastVersion: "bv_1", currentVersion: "bv_1", lastAt: NOW - 60_000, now: NOW }),
|
|
47
|
-
{ refresh: false, reason: "fresh" },
|
|
48
|
-
);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test("a changed version refreshes immediately, however recent the last sync", () => {
|
|
52
|
-
assert.deepEqual(
|
|
53
|
-
shouldRefreshDesign({ lastVersion: "bv_1", currentVersion: "bv_2", lastAt: NOW - 1_000, now: NOW }),
|
|
54
|
-
{ refresh: true, reason: "version-changed" },
|
|
55
|
-
);
|
|
56
|
-
// First-ever version on a seat that had synced an unversioned org.
|
|
57
|
-
assert.deepEqual(
|
|
58
|
-
shouldRefreshDesign({ lastVersion: null, currentVersion: "bv_1", lastAt: NOW - 1_000, now: NOW }),
|
|
59
|
-
{ refresh: true, reason: "version-changed" },
|
|
60
|
-
);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test("an UNKNOWN current version is not a change — the pre-read call must not always say yes", () => {
|
|
64
|
-
for (const currentVersion of [null, undefined, "", 7, {}]) {
|
|
65
|
-
assert.deepEqual(
|
|
66
|
-
shouldRefreshDesign({ lastVersion: "bv_1", currentVersion, lastAt: NOW - 60_000, now: NOW }),
|
|
67
|
-
{ refresh: false, reason: "fresh" },
|
|
68
|
-
`currentVersion=${JSON.stringify(currentVersion)}`,
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("the interval fires at the boundary and after it, not before", () => {
|
|
74
|
-
const at = (dt) => shouldRefreshDesign({ lastVersion: "bv_1", currentVersion: "bv_1", lastAt: NOW - dt, now: NOW });
|
|
75
|
-
assert.equal(at(DESIGN_REFRESH_INTERVAL_MS - 1).refresh, false);
|
|
76
|
-
assert.deepEqual(at(DESIGN_REFRESH_INTERVAL_MS), { refresh: true, reason: "interval" });
|
|
77
|
-
assert.deepEqual(at(DESIGN_REFRESH_INTERVAL_MS * 10), { refresh: true, reason: "interval" });
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("a lastAt in the future refreshes rather than freezing the seat", () => {
|
|
81
|
-
assert.deepEqual(
|
|
82
|
-
shouldRefreshDesign({ lastVersion: "bv_1", currentVersion: "bv_1", lastAt: NOW + 86_400_000, now: NOW }),
|
|
83
|
-
{ refresh: true, reason: "clock-skew" },
|
|
84
|
-
);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test("lastAt is accepted as an ISO string or epoch ms", () => {
|
|
88
|
-
const iso = shouldRefreshDesign({ lastVersion: "bv_1", currentVersion: "bv_1", lastAt: "2026-09-08T11:59:00Z", now: NOW });
|
|
89
|
-
const ms = shouldRefreshDesign({ lastVersion: "bv_1", currentVersion: "bv_1", lastAt: NOW - 60_000, now: NOW });
|
|
90
|
-
assert.deepEqual(iso, ms);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
test("a bad or absent intervalMs falls back to the 15-minute default", () => {
|
|
94
|
-
for (const intervalMs of [undefined, null, 0, -5, NaN, "soon"]) {
|
|
95
|
-
const r = shouldRefreshDesign({ lastVersion: "bv_1", currentVersion: "bv_1", lastAt: NOW - 14 * 60_000, now: NOW, intervalMs });
|
|
96
|
-
assert.equal(r.refresh, false, `intervalMs=${String(intervalMs)}`);
|
|
97
|
-
}
|
|
98
|
-
assert.equal(
|
|
99
|
-
shouldRefreshDesign({ lastVersion: "bv_1", currentVersion: "bv_1", lastAt: NOW - 60_000, now: NOW, intervalMs: 30_000 }).reason,
|
|
100
|
-
"interval",
|
|
101
|
-
"an explicit shorter interval is honoured",
|
|
102
|
-
);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test("foundationVersion prefers headVersionId, then version.id, then a stable 'unversioned'", () => {
|
|
106
|
-
assert.equal(foundationVersion({ headVersionId: "bv_1", version: { id: "bv_0" }, foundation: {} }), "bv_1");
|
|
107
|
-
assert.equal(foundationVersion({ headVersionId: null, version: { id: "bv_0" }, foundation: {} }), "bv_0");
|
|
108
|
-
assert.equal(foundationVersion({ headVersionId: null, version: null, foundation: {} }), "unversioned");
|
|
109
|
-
assert.equal(foundationVersion({}), null, "a frame with no foundation has no version identity");
|
|
110
|
-
assert.equal(foundationVersion(null), null);
|
|
111
|
-
assert.equal(foundationVersion("nope"), null);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
test("'unversioned' is STABLE, so an org that never saved a foundation does not re-render every poll", () => {
|
|
115
|
-
const frame = { headVersionId: null, version: null, foundation: { colors: [] } };
|
|
116
|
-
const v = foundationVersion(frame);
|
|
117
|
-
assert.equal(shouldRefreshDesign({ lastVersion: v, currentVersion: foundationVersion(frame), lastAt: NOW - 60_000, now: NOW }).refresh, false);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
test("foundationVersionLabel reads the label, falls back to V2.<seq>, and never invents", () => {
|
|
121
|
-
assert.equal(foundationVersionLabel({ version: { label: "Palette refresh", seq: 7 } }), "Palette refresh");
|
|
122
|
-
assert.equal(foundationVersionLabel({ version: { seq: 7 } }), "V2.7");
|
|
123
|
-
assert.equal(foundationVersionLabel({ version: { label: " " } }), "");
|
|
124
|
-
assert.equal(foundationVersionLabel({ version: null }), "");
|
|
125
|
-
assert.equal(foundationVersionLabel(null), "");
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test("isUnversionedFoundation catches the frame hq ACTUALLY sends for a workspace with no brand", () => {
|
|
129
|
-
// hq's `loadSavedFoundation` falls back to `dsDefaults()`, so the foundation
|
|
130
|
-
// is never null. `unversioned` is the only truthful signal, and an older hq
|
|
131
|
-
// that omits it is judged by having no version identity at all.
|
|
132
|
-
const stock = { foundation: { colors: [] }, version: null, headVersionId: null, unversioned: true };
|
|
133
|
-
assert.equal(isUnversionedFoundation(stock), true);
|
|
134
|
-
assert.equal(isUnversionedFoundation({ ...stock, unversioned: undefined }), true, "older hq: no version identity of any kind");
|
|
135
|
-
|
|
136
|
-
const saved = { foundation: { colors: [] }, version: { id: "bv_1", seq: 3 }, headVersionId: "bv_1", unversioned: false };
|
|
137
|
-
assert.equal(isUnversionedFoundation(saved), false);
|
|
138
|
-
// hq is trusted when it states the field, even where retention pruned the
|
|
139
|
-
// snapshot row and only the etag survives.
|
|
140
|
-
assert.equal(isUnversionedFoundation({ foundation: {}, version: null, headVersionId: "bv_9", unversioned: false }), false);
|
|
141
|
-
|
|
142
|
-
assert.equal(isUnversionedFoundation(null), false, "an absent frame is a read failure, not an unversioned workspace");
|
|
143
|
-
assert.equal(isUnversionedFoundation({}), false);
|
|
144
|
-
});
|