@bongos/core 1.17.0
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/.bongos-core.json +5727 -0
- package/.claude/skills/blocker-review/SKILL.md +91 -0
- package/.claude/skills/blocker-solve/SKILL.md +96 -0
- package/.claude/skills/builder-backup/SKILL.md +54 -0
- package/.claude/skills/builder-box/SKILL.md +45 -0
- package/.claude/skills/builder-claim/SKILL.md +76 -0
- package/.claude/skills/builder-connect/SKILL.md +59 -0
- package/.claude/skills/builder-cost/SKILL.md +47 -0
- package/.claude/skills/builder-end/SKILL.md +81 -0
- package/.claude/skills/builder-exit/SKILL.md +88 -0
- package/.claude/skills/builder-key/SKILL.md +40 -0
- package/.claude/skills/builder-reauth/SKILL.md +50 -0
- package/.claude/skills/builder-redteam/SKILL.md +109 -0
- package/.claude/skills/builder-release/SKILL.md +41 -0
- package/.claude/skills/builder-setup/SKILL.md +62 -0
- package/.claude/skills/builder-ship/SKILL.md +79 -0
- package/.claude/skills/builder-stage/SKILL.md +51 -0
- package/.claude/skills/builder-start/SKILL.md +46 -0
- package/.claude/skills/close-box/SKILL.md +43 -0
- package/.claude/skills/design-sync/SKILL.md +69 -0
- package/.claude/skills/dev/SKILL.md +49 -0
- package/.claude/skills/feedback/SKILL.md +32 -0
- package/.claude/skills/figma-design-sync/SKILL.md +74 -0
- package/.claude/skills/goal-review/SKILL.md +89 -0
- package/.claude/skills/idea-triage/SKILL.md +144 -0
- package/.claude/skills/ideate/SKILL.md +82 -0
- package/.claude/skills/merge-mode/SKILL.md +169 -0
- package/.claude/skills/new-project/SKILL.md +108 -0
- package/.claude/skills/otb-character-review/SKILL.md +71 -0
- package/.claude/skills/otb-design-review/SKILL.md +47 -0
- package/.claude/skills/otb-feedback-capture/SKILL.md +45 -0
- package/.claude/skills/otb-figma-sync/SKILL.md +54 -0
- package/.claude/skills/otb-tile-generate/SKILL.md +45 -0
- package/.claude/skills/paint/SKILL.md +70 -0
- package/.claude/skills/planning-session/SKILL.md +299 -0
- package/.claude/skills/priority-session/SKILL.md +134 -0
- package/.claude/skills/read-session-export/SKILL.md +58 -0
- package/.claude/skills/recall/SKILL.md +52 -0
- package/.claude/skills/session-handoff/SKILL.md +46 -0
- package/.claude/skills/status/SKILL.md +33 -0
- package/.devcontainer/Dockerfile +69 -0
- package/.devcontainer/README.md +73 -0
- package/.devcontainer/devcontainer-lock.json +19 -0
- package/.devcontainer/devcontainer.json +93 -0
- package/.devcontainer/healthcheck.sh +84 -0
- package/.devcontainer/init-firewall.sh +198 -0
- package/.devcontainer/post-create.sh +153 -0
- package/.dockerignore +36 -0
- package/.env.local.example +32 -0
- package/.gitattributes +83 -0
- package/.gitignore +91 -0
- package/CLAUDE.md +242 -0
- package/CODE_OF_CONDUCT.md +46 -0
- package/CONTRIBUTING.md +51 -0
- package/Dockerfile +46 -0
- package/GOVERNANCE.md +44 -0
- package/LICENSE +661 -0
- package/README.md +88 -0
- package/bin/bongos.js +222 -0
- package/clients/bongos-client/README.md +48 -0
- package/clients/bongos-client/bongos-client.global.js +617 -0
- package/clients/bongos-client/examples/hello-world.mjs +62 -0
- package/clients/bongos-client/index.cjs +619 -0
- package/clients/bongos-client/index.d.ts +793 -0
- package/clients/bongos-client/index.mjs +614 -0
- package/clients/bongos-client/package.json +32 -0
- package/config/branding.neutral.json +60 -0
- package/config/design-tokens.neutral.json +51 -0
- package/config/design-tokens.schema.json +96 -0
- package/config/modules.neutral.json +9 -0
- package/docker-compose.yml +52 -0
- package/docker-entrypoint.sh +30 -0
- package/docs/adr/0001-stack-choice-single-vps.md +45 -0
- package/docs/adr/0002-digitalocean-over-hetzner.md +27 -0
- package/docs/adr/0003-cloudflare-origin-cert-over-letsencrypt.md +35 -0
- package/docs/adr/0004-amazonprimea-name-and-trademark-acceptance.md +45 -0
- package/docs/adr/0005-invisible-other-players-in-v1.md +37 -0
- package/docs/adr/0006-singleton-worldroom-plus-queueroom.md +30 -0
- package/docs/adr/0007-persistent-identity-via-localstorage-uuid.md +31 -0
- package/docs/adr/0008-family-based-tile-generation.md +86 -0
- package/docs/adr/0008-google-chat-oauth-user-auth.md +37 -0
- package/docs/adr/0009-autotile-architecture.md +181 -0
- package/docs/adr/0010-pms-architecture.md +70 -0
- package/docs/adr/0011-terrain-id-rendering-model.md +174 -0
- package/docs/adr/0012-ground-object-cell-split.md +208 -0
- package/docs/adr/0013-paths-as-object-overlays-with-autotile-dispatch.md +158 -0
- package/docs/adr/0014-families-canonical-over-vocabulary.md +103 -0
- package/docs/adr/0015-task-dependencies-and-auto-promotion.md +125 -0
- package/docs/adr/0016-trust-boundary-server-enforced-permissions.md +132 -0
- package/docs/adr/0017-code-simplification-and-repo-cleanliness.md +74 -0
- package/docs/adr/0018-three-rank-model-goes-live.md +97 -0
- package/docs/adr/0019-red-team-bounty-payout-table.md +52 -0
- package/docs/adr/0020-security-model-public-stub.md +70 -0
- package/docs/adr/0021-per-builder-skill-model-preferences.md +99 -0
- package/docs/adr/0022-secrets-policy.md +124 -0
- package/docs/adr/0023-kind-multipliers-and-idea-bonus.md +118 -0
- package/docs/adr/0024-cloneable-repo-local-first-memory.md +277 -0
- package/docs/adr/0024-multi-agent-system-architecture.md +125 -0
- package/docs/adr/0025-offsite-backup-vendor-digitalocean-spaces.md +59 -0
- package/docs/adr/0025-structured-criterion-task-link.md +44 -0
- package/docs/adr/0026-bfg-memory-hygiene-and-cross-builder-learning.md +117 -0
- package/docs/adr/0027-bfg-session-inefficiency-evaluator.md +170 -0
- package/docs/adr/0028-honest-llm-spend-accounting.md +109 -0
- package/docs/adr/0029-status-page-outage-resilience.md +59 -0
- package/docs/adr/0030-builders-hall-live-updates.md +59 -0
- package/docs/adr/0031-cloud-dev-environments-for-builders.md +222 -0
- package/docs/adr/0032-discord-mirror-of-gds.md +50 -0
- package/docs/adr/0033-discord-bot-service-principal.md +82 -0
- package/docs/adr/0034-thetes-graduated-newcomer-rank.md +53 -0
- package/docs/adr/0035-builder-onboarding-three-paths.md +128 -0
- package/docs/adr/0036-builders-subdomain-and-ui-reorg.md +40 -0
- package/docs/adr/0037-discord-channel-management.md +51 -0
- package/docs/adr/0038-chromebook-ttyd-cloudflare-tunnel.md +111 -0
- package/docs/adr/0039-setup-first-onboarding-ux.md +49 -0
- package/docs/adr/0040-remote-control-default-browser-onramp.md +47 -0
- package/docs/adr/0041-temporary-grader-bypass-killswitch.md +40 -0
- package/docs/adr/0042-builder-self-deploy-ci-auto-merge.md +82 -0
- package/docs/adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md +74 -0
- package/docs/adr/0044-mediterranean-palette-replacement.md +73 -0
- package/docs/adr/0044-per-box-live-game-preview.md +57 -0
- package/docs/adr/0045-devbox-desktop-app.md +133 -0
- package/docs/adr/0046-sandbox-first-review-gate.md +72 -0
- package/docs/adr/0047-discord-bugs-intake-anti-abuse.md +36 -0
- package/docs/adr/0048-works-in-progress-ia-split.md +32 -0
- package/docs/adr/0049-split-parallel-safety-contract.md +46 -0
- package/docs/adr/0050-device-flow-admission-invite-gated-by-default.md +43 -0
- package/docs/adr/0051-full-session-transcript-corpus.md +57 -0
- package/docs/adr/0052-sandbox-for-everyone-game-only-preview.md +70 -0
- package/docs/adr/0053-scoped-dev-box-session.md +55 -0
- package/docs/adr/0054-session-token-reward-cost-plus.md +63 -0
- package/docs/adr/0055-server-mediated-branch-publish.md +47 -0
- package/docs/adr/0056-prod-deploy-script-mirror-and-healthcheck-retry.md +62 -0
- package/docs/adr/0057-container-cost-ledger.md +28 -0
- package/docs/adr/0057-discord-archon-approval-channels.md +64 -0
- package/docs/adr/0058-automatic-gate-surface-gatekeeper.md +64 -0
- package/docs/adr/0059-single-approval-remove-devbox-approval-gate.md +37 -0
- package/docs/adr/0060-gds-retrieval-layer.md +97 -0
- package/docs/adr/0061-context-layer-decomposition.md +61 -0
- package/docs/adr/0062-medusa-instance-model-decoupling.md +107 -0
- package/docs/adr/0063-generated-repo-map-symbol-skeleton.md +44 -0
- package/docs/adr/0064-rename-medusa-to-cloud-bongos.md +49 -0
- package/docs/adr/0065-agpl-nonprofit-ai-first-governance.md +69 -0
- package/docs/adr/0066-generated-file-map-sections.md +51 -0
- package/docs/adr/0067-session-start-fast-forward-pull.md +43 -0
- package/docs/adr/0068-shared-art-key-for-newcomers.md +38 -0
- package/docs/adr/0069-hall-live-channel-sse-decouple.md +35 -0
- package/docs/adr/0070-deterministic-session-card-delivery.md +44 -0
- package/docs/adr/0071-box-confirm-before-destroyed-and-drift-reconcile.md +59 -0
- package/docs/adr/0072-bongos-app-mac-signed-first-windows-deferred.md +35 -0
- package/docs/adr/0072-dev-box-code-staleness-visibility.md +39 -0
- package/docs/adr/0073-builder-needs-signal-and-byok-gemini-key.md +64 -0
- package/docs/adr/0073-secrets-scan-exclude-uri-detector.md +37 -0
- package/docs/adr/0074-memory-map-stays-light.md +32 -0
- package/docs/adr/0075-per-system-cost-attribution.md +37 -0
- package/docs/adr/0076-in-session-deterministic-compaction.md +58 -0
- package/docs/adr/0077-content-addressed-llm-cache.md +32 -0
- package/docs/adr/0078-deterministic-first-cron.md +48 -0
- package/docs/adr/0079-value-gated-autonomous-engagement.md +39 -0
- package/docs/adr/0080-llm-cache-api-transport-and-trust-model.md +46 -0
- package/docs/adr/0081-tool-agnostic-design-layer.md +62 -0
- package/docs/adr/0082-productized-key-storage-provisioning.md +32 -0
- package/docs/adr/0082-server-side-merge-conflict-auto-resolution.md +55 -0
- package/docs/adr/0083-modular-architecture-strangler-build-plan.md +143 -0
- package/docs/adr/0084-auto-derived-per-task-rank-floor.md +86 -0
- package/docs/adr/0085-remove-default-per-builder-spend-cap.md +39 -0
- package/docs/adr/0086-goal-scoped-work-hierarchy.md +123 -0
- package/docs/adr/0087-bongos-app-architecture-and-handoff-contract.md +49 -0
- package/docs/adr/0087-compete-on-governance-not-tooling-cursor.md +65 -0
- package/docs/adr/0088-consistent-character-generative-animation.md +169 -0
- package/docs/adr/0089-modular-multi-model-adversarial-grader.md +179 -0
- package/docs/adr/0090-metic-task-authoring.md +73 -0
- package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +106 -0
- package/docs/adr/0092-hosting-module-and-on-prem-target.md +117 -0
- package/docs/adr/0093-tranche-2-core-carve-sequence.md +72 -0
- package/docs/adr/0094-repo-atlas-self-drawing-codebase-map.md +49 -0
- package/docs/adr/0095-borrowed-memory-and-retrieval-concepts.md +65 -0
- package/docs/adr/0095-cross-agent-context-management.md +58 -0
- package/docs/adr/0096-require-reward-before-workable.md +209 -0
- package/docs/adr/0097-one-active-claim-per-session-and-worktree-binding.md +46 -0
- package/docs/adr/0097-retroactive-reward-backfill.md +124 -0
- package/docs/adr/0098-public-mirror-publish-manifest.md +92 -0
- package/docs/adr/0099-delayed-redacted-mirror-export.md +55 -0
- package/docs/adr/0100-two-repo-instance-model.md +60 -0
- package/docs/adr/0101-goal-hierarchy-phase-5-judge-membership-reward.md +90 -0
- package/docs/adr/0102-finish-bounding-the-kernel.md +36 -0
- package/docs/adr/0103-core-first-extraction-cloud-bongos-trunk.md +70 -0
- package/docs/adr/0103-gdsv4-bongos-consolidation.md +28 -0
- package/docs/adr/0104-trust-gds-api-channel-in-auto-mode.md +42 -0
- package/docs/adr/0105-instance-seed-migrations-out-of-core.md +47 -0
- package/docs/adr/0106-goal-owner-manager-authority.md +84 -0
- package/docs/adr/0107-module-upstreaming-contribution-to-core-catalog.md +83 -0
- package/docs/adr/0108-instance-composition-configurable-root.md +87 -0
- package/docs/adr/0109-self-describing-openapi-and-hosted-docs.md +44 -0
- package/docs/adr/0110-untrack-whole-file-generated-nav-docs.md +49 -0
- package/docs/adr/0111-instance-hosting-provisioning-module.md +135 -0
- package/docs/adr/0112-private-goals-invitations-join-requests.md +72 -0
- package/docs/adr/0113-sandbox-studio-descope-superseded-by-0044-0052.md +41 -0
- package/docs/adr/0114-instance-docs-discovery-contract.md +32 -0
- package/docs/adr/0115-scheduled-routines-portability.md +31 -0
- package/docs/adr/0116-api-error-envelope-and-code-taxonomy.md +62 -0
- package/docs/adr/0117-api-versioning-and-deprecation-policy.md +50 -0
- package/docs/adr/0118-api-contract-source-of-truth-code-first.md +47 -0
- package/docs/adr/0119-api-pagination-contract.md +34 -0
- package/docs/adr/0120-pay-on-land-and-builder-owned-rebase-gate.md +108 -0
- package/docs/adr/0121-greenfield-vs-brownfield-onboarding-adopt-existing-repo.md +97 -0
- package/docs/adr/0122-onboarding-diagram-renders-deploy-rendered-off-git.md +43 -0
- package/docs/adr/0123-box-idle-sweep-autosave-before-destroy.md +36 -0
- package/docs/adr/0124-typed-api-response-bodies.md +37 -0
- package/docs/adr/0125-control-plane-scaffolds-standalone-instance-repo.md +36 -0
- package/docs/adr/0126-dedicated-cloudbongos-control-plane-droplet.md +30 -0
- package/docs/adr/0127-cross-box-fleet-observability.md +64 -0
- package/docs/adr/0128-provisioning-runner-privilege-and-db-auth-model.md +46 -0
- package/docs/adr/0129-cloudbongos-control-plane-pull-deploy.md +34 -0
- package/docs/adr/0130-provision-remote-exec-over-ssh.md +61 -0
- package/docs/adr/0131-rank-scoped-skill-visibility.md +47 -0
- package/docs/adr/0132-cohost-fleet-control-plane-migration.md +54 -0
- package/docs/adr/0133-github-app-manifest-onboarding-signin.md +42 -0
- package/docs/adr/0134-private-first-npm-distribution.md +38 -0
- package/docs/adr/README.md +208 -0
- package/docs/api/openapi.json +13720 -0
- package/docs/api-reference.md +437 -0
- package/docs/architecture.md +244 -0
- package/docs/branding-contract.md +66 -0
- package/docs/branding-fill-prompt.md +25 -0
- package/docs/canonical-permissions.md +241 -0
- package/docs/design/container-exterior-tiles.md +49 -0
- package/docs/design/container-exterior.md +81 -0
- package/docs/design/container-interior.md +77 -0
- package/docs/design/modular-architecture/00-research-report.md +107 -0
- package/docs/design/modular-architecture/01-architecture.md +125 -0
- package/docs/design/modular-architecture/02-module-map.md +116 -0
- package/docs/design/modular-architecture/03-builder-flows.md +104 -0
- package/docs/design/modular-architecture/04-module-lifecycle.md +62 -0
- package/docs/design/modular-architecture/README.md +27 -0
- package/docs/design/vanilla-hall-ui-redesign-scope.md +284 -0
- package/docs/design/world-map-scroll.md +41 -0
- package/docs/design-contract.md +320 -0
- package/docs/file-map.md +418 -0
- package/docs/handoff-template.md +92 -0
- package/docs/modules-contract.md +293 -0
- package/docs/onboarding/browser-terminal-guide.md +73 -0
- package/docs/onboarding/diagrams/01-task-lifecycle.mmd +28 -0
- package/docs/onboarding/diagrams/02-rank-ladder.mmd +54 -0
- package/docs/onboarding/diagrams/03-drachmae-karma.mmd +37 -0
- package/docs/onboarding/diagrams/04-architecture.mmd +51 -0
- package/docs/onboarding/diagrams/05-versioning.mmd +29 -0
- package/docs/onboarding/diagrams/README.md +94 -0
- package/docs/onboarding/diagrams/assertions.json +170 -0
- package/docs/onboarding/diagrams/puppeteer-config.json +1 -0
- package/docs/onboarding/diagrams/render-config.json +9 -0
- package/docs/onboarding/drachmae-and-karma.md +178 -0
- package/docs/onboarding/primer.md +202 -0
- package/docs/project-context.template.md +67 -0
- package/docs/recipes/README.md +35 -0
- package/docs/recipes/audit-replay.md +100 -0
- package/docs/recipes/bongos-cli-release.md +66 -0
- package/docs/recipes/builder-box-lifecycle.md +152 -0
- package/docs/recipes/claude-design-loop.md +143 -0
- package/docs/recipes/claude-gemini-bongos-doors.md +155 -0
- package/docs/recipes/cloudbongos-staging-gate.md +139 -0
- package/docs/recipes/cloudbongos-standup.md +111 -0
- package/docs/recipes/devbox-app-release.md +93 -0
- package/docs/recipes/devbox-app-windows-test.md +128 -0
- package/docs/recipes/failed-ship-recovery-proof.md +102 -0
- package/docs/recipes/figma-design-loop.md +129 -0
- package/docs/recipes/gds-db-backup.md +255 -0
- package/docs/recipes/instance-deploy.md +37 -0
- package/docs/recipes/managed-settings-remote-control.md +416 -0
- package/docs/recipes/memory-backup.md +71 -0
- package/docs/recipes/memory-sync-conflicts.md +98 -0
- package/docs/recipes/multi-builder-merge.md +78 -0
- package/docs/recipes/ops-gotchas.md +212 -0
- package/docs/recipes/overnight-builder.md +53 -0
- package/docs/recipes/packaging-the-core.md +49 -0
- package/docs/recipes/parallel-load-results-2026-05-30.md +63 -0
- package/docs/recipes/parallel-load-test.md +32 -0
- package/docs/recipes/pixel-art-pipeline.md +411 -0
- package/docs/recipes/private-npm-distribution.md +79 -0
- package/docs/recipes/search-index-ingestion.md +67 -0
- package/docs/recipes/self-host.md +60 -0
- package/docs/recipes/ship-and-regrade.md +72 -0
- package/docs/recipes/staging-data.md +50 -0
- package/docs/recipes/staging-environment.md +215 -0
- package/docs/recipes/upgrading-the-core.md +58 -0
- package/docs/research/cursor-competitive-analysis.md +255 -0
- package/docs/research/llm-model-agnostic-and-cheaper-grader.md +227 -0
- package/migrations/003_pms.sql +284 -0
- package/migrations/004_pms_cost_idempotency.sql +13 -0
- package/migrations/005_pms_smoke_filter.sql +44 -0
- package/migrations/006_pms_v2.sql +378 -0
- package/migrations/007_pms_v2_hierarchy_trigger.sql +59 -0
- package/migrations/008_pms_v2_migration_allocator.sql +27 -0
- package/migrations/009_pms_v2_blockers_table.sql +68 -0
- package/migrations/010_uptime.sql +29 -0
- package/migrations/011_backfill_v2_v3_done_when.sql +20 -0
- package/migrations/012_pms_v2_task_lifecycle_states.sql +82 -0
- package/migrations/013_claim_locking.sql +22 -0
- package/migrations/014_pms_task_discipline.sql +86 -0
- package/migrations/015_pms_estimation_calibration.sql +140 -0
- package/migrations/016_pms_task_grades.sql +60 -0
- package/migrations/017_version_progress_exclude_abandoned.sql +49 -0
- package/migrations/019_rename_pms_v3_to_gds_v3.sql +65 -0
- package/migrations/020_task_dependencies.sql +99 -0
- package/migrations/021_v3_renumber_and_deps.sql +224 -0
- package/migrations/022_v3_reconcile_dep_gated_status.sql +41 -0
- package/migrations/023_pms_rank.sql +30 -0
- package/migrations/025_builder_exit_status.sql +15 -0
- package/migrations/027_builders_preferred_disciplines.sql +46 -0
- package/migrations/028_tasks_parallel_safe.sql +71 -0
- package/migrations/029_rank_three_live.sql +32 -0
- package/migrations/030_vulnerability_reports.sql +61 -0
- package/migrations/031_reward_simplification.sql +57 -0
- package/migrations/032_repo_health_snapshots.sql +56 -0
- package/migrations/033_audit_log.sql +64 -0
- package/migrations/034_lifecycle_breakdown_leaf_only.sql +62 -0
- package/migrations/035_auth_token_hygiene.sql +66 -0
- package/migrations/037_builder_skill_model_prefs.sql +44 -0
- package/migrations/038_task_override_requests.sql +51 -0
- package/migrations/039_newcomer_friendly_column.sql +124 -0
- package/migrations/040_builder_karma.sql +58 -0
- package/migrations/041_kind_multipliers_and_idea_bonus.sql +42 -0
- package/migrations/042_criterion_proposal_workflow.sql +78 -0
- package/migrations/043_builder_onboarding_observability.sql +66 -0
- package/migrations/044_tasks_requires_rank.sql +97 -0
- package/migrations/045_builder_onboarding_state.sql +147 -0
- package/migrations/046_cost_log_builder_attribution.sql +42 -0
- package/migrations/054_builder_memory.sql +108 -0
- package/migrations/055_task_criteria.sql +90 -0
- package/migrations/058_peer_votes.sql +41 -0
- package/migrations/059_onboarding_pick_disciplines.sql +59 -0
- package/migrations/060_access_requests.sql +46 -0
- package/migrations/061_backfill_override_ship_attribution.sql +29 -0
- package/migrations/062_session_records.sql +34 -0
- package/migrations/063_session_records_tool_errors_idx.sql +11 -0
- package/migrations/064_grade_attempts.sql +18 -0
- package/migrations/065_bfg_principal.sql +58 -0
- package/migrations/066_live_notify_triggers.sql +69 -0
- package/migrations/067_builder_boxes.sql +117 -0
- package/migrations/067_discord_bot_foundation.sql +69 -0
- package/migrations/068_thetes_requires_rank.sql +27 -0
- package/migrations/069_builder_ssh_keys.sql +66 -0
- package/migrations/070_box_intents.sql +101 -0
- package/migrations/071_box_first_provision_approval.sql +46 -0
- package/migrations/072_onboarding_ship_three_remove_primer.sql +80 -0
- package/migrations/073_box_terminal_access.sql +46 -0
- package/migrations/075_builder_sound_prefs.sql +28 -0
- package/migrations/078_box_claude_active.sql +22 -0
- package/migrations/079_box_first_connected_at.sql +20 -0
- package/migrations/081_tasks_needs_migration.sql +34 -0
- package/migrations/084_tasks_security_sensitive.sql +24 -0
- package/migrations/085_security_engagement_docs.sql +34 -0
- package/migrations/086_rename_disciplines.sql +125 -0
- package/migrations/088_builders_anthropic_link.sql +28 -0
- package/migrations/089_builders_monthly_budget.sql +19 -0
- package/migrations/090_box_scoped_sessions.sql +38 -0
- package/migrations/091_session_token_reward.sql +44 -0
- package/migrations/093_tasks_sandbox_review.sql +22 -0
- package/migrations/102_remove_box_first_provision_approval.sql +58 -0
- package/migrations/103_search_chunks.sql +90 -0
- package/migrations/104_builder_box_blocked.sql +34 -0
- package/migrations/105_box_host_keys.sql +35 -0
- package/migrations/111_medusa_customer0_framing.sql +35 -0
- package/migrations/112_drop_track_check.sql +25 -0
- package/migrations/113_merge_lease.sql +16 -0
- package/migrations/114_cloudbongos_rename_live_strings.sql +32 -0
- package/migrations/118_currency_label_decoupling.sql +23 -0
- package/migrations/119_builder_behavior_prefs.sql +31 -0
- package/migrations/121_box_code_version.sql +37 -0
- package/migrations/122_builder_gemini_key.sql +30 -0
- package/migrations/123_cost_log_tiers.sql +33 -0
- package/migrations/124_cost_baseline.sql +45 -0
- package/migrations/125_llm_cache.sql +54 -0
- package/migrations/126_autonomy_runs.sql +33 -0
- package/migrations/143_cost_calibration.sql +63 -0
- package/migrations/145_backfill_task_requires_rank.sql +84 -0
- package/migrations/160_goal_tier.sql +88 -0
- package/migrations/163_polymorphic_dependencies.sql +187 -0
- package/migrations/164_event_sound_prefs.sql +20 -0
- package/migrations/165_task_module_key.sql +15 -0
- package/migrations/171_claims_published_head_sha.sql +24 -0
- package/migrations/174_close_orphaned_claims_on_terminal_tasks.sql +30 -0
- package/migrations/175_task_grades_diff_hash.sql +9 -0
- package/migrations/176_promotion_respects_open_blockers.sql +58 -0
- package/migrations/176_ui_discipline.sql +40 -0
- package/migrations/177_require_reward_before_workable.sql +76 -0
- package/migrations/178_reward_gate_auto_assign_revert_autopromote.sql +61 -0
- package/migrations/179_search_chunk_usefulness.sql +33 -0
- package/migrations/180_one_active_claim_per_session.sql +54 -0
- package/migrations/181_cost_log_skill_name.sql +33 -0
- package/migrations/184_claim_release_requested.sql +25 -0
- package/migrations/185_module_upstreaming_goal_wiring.sql +59 -0
- package/migrations/187_goal_sort_order.sql +30 -0
- package/migrations/187_tasks_kind_check_add_verify.sql +21 -0
- package/migrations/README.md +88 -0
- package/migrations/core_188_goal_visibility_and_membership_requests.sql +71 -0
- package/migrations/core_189_core_upgrades_ledger.sql +37 -0
- package/migrations/core_189_credit_log_task_id_index.sql +19 -0
- package/migrations/core_190_rebuild_claimable_task_views.sql +71 -0
- package/migrations/instance/018_pms_v3_planning_seed.sql +131 -0
- package/migrations/instance/080_gds_v4_planning_seed.sql +75 -0
- package/migrations/instance/110_medusa_planning_seed.sql +70 -0
- package/migrations/instance/120_bongos_v1_planning_seed.sql +69 -0
- package/migrations/instance/144_bongos_v1_module_system_criterion.sql +26 -0
- package/migrations/instance/159_bongos_v1_goal_hierarchy_criterion.sql +29 -0
- package/migrations/instance/172_v2_world_planning_seed.sql +163 -0
- package/migrations/instance/173_bongos_v1_c7_core_modularized.sql +33 -0
- package/migrations/instance/182_gdsv4_bongos_consolidation.sql +132 -0
- package/migrations/instance/183_gdsv4_carryover_themed_goals.sql +116 -0
- package/migrations/instance/186_bongos_v1_governance_planning_seed.sql +69 -0
- package/modules/autonomy/CLAUDE.md +49 -0
- package/modules/autonomy/db.js +50 -0
- package/modules/autonomy/module.json +13 -0
- package/modules/autonomy/pollers/routine-timers.js +146 -0
- package/modules/autonomy/routes/autonomy.js +37 -0
- package/modules/builder-settings/CLAUDE.md +58 -0
- package/modules/builder-settings/builder-needs.js +115 -0
- package/modules/builder-settings/db.js +168 -0
- package/modules/builder-settings/display-name.js +84 -0
- package/modules/builder-settings/event-sound-prefs.js +169 -0
- package/modules/builder-settings/interaction-prefs.js +201 -0
- package/modules/builder-settings/model-alloc-prefs.js +147 -0
- package/modules/builder-settings/module.json +10 -0
- package/modules/builder-settings/render-prefs.js +103 -0
- package/modules/builder-settings/routes/settings.js +417 -0
- package/modules/builder-settings/settings.js +52 -0
- package/modules/builder-settings/skill-prefs.js +196 -0
- package/modules/builder-settings/sound-prefs.js +178 -0
- package/modules/builder-settings/wandering-prefs.js +282 -0
- package/modules/dev-box/CLAUDE.md +38 -0
- package/modules/dev-box/box-access.js +275 -0
- package/modules/dev-box/box-credential.js +94 -0
- package/modules/dev-box/box-onboard.js +486 -0
- package/modules/dev-box/boxes.js +842 -0
- package/modules/dev-box/db.js +39 -0
- package/modules/dev-box/module.json +14 -0
- package/modules/dev-box/routes/box.js +977 -0
- package/modules/discord/CLAUDE.md +50 -0
- package/modules/discord/auth.js +54 -0
- package/modules/discord/bug-attachments.js +210 -0
- package/modules/discord/db.js +96 -0
- package/modules/discord/discord-approvals.js +145 -0
- package/modules/discord/discord-audit.js +29 -0
- package/modules/discord/discord-bot.js +545 -0
- package/modules/discord/discord-bugs.js +257 -0
- package/modules/discord/discord-channels.js +412 -0
- package/modules/discord/discord-inbound.js +147 -0
- package/modules/discord/discord-message-buffer.js +54 -0
- package/modules/discord/discord-reaction.js +186 -0
- package/modules/discord/discord-role-sync.js +318 -0
- package/modules/discord/module.json +14 -0
- package/modules/discord/pollers/discord-bot.js +19 -0
- package/modules/discord/routes/bug-attachments.js +44 -0
- package/modules/discord/routes/discord.js +102 -0
- package/modules/discord/ship-broadcast.js +78 -0
- package/modules/discord/webhook.js +74 -0
- package/modules/economy/CLAUDE.md +48 -0
- package/modules/economy/achievements.js +594 -0
- package/modules/economy/cost-classify.js +331 -0
- package/modules/economy/cost-summary-shape.js +90 -0
- package/modules/economy/cost.js +438 -0
- package/modules/economy/credits.js +430 -0
- package/modules/economy/migrations/economy_001_fix_gds_shipper_description.sql +91 -0
- package/modules/economy/module.json +10 -0
- package/modules/economy/reward.js +61 -0
- package/modules/economy/routes/cost.js +97 -0
- package/modules/economy/routes/leaderboard.js +26 -0
- package/modules/economy/routes/reward.js +42 -0
- package/modules/economy/streak.js +285 -0
- package/modules/grading/CLAUDE.md +42 -0
- package/modules/grading/db.js +39 -0
- package/modules/grading/grader-rubric.json +151 -0
- package/modules/grading/grader-workers/efficiency.js +213 -0
- package/modules/grading/grader-workers/extract-json.js +80 -0
- package/modules/grading/grader-workers/fence.js +100 -0
- package/modules/grading/grader-workers/hacker.js +239 -0
- package/modules/grading/grader-workers/index.js +183 -0
- package/modules/grading/grader-workers/narc.js +207 -0
- package/modules/grading/grader-workers/quality.js +198 -0
- package/modules/grading/grader-workers/rubric.js +20 -0
- package/modules/grading/grader-workers/worker-prompt.js +89 -0
- package/modules/grading/grader-workers/worker-verdict.js +50 -0
- package/modules/grading/grader.js +1790 -0
- package/modules/grading/module.json +12 -0
- package/modules/grading/routes/grade.js +51 -0
- package/modules/hall-ui/CLAUDE.md +61 -0
- package/modules/hall-ui/module.json +14 -0
- package/modules/hall-ui/public/atlas.html +180 -0
- package/modules/hall-ui/public/atlas.js +336 -0
- package/modules/hall-ui/public/box-panel.js +423 -0
- package/modules/hall-ui/public/brand-apply.js +117 -0
- package/modules/hall-ui/public/builders.js +3028 -0
- package/modules/hall-ui/public/chime.wav +0 -0
- package/modules/hall-ui/public/copy-on-click.js +174 -0
- package/modules/hall-ui/public/cursors/arrow.png +0 -0
- package/modules/hall-ui/public/cursors/hand-pointer.png +0 -0
- package/modules/hall-ui/public/cursors/magnifier-out.png +0 -0
- package/modules/hall-ui/public/cursors/magnifier.png +0 -0
- package/modules/hall-ui/public/diagram-viewer.css +125 -0
- package/modules/hall-ui/public/diagram-viewer.js +330 -0
- package/modules/hall-ui/public/diagrams.html +113 -0
- package/modules/hall-ui/public/dom-utils.js +212 -0
- package/modules/hall-ui/public/drachmae.html +68 -0
- package/modules/hall-ui/public/drachmae.js +136 -0
- package/modules/hall-ui/public/gate.html +143 -0
- package/modules/hall-ui/public/gate.js +228 -0
- package/modules/hall-ui/public/goals-page.js +1297 -0
- package/modules/hall-ui/public/goals.html +376 -0
- package/modules/hall-ui/public/goals.js +119 -0
- package/modules/hall-ui/public/hall-widgets.js +189 -0
- package/modules/hall-ui/public/harbor.html +167 -0
- package/modules/hall-ui/public/harbor.js +335 -0
- package/modules/hall-ui/public/index.html +116 -0
- package/modules/hall-ui/public/instances-panel.js +172 -0
- package/modules/hall-ui/public/md-reader.js +234 -0
- package/modules/hall-ui/public/modules.html +119 -0
- package/modules/hall-ui/public/modules.js +154 -0
- package/modules/hall-ui/public/new-project-wizard.js +186 -0
- package/modules/hall-ui/public/not-ready.html +48 -0
- package/modules/hall-ui/public/pair.html +119 -0
- package/modules/hall-ui/public/pair.js +132 -0
- package/modules/hall-ui/public/primer.css +404 -0
- package/modules/hall-ui/public/primer.html +85 -0
- package/modules/hall-ui/public/primer.js +641 -0
- package/modules/hall-ui/public/profile.html +85 -0
- package/modules/hall-ui/public/profile.js +236 -0
- package/modules/hall-ui/public/ranks.html +69 -0
- package/modules/hall-ui/public/ranks.js +206 -0
- package/modules/hall-ui/public/roadmap.html +209 -0
- package/modules/hall-ui/public/roadmap.js +375 -0
- package/modules/hall-ui/public/sessions.html +92 -0
- package/modules/hall-ui/public/sessions.js +222 -0
- package/modules/hall-ui/public/settings.html +640 -0
- package/modules/hall-ui/public/settings.js +1219 -0
- package/modules/hall-ui/public/shell.js +495 -0
- package/modules/hall-ui/public/style.css +1748 -0
- package/modules/hall-ui/public/task-detail.js +253 -0
- package/modules/hall-ui/public/task.html +83 -0
- package/modules/hall-ui/public/task.js +326 -0
- package/modules/hall-ui/public/watch.html +333 -0
- package/modules/hall-ui/public/watch.js +859 -0
- package/modules/hall-ui/public/work.html +469 -0
- package/modules/hall-ui/public/work.js +1292 -0
- package/modules/ideas/CLAUDE.md +37 -0
- package/modules/ideas/blockers.js +100 -0
- package/modules/ideas/inbox.js +459 -0
- package/modules/ideas/module.json +10 -0
- package/modules/ideas/routes/blockers.js +120 -0
- package/modules/ideas/routes/inbox.js +230 -0
- package/modules/lifecycle/CLAUDE.md +63 -0
- package/modules/lifecycle/conflict-resolve.js +436 -0
- package/modules/lifecycle/db.js +4970 -0
- package/modules/lifecycle/done-when.js +355 -0
- package/modules/lifecycle/github-push.js +969 -0
- package/modules/lifecycle/goal-conflicts.js +133 -0
- package/modules/lifecycle/hierarchy.js +104 -0
- package/modules/lifecycle/lifecycle.js +58 -0
- package/modules/lifecycle/merge-lock.js +261 -0
- package/modules/lifecycle/migrations/lifecycle_001_goal_first_leads.sql +28 -0
- package/modules/lifecycle/migrations/lifecycle_002_backfill_orphan_task_goals.sql +36 -0
- package/modules/lifecycle/module.json +13 -0
- package/modules/lifecycle/pollers/publish-reconciler.js +20 -0
- package/modules/lifecycle/publish-reconciler.js +418 -0
- package/modules/lifecycle/routes/analytics.js +63 -0
- package/modules/lifecycle/routes/claims.js +506 -0
- package/modules/lifecycle/routes/dependencies.js +82 -0
- package/modules/lifecycle/routes/done-when.js +136 -0
- package/modules/lifecycle/routes/gate-approvals.js +197 -0
- package/modules/lifecycle/routes/goals.js +1419 -0
- package/modules/lifecycle/routes/lifecycle.js +43 -0
- package/modules/lifecycle/routes/tasks.js +1703 -0
- package/modules/lifecycle/routes/versions.js +128 -0
- package/modules/lifecycle/ship-card.js +505 -0
- package/modules/lifecycle/ship-preflight.js +225 -0
- package/modules/lifecycle/task-classifier.js +512 -0
- package/modules/lifecycle/version-close.js +106 -0
- package/modules/memory/CLAUDE.md +40 -0
- package/modules/memory/learnings.js +275 -0
- package/modules/memory/memory.js +572 -0
- package/modules/memory/module.json +12 -0
- package/modules/memory/routes/learnings.js +90 -0
- package/modules/memory/routes/memory.js +916 -0
- package/modules/memory/routes/search.js +188 -0
- package/modules/memory/search-chunker.js +252 -0
- package/modules/memory/search.js +320 -0
- package/modules/onboarding/CLAUDE.md +55 -0
- package/modules/onboarding/approval-broadcast.js +59 -0
- package/modules/onboarding/db.js +54 -0
- package/modules/onboarding/module.json +10 -0
- package/modules/onboarding/newcomer-restock.js +212 -0
- package/modules/onboarding/onboarding-state.js +532 -0
- package/modules/onboarding/onboarding.js +508 -0
- package/modules/onboarding/port.js +63 -0
- package/modules/onboarding/routes/access-requests.js +208 -0
- package/modules/onboarding/routes/onboarding.js +54 -0
- package/modules/security/CLAUDE.md +44 -0
- package/modules/security/module.json +10 -0
- package/modules/security/routes/reports.js +251 -0
- package/modules/security/secret-scrub.js +201 -0
- package/modules/security/security.js +294 -0
- package/modules/sessions/CLAUDE.md +39 -0
- package/modules/sessions/bfg.js +357 -0
- package/modules/sessions/db.js +326 -0
- package/modules/sessions/module.json +10 -0
- package/modules/sessions/pulse.js +149 -0
- package/modules/sessions/routes/sessions.js +331 -0
- package/modules/status-ui/CLAUDE.md +47 -0
- package/modules/status-ui/module.json +14 -0
- package/modules/status-ui/public/README.md +29 -0
- package/modules/status-ui/public/cursors/arrow.png +0 -0
- package/modules/status-ui/public/cursors/hand-pointer.png +0 -0
- package/modules/status-ui/public/index.html +363 -0
- package/modules/status-ui/public/snapshots/.gitkeep +0 -0
- package/modules/status-ui/public/status.js +1375 -0
- package/modules/status-ui/public/style.css +1342 -0
- package/package-lock.json +975 -0
- package/package.json +28 -0
- package/public-docs/index.html +35 -0
- package/public-docs/redoc.standalone.js +1838 -0
- package/public-docs/redoc.standalone.js.LICENSE.txt +102 -0
- package/public-landing/buddha.png +0 -0
- package/public-landing/create.html +868 -0
- package/public-landing/index.html +168 -0
- package/scripts/bongos-mcp.js +28 -0
- package/scripts/cron/style_guide_audit.sh +134 -0
- package/scripts/discord/README.md +52 -0
- package/scripts/discord/lib.js +80 -0
- package/scripts/discord/post.js +51 -0
- package/scripts/gds/CLAUDE.md +144 -0
- package/scripts/gds/abandon.js +58 -0
- package/scripts/gds/adopt-detect.js +123 -0
- package/scripts/gds/adopt-import.js +111 -0
- package/scripts/gds/adopt-preflight.js +121 -0
- package/scripts/gds/api.js +78 -0
- package/scripts/gds/architect-audit.js +288 -0
- package/scripts/gds/art-stage.js +152 -0
- package/scripts/gds/audit-authorship.sh +243 -0
- package/scripts/gds/audit-deps.js +121 -0
- package/scripts/gds/audit-exports.js +128 -0
- package/scripts/gds/audit-replay.sh +161 -0
- package/scripts/gds/audit-ships.js +251 -0
- package/scripts/gds/autonomy-gate.js +135 -0
- package/scripts/gds/backfill-cost.js +165 -0
- package/scripts/gds/backfill-sessions.js +351 -0
- package/scripts/gds/backfill-task-rewards.js +408 -0
- package/scripts/gds/backup.js +94 -0
- package/scripts/gds/bfg-principal-token.js +65 -0
- package/scripts/gds/box-auth-check.js +160 -0
- package/scripts/gds/box-connect-lib.js +453 -0
- package/scripts/gds/box.js +1258 -0
- package/scripts/gds/build-bongos.js +94 -0
- package/scripts/gds/capture.js +123 -0
- package/scripts/gds/cf-tunnel.js +419 -0
- package/scripts/gds/ci-grade.js +82 -0
- package/scripts/gds/claim-recall.js +112 -0
- package/scripts/gds/claim.js +333 -0
- package/scripts/gds/classify-discipline.js +153 -0
- package/scripts/gds/claude-materialize.js +176 -0
- package/scripts/gds/cleanup-orphans.js +74 -0
- package/scripts/gds/cli-lib.js +518 -0
- package/scripts/gds/code.js +101 -0
- package/scripts/gds/codemod-rename-src-gds.js +145 -0
- package/scripts/gds/conductor-dispatch.js +426 -0
- package/scripts/gds/context-pack.js +228 -0
- package/scripts/gds/coreB-carve-proof.sh +716 -0
- package/scripts/gds/cost.js +47 -0
- package/scripts/gds/db-backup-nightly.sh +160 -0
- package/scripts/gds/db-backup-offsite.sh +152 -0
- package/scripts/gds/demote.js +40 -0
- package/scripts/gds/design-sync.js +62 -0
- package/scripts/gds/diagnose-achievements.js +118 -0
- package/scripts/gds/diagram-facts.js +319 -0
- package/scripts/gds/discipline-modes.json +25 -0
- package/scripts/gds/discord-channels.js +66 -0
- package/scripts/gds/do-api.js +176 -0
- package/scripts/gds/docs-entropy.js +403 -0
- package/scripts/gds/doctor.js +389 -0
- package/scripts/gds/feedback-latest.js +94 -0
- package/scripts/gds/fetch-art-key.js +106 -0
- package/scripts/gds/fetch-sound-prefs.js +88 -0
- package/scripts/gds/figma-design-sync.js +61 -0
- package/scripts/gds/fitness.js +1446 -0
- package/scripts/gds/gate-review.js +322 -0
- package/scripts/gds/gating.js +325 -0
- package/scripts/gds/gds-db-backup.service +24 -0
- package/scripts/gds/gds-db-backup.timer +20 -0
- package/scripts/gds/gds-db-offsite.service +29 -0
- package/scripts/gds/gds-db-offsite.timer +18 -0
- package/scripts/gds/gen-api-client.js +508 -0
- package/scripts/gds/gen-api-docs.js +1037 -0
- package/scripts/gds/gen-atlas.js +366 -0
- package/scripts/gds/gen-diagrams.js +608 -0
- package/scripts/gds/gen-file-map.js +196 -0
- package/scripts/gds/gen-repo-map.js +519 -0
- package/scripts/gds/gen-session-index.js +210 -0
- package/scripts/gds/git-merge-regen.js +147 -0
- package/scripts/gds/grade-smoke.js +205 -0
- package/scripts/gds/hooks/pre-push.js +169 -0
- package/scripts/gds/http-api-client.js +88 -0
- package/scripts/gds/init.js +903 -0
- package/scripts/gds/install-git-hooks.js +114 -0
- package/scripts/gds/key-card.js +213 -0
- package/scripts/gds/key-status.js +126 -0
- package/scripts/gds/land-watch.js +168 -0
- package/scripts/gds/learning-capture.js +145 -0
- package/scripts/gds/lib.sh +44 -0
- package/scripts/gds/linkify-refs.js +473 -0
- package/scripts/gds/local-preview-lib.js +159 -0
- package/scripts/gds/local-preview.js +95 -0
- package/scripts/gds/login.js +225 -0
- package/scripts/gds/main-audit.js +279 -0
- package/scripts/gds/me.js +88 -0
- package/scripts/gds/memory-map.js +174 -0
- package/scripts/gds/merge-lock.js +71 -0
- package/scripts/gds/migration-namespace.js +200 -0
- package/scripts/gds/mirror-lineage-check.js +319 -0
- package/scripts/gds/mirror-redact.js +305 -0
- package/scripts/gds/module.js +482 -0
- package/scripts/gds/newcomer-floor.config.json +13 -0
- package/scripts/gds/newcomer-floor.js +415 -0
- package/scripts/gds/newcomer-floor.templates.json +86 -0
- package/scripts/gds/newcomer-floor.test.js +235 -0
- package/scripts/gds/next-number.js +163 -0
- package/scripts/gds/oauth-secret.js +197 -0
- package/scripts/gds/onboard.js +217 -0
- package/scripts/gds/onboarding-analyze.js +226 -0
- package/scripts/gds/onboarding-config.js +178 -0
- package/scripts/gds/onboarding-ship.js +92 -0
- package/scripts/gds/package-core.js +684 -0
- package/scripts/gds/paste-token.js +131 -0
- package/scripts/gds/portability-smoke-art.sh +85 -0
- package/scripts/gds/portability-smoke-memory.sh +147 -0
- package/scripts/gds/provision.js +1324 -0
- package/scripts/gds/publish-manifest.js +307 -0
- package/scripts/gds/pulse.js +309 -0
- package/scripts/gds/push-main.js +45 -0
- package/scripts/gds/read-session-export.js +359 -0
- package/scripts/gds/reauth.js +149 -0
- package/scripts/gds/recall.js +135 -0
- package/scripts/gds/release.js +71 -0
- package/scripts/gds/render-ideas.js +173 -0
- package/scripts/gds/repo-metrics.js +363 -0
- package/scripts/gds/resolve-skill-model.js +57 -0
- package/scripts/gds/run-routine.js +197 -0
- package/scripts/gds/run-unit-tests.js +178 -0
- package/scripts/gds/sandbox-stage.js +653 -0
- package/scripts/gds/search-ingest-db.js +209 -0
- package/scripts/gds/search-ingest-md.js +225 -0
- package/scripts/gds/security-baseline-check.sh +180 -0
- package/scripts/gds/seed-adopt-tasks.js +75 -0
- package/scripts/gds/seed-api-contract-goal-tasks.js +141 -0
- package/scripts/gds/seed-bongos-app-tasks.js +294 -0
- package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +81 -0
- package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +100 -0
- package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +307 -0
- package/scripts/gds/seed-bongos-module-system-tasks.js +346 -0
- package/scripts/gds/seed-bongos-tasks.js +214 -0
- package/scripts/gds/seed-gds-v4-tasks.js +624 -0
- package/scripts/gds/seed-governance-tasks.js +340 -0
- package/scripts/gds/seed-medusa-tasks.js +440 -0
- package/scripts/gds/seed-module-upstreaming.js +219 -0
- package/scripts/gds/seed-productization-tasks.js +235 -0
- package/scripts/gds/seed-provisioning-tasks.js +83 -0
- package/scripts/gds/seed-staging.sh +104 -0
- package/scripts/gds/seed-v2-world-tasks.js +283 -0
- package/scripts/gds/seed-v3-tasks.js +1981 -0
- package/scripts/gds/session-cost.js +393 -0
- package/scripts/gds/session-digest.js +179 -0
- package/scripts/gds/session-eval.js +576 -0
- package/scripts/gds/session.js +404 -0
- package/scripts/gds/setup.js +504 -0
- package/scripts/gds/shell.js +100 -0
- package/scripts/gds/ship.js +3618 -0
- package/scripts/gds/smoke-batch-claim.sh +213 -0
- package/scripts/gds/smoke-batch-release.sh +296 -0
- package/scripts/gds/smoke-box.sh +150 -0
- package/scripts/gds/smoke-claim-consistency.sh +212 -0
- package/scripts/gds/smoke-dependencies.sh +84 -0
- package/scripts/gds/smoke-gds.js +125 -0
- package/scripts/gds/smoke-write.sh +168 -0
- package/scripts/gds/start.js +782 -0
- package/scripts/gds/status.js +365 -0
- package/scripts/gds/triage.js +366 -0
- package/scripts/gds/upgrade.js +421 -0
- package/scripts/gds/validate-design.js +254 -0
- package/scripts/gds/version-close.js +549 -0
- package/scripts/migrate.sh +183 -0
- package/scripts/migrate_cost_ledger.sh +178 -0
- package/scripts/public-mirror-export.js +291 -0
- package/scripts/render-diagrams.sh +88 -0
- package/scripts/security/dep-audit.js +276 -0
- package/scripts/setup-builder.js +274 -0
- package/scripts/setup-builder.sh +28 -0
- package/scripts/snapshots/backfill-history.mjs +292 -0
- package/scripts/snapshots/maybe-render-on-deploy.sh +66 -0
- package/scripts/snapshots/render-pre-art-eras.mjs +329 -0
- package/scripts/snapshots/render-world.mjs +322 -0
- package/scripts/status-mirror-sync.js +192 -0
- package/scripts/status-probe.mjs +185 -0
- package/server.js +212 -0
- package/src/asset-version.js +71 -0
- package/src/bongos/CLAUDE.md +64 -0
- package/src/bongos/api-errors.js +281 -0
- package/src/bongos/api-path-404.js +67 -0
- package/src/bongos/api-prefix.js +38 -0
- package/src/bongos/app-pair.js +172 -0
- package/src/bongos/auth.js +979 -0
- package/src/bongos/cascade-dispatch.js +123 -0
- package/src/bongos/db-kernel.js +252 -0
- package/src/bongos/db.js +911 -0
- package/src/bongos/goal-scope-check.js +120 -0
- package/src/bongos/hierarchy-config.js +189 -0
- package/src/bongos/live-channel.js +145 -0
- package/src/bongos/llm-cache.js +260 -0
- package/src/bongos/llm-pricing.js +220 -0
- package/src/bongos/metrics.js +286 -0
- package/src/bongos/middleware/audit.js +274 -0
- package/src/bongos/middleware/error-envelope.js +93 -0
- package/src/bongos/middleware/rate-limit.js +195 -0
- package/src/bongos/module-scope-map.js +271 -0
- package/src/bongos/optimizer.js +166 -0
- package/src/bongos/path-match.js +47 -0
- package/src/bongos/permission-path-check.js +248 -0
- package/src/bongos/pool.js +55 -0
- package/src/bongos/repo-info.js +91 -0
- package/src/bongos/route-rank-check.js +420 -0
- package/src/bongos/routes/CLAUDE.md +43 -0
- package/src/bongos/routes/_helpers.js +369 -0
- package/src/bongos/routes/audit-log.js +59 -0
- package/src/bongos/routes/auth.js +755 -0
- package/src/bongos/routes/backup.js +104 -0
- package/src/bongos/routes/builders.js +526 -0
- package/src/bongos/routes/healthz.js +16 -0
- package/src/bongos/routes/instance.js +129 -0
- package/src/bongos/routes/live.js +125 -0
- package/src/bongos/routes/llm-cache.js +119 -0
- package/src/bongos/routes/me.js +380 -0
- package/src/bongos/routes/modules.js +131 -0
- package/src/bongos/routes/optimizer.js +54 -0
- package/src/bongos/routes/public.js +476 -0
- package/src/bongos/routes/security.js +207 -0
- package/src/bongos/routes.js +166 -0
- package/src/bongos/secret-box.js +177 -0
- package/src/bongos/sensitive-surfaces.js +30 -0
- package/src/bongos/serve-internal.js +889 -0
- package/src/bongos/uptime-poller.js +90 -0
- package/src/bongos-downloads.js +70 -0
- package/src/branding.js +182 -0
- package/src/build-info.js +77 -0
- package/src/devbox-downloads.js +67 -0
- package/src/instance-config.js +200 -0
- package/src/module-api.js +366 -0
- package/src/module-loader/loader.js +268 -0
- package/src/module-loader/manifest-schema.js +140 -0
- package/src/module-loader/provenance.js +28 -0
- package/src/module-loader/semver.js +100 -0
- package/src/module-seams.js +291 -0
- package/src/modules.js +254 -0
- package/src/platform-server.js +135 -0
- package/src/ui/adapters/claude-design/index.js +333 -0
- package/src/ui/adapters/figma/index.js +328 -0
- package/tests/abandon_task.mjs +138 -0
- package/tests/achievements_reconcile.mjs +167 -0
- package/tests/adopt_detect.mjs +141 -0
- package/tests/adopt_import.mjs +132 -0
- package/tests/adopt_preflight.mjs +105 -0
- package/tests/anti_grid.mjs +89 -0
- package/tests/api_client.mjs +231 -0
- package/tests/api_docs.mjs +283 -0
- package/tests/api_error_envelope_buildcheck.mjs +56 -0
- package/tests/api_error_envelope_middleware.mjs +99 -0
- package/tests/api_error_registry.mjs +108 -0
- package/tests/api_pagination_contract.mjs +51 -0
- package/tests/api_path_404.mjs +96 -0
- package/tests/app_pair.mjs +168 -0
- package/tests/architect.mjs +140 -0
- package/tests/art_key.mjs +121 -0
- package/tests/art_stage.mjs +121 -0
- package/tests/asset_version.mjs +94 -0
- package/tests/atlas.mjs +69 -0
- package/tests/audit_deps.mjs +74 -0
- package/tests/audit_middleware.mjs +385 -0
- package/tests/auth_admission_gate.mjs +164 -0
- package/tests/auth_anthropic_identity.mjs +95 -0
- package/tests/auth_duplicate_cookie.mjs +56 -0
- package/tests/auth_error_brand.mjs +77 -0
- package/tests/auth_flow_slice1.mjs +223 -0
- package/tests/auth_inactive_builder.mjs +94 -0
- package/tests/auth_page_gate.mjs +92 -0
- package/tests/auth_session_ttl.mjs +155 -0
- package/tests/autonomous_fit_protected_paths.mjs +115 -0
- package/tests/autonomy_gate.mjs +85 -0
- package/tests/autotile_variants.mjs +256 -0
- package/tests/autotile_xverify.mjs +133 -0
- package/tests/backfill_sessions.mjs +101 -0
- package/tests/backfill_task_rewards.mjs +152 -0
- package/tests/backup_cli.mjs +104 -0
- package/tests/bfg.mjs +327 -0
- package/tests/bfg_write.mjs +423 -0
- package/tests/bongos_box_connect.mjs +89 -0
- package/tests/bongos_dispatch.mjs +74 -0
- package/tests/bongos_downloads.mjs +118 -0
- package/tests/bongos_login.mjs +34 -0
- package/tests/box_access.mjs +186 -0
- package/tests/box_auth_check.mjs +114 -0
- package/tests/box_code_staleness.mjs +116 -0
- package/tests/box_connect_e2e.mjs +196 -0
- package/tests/box_cost.mjs +70 -0
- package/tests/box_dns_repoint.mjs +151 -0
- package/tests/box_host_keys.mjs +102 -0
- package/tests/box_onboard.mjs +317 -0
- package/tests/box_scope_session.mjs +115 -0
- package/tests/box_ship_permissions.mjs +71 -0
- package/tests/box_terminal_ssrf.mjs +90 -0
- package/tests/boxes.mjs +1255 -0
- package/tests/branding.mjs +88 -0
- package/tests/bug_attachments.mjs +189 -0
- package/tests/build_info.mjs +88 -0
- package/tests/builder_needs.mjs +99 -0
- package/tests/cap_newcomer_tasks.mjs +114 -0
- package/tests/cascade-dispatch.mjs +95 -0
- package/tests/cf_tunnel.mjs +459 -0
- package/tests/claim_recall.mjs +150 -0
- package/tests/claims_bind_session.mjs +47 -0
- package/tests/claude_materialize.mjs +148 -0
- package/tests/cli_box_scope.mjs +52 -0
- package/tests/cli_lib_formatters.mjs +87 -0
- package/tests/cli_token_reissue.mjs +147 -0
- package/tests/client_bundle_route.mjs +47 -0
- package/tests/cloud_bongos_pack.mjs +85 -0
- package/tests/conductor.mjs +496 -0
- package/tests/confirm_attribution.mjs +156 -0
- package/tests/conflict_resolve.mjs +462 -0
- package/tests/context_pack.mjs +240 -0
- package/tests/cost.mjs +94 -0
- package/tests/cost_audit.mjs +122 -0
- package/tests/cost_budget_status.mjs +78 -0
- package/tests/cost_reconcile.mjs +102 -0
- package/tests/cost_summary_shape.mjs +94 -0
- package/tests/credit_grant.mjs +376 -0
- package/tests/criterion_progress.mjs +220 -0
- package/tests/criterion_proposal.mjs +109 -0
- package/tests/criterion_ref_parse.mjs +53 -0
- package/tests/currency_label.mjs +119 -0
- package/tests/day_cycle.mjs +197 -0
- package/tests/dependencies_migration.mjs +77 -0
- package/tests/dependencies_polymorphic.mjs +212 -0
- package/tests/deploy_instance.mjs +78 -0
- package/tests/devbox_downloads.mjs +122 -0
- package/tests/diff_derived_signals.mjs +115 -0
- package/tests/discord_approvals.mjs +174 -0
- package/tests/discord_autojoin.mjs +158 -0
- package/tests/discord_bot.mjs +94 -0
- package/tests/discord_bugs.mjs +297 -0
- package/tests/discord_channels.mjs +337 -0
- package/tests/discord_foundation.mjs +76 -0
- package/tests/discord_inbound.mjs +190 -0
- package/tests/discord_message_buffer.mjs +87 -0
- package/tests/discord_oauth.mjs +55 -0
- package/tests/discord_reaction.mjs +170 -0
- package/tests/discord_role_sync.mjs +151 -0
- package/tests/display_name.mjs +123 -0
- package/tests/dns_preflight.mjs +74 -0
- package/tests/event_sound_prefs.mjs +194 -0
- package/tests/eviction_policy.mjs +279 -0
- package/tests/figma_adapter.mjs +199 -0
- package/tests/file_map.mjs +91 -0
- package/tests/first_admin_bootstrap.mjs +40 -0
- package/tests/fitness.mjs +435 -0
- package/tests/fitness_two_root.mjs +104 -0
- package/tests/fixtures/session-506-digest.json +34 -0
- package/tests/gate_approvals.mjs +451 -0
- package/tests/gate_review.mjs +152 -0
- package/tests/git_merge_regen.mjs +151 -0
- package/tests/github_push_ancestry.mjs +119 -0
- package/tests/github_push_land_proof.mjs +127 -0
- package/tests/github_push_merge_driver.mjs +175 -0
- package/tests/goal_abuse_matrix.mjs +187 -0
- package/tests/goal_achievement.mjs +146 -0
- package/tests/goal_conflicts.mjs +305 -0
- package/tests/goal_dependencies_read.mjs +73 -0
- package/tests/goal_member_roles.mjs +420 -0
- package/tests/goal_membership_requests.mjs +332 -0
- package/tests/goal_routes.mjs +203 -0
- package/tests/goal_scope_check.mjs +167 -0
- package/tests/goal_tier.mjs +312 -0
- package/tests/goal_wall_proof.mjs +112 -0
- package/tests/grade_attempts.mjs +73 -0
- package/tests/grade_attribution.mjs +117 -0
- package/tests/grade_diff_hash.mjs +191 -0
- package/tests/grade_server_authoritative.mjs +305 -0
- package/tests/grade_unavailable_display.mjs +66 -0
- package/tests/grader.mjs +1960 -0
- package/tests/grader_bypass.mjs +57 -0
- package/tests/grader_panel.mjs +252 -0
- package/tests/grader_prompt_fencing.mjs +192 -0
- package/tests/helpers.mjs +52 -0
- package/tests/hierarchy-config.mjs +81 -0
- package/tests/init.mjs +463 -0
- package/tests/instance_config.mjs +76 -0
- package/tests/instance_manifest.mjs +110 -0
- package/tests/interaction_prefs.mjs +72 -0
- package/tests/key-card.mjs +110 -0
- package/tests/key-status.mjs +45 -0
- package/tests/land_watch.mjs +115 -0
- package/tests/lifecycle-card.mjs +145 -0
- package/tests/lifecycle_breakdown_view.mjs +236 -0
- package/tests/linkify_refs.mjs +264 -0
- package/tests/live_channel.mjs +128 -0
- package/tests/live_sse.mjs +122 -0
- package/tests/llm-cache-route.mjs +110 -0
- package/tests/llm-cache.mjs +140 -0
- package/tests/llm-pricing.mjs +152 -0
- package/tests/local_preview.mjs +136 -0
- package/tests/main_audit.mjs +137 -0
- package/tests/memory_isolation.mjs +431 -0
- package/tests/memory_map.mjs +107 -0
- package/tests/memory_pull.mjs +429 -0
- package/tests/merge_lease.mjs +100 -0
- package/tests/merge_lock.mjs +312 -0
- package/tests/metrics.mjs +147 -0
- package/tests/migration_allocation.mjs +146 -0
- package/tests/migration_namespace.mjs +185 -0
- package/tests/migrations_fresh_replay_guard.mjs +38 -0
- package/tests/mirror_lineage_fulltree.mjs +45 -0
- package/tests/mirror_lineage_proof.mjs +72 -0
- package/tests/mirror_redact.mjs +193 -0
- package/tests/model_alloc_prefs.mjs +63 -0
- package/tests/module-scope-map.mjs +88 -0
- package/tests/module_api.mjs +110 -0
- package/tests/module_cli.mjs +292 -0
- package/tests/module_contributions.mjs +148 -0
- package/tests/module_loader.mjs +286 -0
- package/tests/module_manifest.mjs +194 -0
- package/tests/module_owned_tests.mjs +105 -0
- package/tests/module_provenance.mjs +34 -0
- package/tests/module_route_rank.mjs +147 -0
- package/tests/module_seams.mjs +68 -0
- package/tests/modules.mjs +156 -0
- package/tests/modules_route.mjs +38 -0
- package/tests/newcomer_floor.mjs +17 -0
- package/tests/newcomer_restock.mjs +80 -0
- package/tests/next_number.mjs +154 -0
- package/tests/oauth_secret.mjs +60 -0
- package/tests/onboard.mjs +70 -0
- package/tests/onboarding_gate.mjs +267 -0
- package/tests/onboarding_observability.mjs +344 -0
- package/tests/onboarding_route_signals.mjs +175 -0
- package/tests/onboarding_state.mjs +346 -0
- package/tests/one_active_claim_per_session.mjs +111 -0
- package/tests/orphaned_claim_ship.mjs +135 -0
- package/tests/override_attribution.mjs +142 -0
- package/tests/override_request_ownership.mjs +235 -0
- package/tests/package_core.mjs +435 -0
- package/tests/parallel-load.mjs +402 -0
- package/tests/path_match.mjs +62 -0
- package/tests/permission_path.mjs +151 -0
- package/tests/platform_boot.mjs +167 -0
- package/tests/pre_compact.mjs +60 -0
- package/tests/preview_server.mjs +127 -0
- package/tests/profile_route.mjs +197 -0
- package/tests/provision.mjs +805 -0
- package/tests/provisioning_github_app_routes.mjs +98 -0
- package/tests/public_mirror_export.mjs +124 -0
- package/tests/public_task_resolver.mjs +112 -0
- package/tests/publish_branch_route.mjs +422 -0
- package/tests/publish_manifest.mjs +184 -0
- package/tests/publish_reconciler.mjs +728 -0
- package/tests/rank_gate.mjs +463 -0
- package/tests/rate_limit_public.mjs +217 -0
- package/tests/read_session_export.mjs +89 -0
- package/tests/recall_cli.mjs +82 -0
- package/tests/recall_hints.mjs +119 -0
- package/tests/recent_shipped_window.mjs +80 -0
- package/tests/regrade_eligibility.mjs +202 -0
- package/tests/render_prefs.mjs +122 -0
- package/tests/repo_map.mjs +92 -0
- package/tests/reward_gate.mjs +284 -0
- package/tests/route_rank_check.mjs +243 -0
- package/tests/route_validation.mjs +490 -0
- package/tests/routine_timers.mjs +72 -0
- package/tests/rubric_fixtures.mjs +140 -0
- package/tests/run_routine.mjs +69 -0
- package/tests/sandbox_stage.mjs +582 -0
- package/tests/scrubber_corpus.mjs +257 -0
- package/tests/search_chunker.mjs +209 -0
- package/tests/search_ingest.mjs +96 -0
- package/tests/search_ingest_db.mjs +88 -0
- package/tests/search_isolation.mjs +204 -0
- package/tests/search_route.mjs +95 -0
- package/tests/secret_box.mjs +189 -0
- package/tests/security_docs.mjs +186 -0
- package/tests/security_route.mjs +108 -0
- package/tests/served_paths_shipped.mjs +118 -0
- package/tests/session-cards.mjs +142 -0
- package/tests/session_506_regression.mjs +69 -0
- package/tests/session_caps.mjs +238 -0
- package/tests/session_cost.mjs +133 -0
- package/tests/session_digest.mjs +73 -0
- package/tests/session_eval.mjs +386 -0
- package/tests/session_index.mjs +105 -0
- package/tests/session_records.mjs +369 -0
- package/tests/session_search.mjs +78 -0
- package/tests/session_start_freshness.mjs +123 -0
- package/tests/setup_smoke.mjs +154 -0
- package/tests/ship_autolinkify.mjs +60 -0
- package/tests/ship_automerge_injection.mjs +174 -0
- package/tests/ship_broadcast_routing.mjs +125 -0
- package/tests/ship_broadcast_server.mjs +175 -0
- package/tests/ship_card.mjs +280 -0
- package/tests/ship_ci_deploy.mjs +374 -0
- package/tests/ship_preflight.mjs +368 -0
- package/tests/ship_premerge.mjs +75 -0
- package/tests/ship_resume.mjs +129 -0
- package/tests/ship_upload_skip.mjs +89 -0
- package/tests/ship_zero_commit.mjs +60 -0
- package/tests/single_host_hall.mjs +98 -0
- package/tests/skill_prefs.mjs +150 -0
- package/tests/smoke_preflight.mjs +66 -0
- package/tests/snapshot_picker.mjs +233 -0
- package/tests/sound_prefs.mjs +198 -0
- package/tests/sprite_facing.mjs +35 -0
- package/tests/status-probe.mjs +89 -0
- package/tests/status_backfill.mjs +94 -0
- package/tests/stop_refcheck.mjs +127 -0
- package/tests/streak.mjs +175 -0
- package/tests/subdomain_auth.mjs +58 -0
- package/tests/task_classifier_vocab.mjs +41 -0
- package/tests/task_create_idempotency.mjs +96 -0
- package/tests/task_goal_link.mjs +93 -0
- package/tests/task_ownership_gate.mjs +125 -0
- package/tests/terrain_picker.mjs +298 -0
- package/tests/touches_overlap.mjs +75 -0
- package/tests/triage_development.mjs +140 -0
- package/tests/turn_in_place.mjs +280 -0
- package/tests/upgrade.mjs +357 -0
- package/tests/verify_task_guard.mjs +64 -0
- package/tests/version_close.mjs +76 -0
- package/tests/versions_route.mjs +93 -0
- package/tests/walkability.mjs +188 -0
- package/tests/wandering_prefs.mjs +176 -0
- package/tests/worktree_disambiguation.mjs +105 -0
- package/tests/worktree_guard.mjs +90 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// tests/day_cycle.mjs
|
|
2
|
+
//
|
|
3
|
+
// The pure math behind the #639 time-of-day lighting. No Phaser, no DOM — the
|
|
4
|
+
// fx/lighting.js glue is a thin shell over these functions, so getting the
|
|
5
|
+
// math right here is most of the feature.
|
|
6
|
+
//
|
|
7
|
+
// Run: node tests/day_cycle.mjs
|
|
8
|
+
|
|
9
|
+
import { strict as assert } from 'node:assert';
|
|
10
|
+
import {
|
|
11
|
+
DEFAULT_PERIOD_MS,
|
|
12
|
+
KEYFRAMES,
|
|
13
|
+
SKY_PHASES,
|
|
14
|
+
wrap01,
|
|
15
|
+
phaseFromClock,
|
|
16
|
+
lerpColor,
|
|
17
|
+
bracket,
|
|
18
|
+
tintAt,
|
|
19
|
+
parseSkyOverride,
|
|
20
|
+
} from '../modules/game/public/game/fx/dayCycle.js';
|
|
21
|
+
|
|
22
|
+
let passed = 0;
|
|
23
|
+
function test(name, fn) {
|
|
24
|
+
try {
|
|
25
|
+
fn();
|
|
26
|
+
console.log(` ok ${name}`);
|
|
27
|
+
passed++;
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.error(` FAIL ${name}: ${e.message}`);
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const chan = (c) => [(c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff];
|
|
35
|
+
|
|
36
|
+
// ---------- wrap01 -------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
test('wrap01 maps any real into [0,1)', () => {
|
|
39
|
+
assert.equal(wrap01(0), 0);
|
|
40
|
+
assert.equal(wrap01(0.5), 0.5);
|
|
41
|
+
assert.equal(wrap01(1), 0);
|
|
42
|
+
assert.ok(Math.abs(wrap01(1.25) - 0.25) < 1e-9);
|
|
43
|
+
assert.ok(Math.abs(wrap01(-0.25) - 0.75) < 1e-9);
|
|
44
|
+
assert.ok(Math.abs(wrap01(-2.1) - 0.9) < 1e-9);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// ---------- phaseFromClock ----------------------------------------------
|
|
48
|
+
|
|
49
|
+
test('phaseFromClock is 0 at the epoch and 0.5 at half a period', () => {
|
|
50
|
+
assert.equal(phaseFromClock(0), 0);
|
|
51
|
+
assert.equal(phaseFromClock(DEFAULT_PERIOD_MS / 2), 0.5);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('phaseFromClock wraps each period', () => {
|
|
55
|
+
assert.equal(phaseFromClock(DEFAULT_PERIOD_MS), 0);
|
|
56
|
+
assert.ok(Math.abs(phaseFromClock(DEFAULT_PERIOD_MS * 1.25) - 0.25) < 1e-9);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('phaseFromClock is deterministic — shared across clients by construction', () => {
|
|
60
|
+
const now = 1_700_000_123_456;
|
|
61
|
+
assert.equal(phaseFromClock(now), phaseFromClock(now));
|
|
62
|
+
// Two clients a few seconds apart see ~the same phase (period is minutes).
|
|
63
|
+
const skew = phaseFromClock(now + 3000) - phaseFromClock(now);
|
|
64
|
+
assert.ok(Math.abs(skew) < 0.01, `3s skew tiny: ${skew}`);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('phaseFromClock guards a non-positive period', () => {
|
|
68
|
+
assert.equal(phaseFromClock(1234, 0), 0);
|
|
69
|
+
assert.equal(phaseFromClock(1234, -5), 0);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// ---------- lerpColor ----------------------------------------------------
|
|
73
|
+
|
|
74
|
+
test('lerpColor returns the endpoints at f=0 and f=1', () => {
|
|
75
|
+
assert.equal(lerpColor(0x000000, 0xffffff, 0), 0x000000);
|
|
76
|
+
assert.equal(lerpColor(0x000000, 0xffffff, 1), 0xffffff);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('lerpColor blends channel-by-channel at the midpoint', () => {
|
|
80
|
+
// (0,128,255) is the per-channel midpoint of black and 0x00ffff... use a
|
|
81
|
+
// clean case: midpoint of 0x000000 and 0x804020 is (64,32,16).
|
|
82
|
+
assert.deepEqual(chan(lerpColor(0x000000, 0x804020, 0.5)), [64, 32, 16]);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('lerpColor clamps f outside [0,1]', () => {
|
|
86
|
+
assert.equal(lerpColor(0x102030, 0xa0b0c0, -1), 0x102030);
|
|
87
|
+
assert.equal(lerpColor(0x102030, 0xa0b0c0, 2), 0xa0b0c0);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// ---------- bracket / tintAt --------------------------------------------
|
|
91
|
+
|
|
92
|
+
test('tintAt hits each keyframe exactly at its phase', () => {
|
|
93
|
+
for (const kf of KEYFRAMES) {
|
|
94
|
+
const { color, alpha } = tintAt(kf.t);
|
|
95
|
+
assert.equal(color, kf.color, `${kf.name}@${kf.t} color`);
|
|
96
|
+
assert.ok(Math.abs(alpha - kf.alpha) < 1e-9, `${kf.name}@${kf.t} alpha`);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('high noon is fully transparent (base art at full strength)', () => {
|
|
101
|
+
assert.equal(tintAt(SKY_PHASES.midday).alpha, 0);
|
|
102
|
+
// The whole noon plateau holds at alpha 0.
|
|
103
|
+
assert.equal(tintAt(0.45).alpha, 0);
|
|
104
|
+
assert.equal(tintAt(0.50).alpha, 0);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('golden hour is the warm hero state', () => {
|
|
108
|
+
const t = tintAt(SKY_PHASES.golden);
|
|
109
|
+
const [r, g, b] = chan(t.color);
|
|
110
|
+
assert.ok(r > g && g > b, `amber: r>g>b got ${r},${g},${b}`);
|
|
111
|
+
assert.ok(t.alpha > 0.3, `visible: ${t.alpha}`);
|
|
112
|
+
assert.equal(t.name, 'golden');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('night is a dark blue-dominant tint', () => {
|
|
116
|
+
const [r, g, b] = chan(tintAt(0).color);
|
|
117
|
+
assert.ok(b > r && b > g, `blue-dominant: ${r},${g},${b}`);
|
|
118
|
+
assert.ok(tintAt(0).alpha > 0.5, 'strong');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('the wrap segment interpolates nightfall → deep night across midnight', () => {
|
|
122
|
+
// phase 0.94 sits between the 0.88 nightfall keyframe and the 0.00 deep-night
|
|
123
|
+
// keyframe (read circularly). Alpha must land strictly between the two.
|
|
124
|
+
const { alpha } = tintAt(0.94);
|
|
125
|
+
assert.ok(alpha > 0.64 && alpha < 0.72, `between nightfall and deep night: ${alpha}`);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('bracket picks the wrap segment for late-night phases', () => {
|
|
129
|
+
const b = bracket(0.95);
|
|
130
|
+
assert.equal(b.from.t, 0.88);
|
|
131
|
+
assert.equal(b.to.t, 0.00);
|
|
132
|
+
assert.ok(b.f > 0 && b.f < 1);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('tintAt is continuous and total over the whole cycle (no gaps/throws)', () => {
|
|
136
|
+
let prev = tintAt(0);
|
|
137
|
+
for (let i = 1; i <= 1000; i++) {
|
|
138
|
+
const p = i / 1000;
|
|
139
|
+
const cur = tintAt(p);
|
|
140
|
+
assert.ok(cur.alpha >= 0 && cur.alpha <= 1, `alpha in range @${p}`);
|
|
141
|
+
// No discontinuous jump bigger than the largest keyframe-to-keyframe step.
|
|
142
|
+
assert.ok(Math.abs(cur.alpha - prev.alpha) < 0.05, `smooth @${p}`);
|
|
143
|
+
prev = cur;
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test('tintAt wraps: phase 1.0 equals phase 0.0', () => {
|
|
148
|
+
assert.deepEqual(tintAt(1.0), tintAt(0.0));
|
|
149
|
+
assert.deepEqual(tintAt(1.5), tintAt(0.5));
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// ---------- parseSkyOverride --------------------------------------------
|
|
153
|
+
|
|
154
|
+
test('parseSkyOverride: absent / blank => null (run the live clock)', () => {
|
|
155
|
+
assert.equal(parseSkyOverride(null), null);
|
|
156
|
+
assert.equal(parseSkyOverride(undefined), null);
|
|
157
|
+
assert.equal(parseSkyOverride(''), null);
|
|
158
|
+
assert.equal(parseSkyOverride(' '), null);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test('parseSkyOverride: mood names (case-insensitive) => their phase', () => {
|
|
162
|
+
assert.equal(parseSkyOverride('golden'), SKY_PHASES.golden);
|
|
163
|
+
assert.equal(parseSkyOverride('NIGHT'), SKY_PHASES.night);
|
|
164
|
+
assert.equal(parseSkyOverride('Dusk'), SKY_PHASES.dusk);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('parseSkyOverride: raw fractions, wrapped into [0,1)', () => {
|
|
168
|
+
assert.equal(parseSkyOverride('0.68'), 0.68);
|
|
169
|
+
assert.equal(parseSkyOverride('0'), 0);
|
|
170
|
+
assert.ok(Math.abs(parseSkyOverride('1.25') - 0.25) < 1e-9);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test('parseSkyOverride: garbage => null', () => {
|
|
174
|
+
assert.equal(parseSkyOverride('banana'), null);
|
|
175
|
+
assert.equal(parseSkyOverride('NaN'), null);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// ---------- data sanity --------------------------------------------------
|
|
179
|
+
|
|
180
|
+
test('KEYFRAMES are sorted, valid colours, alphas in [0,1]', () => {
|
|
181
|
+
for (let i = 0; i < KEYFRAMES.length; i++) {
|
|
182
|
+
const kf = KEYFRAMES[i];
|
|
183
|
+
assert.ok(kf.t >= 0 && kf.t < 1, `t in [0,1): ${kf.t}`);
|
|
184
|
+
assert.ok(kf.alpha >= 0 && kf.alpha <= 1, `alpha in [0,1]: ${kf.alpha}`);
|
|
185
|
+
assert.ok(Number.isInteger(kf.color) && kf.color >= 0 && kf.color <= 0xffffff, 'color 24-bit');
|
|
186
|
+
if (i > 0) assert.ok(kf.t > KEYFRAMES[i - 1].t, `strictly ascending @${i}`);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test('SKY_PHASES all resolve into [0,1) and round-trip through tintAt', () => {
|
|
191
|
+
for (const [name, p] of Object.entries(SKY_PHASES)) {
|
|
192
|
+
assert.ok(p >= 0 && p < 1, `${name} phase in range`);
|
|
193
|
+
assert.doesNotThrow(() => tintAt(p), `${name} tints`);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
console.log(`\nday_cycle: ${passed} passed`);
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// tests/dependencies_migration.mjs
|
|
2
|
+
//
|
|
3
|
+
// Static shape guard for migration 163 (the polymorphic dependency edge) + the
|
|
4
|
+
// db.js repoint, in the style of migration_allocation.mjs: no live DB, assert the
|
|
5
|
+
// SQL TEXT so a future edit can't silently drop the table shape, the additive
|
|
6
|
+
// backfill, the three promotion triggers, or the task-only filter on the repointed
|
|
7
|
+
// task-dependency CRUD. The runtime behaviour of the CTE + triggers is proven
|
|
8
|
+
// against real Postgres at deploy; this pins the contract.
|
|
9
|
+
//
|
|
10
|
+
// Run: node tests/dependencies_migration.mjs
|
|
11
|
+
|
|
12
|
+
import { strict as assert } from 'node:assert';
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
import { dirname, join } from 'node:path';
|
|
16
|
+
import { makeRunner } from './helpers.mjs';
|
|
17
|
+
|
|
18
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const repoRoot = join(__dirname, '..');
|
|
20
|
+
const read = (...p) => readFileSync(join(repoRoot, ...p), 'utf8');
|
|
21
|
+
|
|
22
|
+
const mig = read('migrations', '163_polymorphic_dependencies.sql');
|
|
23
|
+
const migN = mig.replace(/\s+/g, ' ');
|
|
24
|
+
// the task-dependency CRUD + the claim-gate slice carved to the lifecycle module at BV1.R86.
|
|
25
|
+
const dbSrc = read('modules', 'lifecycle', 'db.js');
|
|
26
|
+
|
|
27
|
+
const { test, summary } = makeRunner();
|
|
28
|
+
|
|
29
|
+
await test('163 creates `dependencies` with the 4-col PK, kind CHECKs, and no-self-dep', () => {
|
|
30
|
+
assert.match(mig, /CREATE TABLE IF NOT EXISTS dependencies/);
|
|
31
|
+
assert.match(mig, /from_kind\s+text\s+NOT NULL CHECK \(from_kind IN \('task', 'goal', 'criterion'\)\)/);
|
|
32
|
+
assert.match(mig, /to_kind\s+text\s+NOT NULL CHECK \(to_kind\s+IN \('task', 'goal', 'criterion'\)\)/);
|
|
33
|
+
assert.match(mig, /PRIMARY KEY \(from_kind, from_id, to_kind, to_id\)/);
|
|
34
|
+
assert.match(mig, /CONSTRAINT no_self_dep CHECK \(NOT \(from_kind = to_kind AND from_id = to_id\)\)/);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
await test('163 indexes both edge directions', () => {
|
|
38
|
+
assert.match(mig, /idx_dependencies_from ON dependencies \(from_kind, from_id\)/);
|
|
39
|
+
assert.match(mig, /idx_dependencies_to\s+ON dependencies \(to_kind, to_id\)/);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
await test('163 backfills task->task edges via SELECT (additive, replay-safe — not literal VALUES)', () => {
|
|
43
|
+
assert.match(migN, /INSERT INTO dependencies \(from_kind, from_id, to_kind, to_id, created_at\) SELECT 'task', td\.task_id, 'task', td\.depends_on_task_id/);
|
|
44
|
+
assert.match(migN, /FROM task_dependencies td ON CONFLICT DO NOTHING/);
|
|
45
|
+
// it must NOT drop the legacy table — migration 021 still seeds it on fresh bringup.
|
|
46
|
+
assert.ok(!/DROP TABLE\s+(IF EXISTS\s+)?task_dependencies/i.test(mig), 'must not drop task_dependencies');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
await test('163 defines the shared predicate + three promotion triggers on the three tables', () => {
|
|
50
|
+
assert.match(mig, /CREATE OR REPLACE FUNCTION task_is_fully_unblocked\(p_task_id bigint\)/);
|
|
51
|
+
assert.match(migN, /CREATE TRIGGER trg_promote_dependents_on_ship AFTER UPDATE OF status ON tasks/);
|
|
52
|
+
assert.match(migN, /CREATE TRIGGER trg_promote_dependents_on_crit_satisfy AFTER UPDATE OF satisfied ON done_when_criteria/);
|
|
53
|
+
assert.match(migN, /CREATE TRIGGER trg_promote_dependents_on_goal_achieve AFTER UPDATE OF status ON goals/);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
await test('163 bumps the migration counter floor to >= 164 and records itself', () => {
|
|
57
|
+
assert.match(mig, /UPDATE migration_counter SET next_number = GREATEST\(next_number, 164\)/);
|
|
58
|
+
assert.match(mig, /INSERT INTO schema_migrations \(version\) VALUES \('163_polymorphic_dependencies'\)/);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
await test('db.js: task-dependency CRUD repoints onto `dependencies`, filtered to from_kind/to_kind = task', () => {
|
|
62
|
+
assert.match(dbSrc, /FROM dependencies d/);
|
|
63
|
+
assert.match(dbSrc, /WHERE d\.from_kind = 'task' AND d\.to_kind = 'task'/);
|
|
64
|
+
assert.match(dbSrc, /INSERT INTO dependencies \(from_kind, from_id, to_kind, to_id\)/);
|
|
65
|
+
assert.match(dbSrc, /VALUES \('task', \$1, 'task', \$2\)/);
|
|
66
|
+
// no code path still reads/writes the legacy join table (comments may mention it).
|
|
67
|
+
assert.ok(!/(FROM|INTO|DELETE FROM)\s+task_dependencies/.test(dbSrc), 'no SQL still targets task_dependencies');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
await test('db.js: the claim gate + batch resolve via unsatisfiedDeps (the old unshippedDependencies is gone)', () => {
|
|
71
|
+
assert.ok(!/unshippedDependencies/.test(dbSrc), 'unshippedDependencies fully replaced');
|
|
72
|
+
assert.match(dbSrc, /const unmetDeps = await unsatisfiedDeps\(taskId, client\)/, 'single-claim gate');
|
|
73
|
+
assert.match(dbSrc, /const unmet = await unsatisfiedDeps\(t\.id, client\)/, 'batch gate');
|
|
74
|
+
assert.match(dbSrc, /!\(d\.kind === 'task' && batchIdSet\.has\(Number\(d\.id\)\)\)/, 'batch-internal filter is task-kind-only');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
summary();
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// tests/dependencies_polymorphic.mjs
|
|
2
|
+
//
|
|
3
|
+
// DB-free unit guard for the polymorphic dependency edge (ADR 0086 §5, BV1.R62 /
|
|
4
|
+
// task 1516): the claim-gate resolver `unsatisfiedDeps`, the generalized cycle
|
|
5
|
+
// check `findCycle` + its task-only bigint[] wrapper `findDependencyCycle`,
|
|
6
|
+
// `addDependency`'s synchronous input validation, the batch task-kind-only filter,
|
|
7
|
+
// and a pure-JS reproduction of the promotion/gate predicate. The recursive CTE +
|
|
8
|
+
// plpgsql triggers themselves get their RUNTIME proof against live Postgres at
|
|
9
|
+
// deploy (migrate.sh + verify-gds-only-schema.sh); there is no local DB, so these
|
|
10
|
+
// tests pin the SQL TEXT + bound params + the JS glue exactly — the same posture as
|
|
11
|
+
// goal_tier.mjs / migration_allocation.mjs.
|
|
12
|
+
//
|
|
13
|
+
// Run: node tests/dependencies_polymorphic.mjs
|
|
14
|
+
|
|
15
|
+
import { strict as assert } from 'node:assert';
|
|
16
|
+
import { createRequire } from 'node:module';
|
|
17
|
+
import { makeRunner } from './helpers.mjs';
|
|
18
|
+
|
|
19
|
+
process.env.NODE_ENV = 'test';
|
|
20
|
+
const require = createRequire(import.meta.url);
|
|
21
|
+
const db = require('../modules/lifecycle/db.js');
|
|
22
|
+
const { unsatisfiedDeps, findCycle, findDependencyCycle, addDependency } = db;
|
|
23
|
+
|
|
24
|
+
const { test, summary } = makeRunner();
|
|
25
|
+
|
|
26
|
+
// Minimal SQL-recording fake (client OR executor): returns canned rows by matcher.
|
|
27
|
+
function fake(handler) {
|
|
28
|
+
const queries = [];
|
|
29
|
+
const norm = (s) => String(s).replace(/\s+/g, ' ').trim();
|
|
30
|
+
return {
|
|
31
|
+
queries,
|
|
32
|
+
query: async (sql, params) => {
|
|
33
|
+
queries.push({ sql: norm(sql), params });
|
|
34
|
+
return (handler ? handler(norm(sql), params) : null) || { rows: [] };
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const last = (f) => f.queries[f.queries.length - 1];
|
|
39
|
+
|
|
40
|
+
// ============================ unsatisfiedDeps ============================
|
|
41
|
+
|
|
42
|
+
await test('unsatisfiedDeps: one query, bound to the task id, resolving own + goal + criterion gating', async () => {
|
|
43
|
+
const unmet = [
|
|
44
|
+
{ kind: 'task', id: 10, title: 'dep task', state: 'active' },
|
|
45
|
+
{ kind: 'goal', id: 20, title: 'dep goal', state: 'open' },
|
|
46
|
+
{ kind: 'criterion', id: 30, title: 'dep crit', state: 'unsatisfied' },
|
|
47
|
+
];
|
|
48
|
+
const fc = fake((s) => (/WITH gating AS/.test(s) ? { rows: unmet } : null));
|
|
49
|
+
const out = await unsatisfiedDeps(5, fc);
|
|
50
|
+
assert.deepEqual(out, unmet, 'returns the unmet rows unchanged');
|
|
51
|
+
const q = last(fc);
|
|
52
|
+
assert.deepEqual(q.params, [5], 'bound to the task id only');
|
|
53
|
+
// the three FROM-sources of the gating CTE (own + inherited goal + inherited criteria)
|
|
54
|
+
assert.match(q.sql, /from_kind = 'task' AND d\.from_id = t\.id/);
|
|
55
|
+
assert.match(q.sql, /from_kind = 'goal' AND d\.from_id = t\.goal_id/);
|
|
56
|
+
assert.match(q.sql, /from_kind = 'criterion' AND d\.from_id IN \( SELECT tc\.criterion_id FROM task_criteria/);
|
|
57
|
+
// the three done-ness resolutions
|
|
58
|
+
assert.match(q.sql, /JOIN tasks x ON g\.to_kind = 'task'/);
|
|
59
|
+
assert.match(q.sql, /x\.status <> 'shipped'/);
|
|
60
|
+
assert.match(q.sql, /JOIN done_when_criteria x ON g\.to_kind = 'criterion'/);
|
|
61
|
+
assert.match(q.sql, /x\.satisfied = false/);
|
|
62
|
+
assert.match(q.sql, /JOIN goals x ON g\.to_kind = 'goal'/);
|
|
63
|
+
assert.match(q.sql, /x\.status <> 'achieved'/);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await test('unsatisfiedDeps: a fully-satisfied task returns [] (claimable)', async () => {
|
|
67
|
+
const fc = fake(() => ({ rows: [] }));
|
|
68
|
+
assert.deepEqual(await unsatisfiedDeps(5, fc), []);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
await test('unsatisfiedDeps: a cross-goal block surfaces the unachieved goal (done-when #5)', async () => {
|
|
72
|
+
const fc = fake((s) => (/WITH gating AS/.test(s) ? { rows: [{ kind: 'goal', id: 99, title: 'other goal', state: 'open' }] } : null));
|
|
73
|
+
const out = await unsatisfiedDeps(5, fc);
|
|
74
|
+
assert.deepEqual(out, [{ kind: 'goal', id: 99, title: 'other goal', state: 'open' }]);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// ============================ findCycle ============================
|
|
78
|
+
|
|
79
|
+
await test('findCycle: a self-edge short-circuits without querying', async () => {
|
|
80
|
+
const fc = fake(() => { throw new Error('should not query'); });
|
|
81
|
+
assert.deepEqual(await findCycle('task', 7, 'task', 7, fc), ['task:7', 'task:7']);
|
|
82
|
+
assert.equal(fc.queries.length, 0);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
await test('findCycle: seeds at `to`, searches for `from`, walks the graph by (kind,id)', async () => {
|
|
86
|
+
const fc = fake((s) => (/WITH RECURSIVE walk/.test(s) ? { rows: [{ path: ['goal:2', 'task:9', 'task:1'] }] } : null));
|
|
87
|
+
const path = await findCycle('task', 1, 'goal', 2, fc);
|
|
88
|
+
assert.deepEqual(path, ['goal:2', 'task:9', 'task:1']);
|
|
89
|
+
assert.deepEqual(last(fc).params, ['goal', 2, 'task', 1], 'params: toKind, toId, fromKind, fromId');
|
|
90
|
+
assert.match(last(fc).sql, /JOIN walk w ON d\.from_kind = w\.kind AND d\.from_id = w\.id/);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
await test('findCycle: no path returns null (safe to add the edge)', async () => {
|
|
94
|
+
const fc = fake(() => ({ rows: [] }));
|
|
95
|
+
assert.equal(await findCycle('task', 1, 'task', 2, fc), null);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
await test('findDependencyCycle: task-only wrapper maps a pure-task path back to bigint[]', async () => {
|
|
99
|
+
const fc = fake((s) => (/WITH RECURSIVE walk/.test(s) ? { rows: [{ path: ['task:2', 'task:5', 'task:1'] }] } : null));
|
|
100
|
+
assert.deepEqual(await findDependencyCycle(1, 2, fc), [2, 5, 1], 'historical bigint[] shape preserved');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
await test('findDependencyCycle: a cycle through a non-task node keeps that node as a kind:id token', async () => {
|
|
104
|
+
const fc = fake((s) => (/WITH RECURSIVE walk/.test(s) ? { rows: [{ path: ['task:2', 'goal:3', 'task:1'] }] } : null));
|
|
105
|
+
assert.deepEqual(await findDependencyCycle(1, 2, fc), [2, 'goal:3', 1]);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
await test('findDependencyCycle: self-dep short-circuits to [id, id]', async () => {
|
|
109
|
+
const fc = fake(() => { throw new Error('no query'); });
|
|
110
|
+
assert.deepEqual(await findDependencyCycle(7, 7, fc), [7, 7]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// ===================== addDependency input validation =====================
|
|
114
|
+
// (NODE_NOT_FOUND / CYCLE / INSERT touch the module pool and are exercised against
|
|
115
|
+
// live Postgres at deploy; the synchronous validation throws first, no DB needed.)
|
|
116
|
+
|
|
117
|
+
await test('addDependency: rejects an unknown kind before touching the DB', async () => {
|
|
118
|
+
await assert.rejects(() => addDependency('bogus', 1, 'task', 2), (e) => e.code === 'BAD_KIND');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
await test('addDependency: rejects a self-edge before touching the DB', async () => {
|
|
122
|
+
await assert.rejects(() => addDependency('goal', 4, 'goal', 4), (e) => e.code === 'SELF_DEP');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// ============== pure-JS reproduction of task_is_fully_unblocked ==============
|
|
126
|
+
// Mirrors the migration's SQL predicate (own + goal + criterion gating; done =
|
|
127
|
+
// shipped|satisfied|achieved) so the promotion/gate LOGIC is pinned even though the
|
|
128
|
+
// SQL itself runs only against live Postgres.
|
|
129
|
+
function isFullyUnblocked(task, edges, done, openBlockers = new Set()) {
|
|
130
|
+
const gating = edges.filter((e) =>
|
|
131
|
+
(e.from.kind === 'task' && e.from.id === task.id) ||
|
|
132
|
+
(e.from.kind === 'goal' && task.goalId != null && e.from.id === task.goalId) ||
|
|
133
|
+
(e.from.kind === 'criterion' && task.criteria.includes(e.from.id)));
|
|
134
|
+
// V4.R15 / task 953: an open blocker linked via task_blockers also keeps the
|
|
135
|
+
// task blocked, regardless of dep done-ness (mirrors migration 176).
|
|
136
|
+
if (openBlockers.has(task.id)) return false;
|
|
137
|
+
return gating.every((e) => done.has(`${e.to.kind}:${e.to.id}`));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
await test('predicate: a task with own + goal + criterion deps unblocks only when ALL are done', () => {
|
|
141
|
+
const task = { id: 1, goalId: 50, criteria: [60] };
|
|
142
|
+
const edges = [
|
|
143
|
+
{ from: { kind: 'task', id: 1 }, to: { kind: 'task', id: 10 } }, // own
|
|
144
|
+
{ from: { kind: 'goal', id: 50 }, to: { kind: 'goal', id: 70 } }, // inherited via goal
|
|
145
|
+
{ from: { kind: 'criterion', id: 60 }, to: { kind: 'criterion', id: 80 } }, // inherited via criterion
|
|
146
|
+
];
|
|
147
|
+
assert.equal(isFullyUnblocked(task, edges, new Set()), false, 'nothing done -> blocked');
|
|
148
|
+
assert.equal(isFullyUnblocked(task, edges, new Set(['task:10', 'goal:70'])), false, 'one still open -> blocked');
|
|
149
|
+
assert.equal(isFullyUnblocked(task, edges, new Set(['task:10', 'goal:70', 'criterion:80'])), true, 'all done -> unblocked');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
await test('predicate: no gating edges is trivially unblocked; a NULL goal_id ignores goal-inherited edges', () => {
|
|
153
|
+
assert.equal(isFullyUnblocked({ id: 9, goalId: null, criteria: [] }, [], new Set()), true);
|
|
154
|
+
const edges = [{ from: { kind: 'goal', id: 50 }, to: { kind: 'goal', id: 70 } }];
|
|
155
|
+
assert.equal(isFullyUnblocked({ id: 9, goalId: null, criteria: [] }, edges, new Set()), true, 'NULL goal_id -> no goal-inherited gating');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
await test('predicate: an open blocker keeps a task blocked even when ALL deps are done (V4.R15 / idea 226)', () => {
|
|
159
|
+
// idea 226: task #859 sat in backlog, fully dep-satisfied, but linked to an
|
|
160
|
+
// OPEN operator-cutover blocker. Dep-ship promotion must NOT flip it to ready.
|
|
161
|
+
const task = { id: 859, goalId: null, criteria: [] };
|
|
162
|
+
const edges = [
|
|
163
|
+
{ from: { kind: 'task', id: 859 }, to: { kind: 'task', id: 855 } },
|
|
164
|
+
{ from: { kind: 'task', id: 859 }, to: { kind: 'task', id: 856 } },
|
|
165
|
+
];
|
|
166
|
+
const allDepsDone = new Set(['task:855', 'task:856']);
|
|
167
|
+
assert.equal(isFullyUnblocked(task, edges, allDepsDone), true, 'deps done, no blocker -> unblocked');
|
|
168
|
+
assert.equal(
|
|
169
|
+
isFullyUnblocked(task, edges, allDepsDone, new Set([859])),
|
|
170
|
+
false,
|
|
171
|
+
'deps done BUT open blocker -> stays blocked (gate-bypass closed)',
|
|
172
|
+
);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// ============== migration 176 pins the open-blocker clause in the SQL ==============
|
|
176
|
+
import { readFileSync } from 'node:fs';
|
|
177
|
+
import { fileURLToPath } from 'node:url';
|
|
178
|
+
import { dirname, join } from 'node:path';
|
|
179
|
+
|
|
180
|
+
await test('migration 176: task_is_fully_unblocked excludes tasks with an open blocker', () => {
|
|
181
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
182
|
+
const sql = readFileSync(join(here, '..', 'migrations', '176_promotion_respects_open_blockers.sql'), 'utf8')
|
|
183
|
+
.replace(/\s+/g, ' ');
|
|
184
|
+
assert.match(sql, /CREATE OR REPLACE FUNCTION task_is_fully_unblocked/, 'redefines the shared predicate');
|
|
185
|
+
// the new fail-closed clause: no open blocker linked via task_blockers
|
|
186
|
+
assert.match(sql, /FROM task_blockers tb JOIN blockers b ON b\.id = tb\.blocker_id/);
|
|
187
|
+
assert.match(sql, /tb\.task_id = p_task_id/);
|
|
188
|
+
assert.match(sql, /b\.status = 'open'/);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// ============== batch claim: task-kind-only internal filter (R1) ==============
|
|
192
|
+
const batchExternal = (unmet, batchIds) =>
|
|
193
|
+
unmet.filter((d) => !(d.kind === 'task' && batchIds.has(Number(d.id))));
|
|
194
|
+
|
|
195
|
+
await test('batch filter: only an in-batch TASK dep is internal; goal/criterion deps are always external', () => {
|
|
196
|
+
const batch = new Set([10, 11]);
|
|
197
|
+
const unmet = [
|
|
198
|
+
{ kind: 'task', id: 10, title: 't', state: 'ready' }, // internal -> filtered out
|
|
199
|
+
{ kind: 'task', id: 99, title: 't', state: 'ready' }, // external task
|
|
200
|
+
{ kind: 'goal', id: 10, title: 'g', state: 'open' }, // SAME numeric id as a batch task, but a GOAL -> external
|
|
201
|
+
{ kind: 'criterion', id: 11, title: 'c', state: 'unsatisfied' },
|
|
202
|
+
];
|
|
203
|
+
const ext = batchExternal(unmet, batch);
|
|
204
|
+
assert.deepEqual(
|
|
205
|
+
ext.map((d) => `${d.kind}:${d.id}`),
|
|
206
|
+
['task:99', 'goal:10', 'criterion:11'],
|
|
207
|
+
'a goal/criterion sharing a numeric id with a batch task must NOT be filtered (R1)',
|
|
208
|
+
);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// -------------------------------------------------------------------------
|
|
212
|
+
summary();
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// tests/deploy_instance.mjs
|
|
2
|
+
//
|
|
3
|
+
// ADR 0108 §4 (configurable-root W4 / task 1884) — the consumer-instance deploy flow. Pins the
|
|
4
|
+
// SHAPE of scripts/deploy/deploy-instance.sh via its --dry-run (prints each step, executes nothing):
|
|
5
|
+
// git pull → npm ci → migrate (core's three-root migrate.sh) → restart platform-server → /healthz;
|
|
6
|
+
// and asserts it never `git reset --hard` (the pre-split model it replaces). No droplet / no core
|
|
7
|
+
// install needed — --dry-run runs anywhere.
|
|
8
|
+
//
|
|
9
|
+
// Run: node tests/deploy_instance.mjs
|
|
10
|
+
|
|
11
|
+
import { strict as assert } from 'node:assert';
|
|
12
|
+
import { execFileSync } from 'node:child_process';
|
|
13
|
+
import { mkdtempSync, rmSync, existsSync, statSync } from 'node:fs';
|
|
14
|
+
import { tmpdir } from 'node:os';
|
|
15
|
+
import { join, dirname } from 'node:path';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
|
|
18
|
+
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
19
|
+
const SCRIPT = join(ROOT, 'scripts', 'deploy', 'deploy-instance.sh');
|
|
20
|
+
|
|
21
|
+
let passed = 0;
|
|
22
|
+
let failed = 0;
|
|
23
|
+
function t(name, fn) {
|
|
24
|
+
try { fn(); passed++; console.log(` PASS ${name}`); }
|
|
25
|
+
catch (e) { failed++; console.log(` FAIL ${name}\n ${e.message}`); }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function dryRun(env = {}) {
|
|
29
|
+
const dir = mkdtempSync(join(tmpdir(), 'w4-inst-'));
|
|
30
|
+
try {
|
|
31
|
+
return execFileSync('bash', [SCRIPT, '--dry-run'], {
|
|
32
|
+
encoding: 'utf8',
|
|
33
|
+
env: { ...process.env, INSTANCE_DIR: dir, ...env },
|
|
34
|
+
});
|
|
35
|
+
} finally {
|
|
36
|
+
rmSync(dir, { recursive: true, force: true });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
t('deploy-instance.sh exists and is executable', () => {
|
|
41
|
+
assert.ok(existsSync(SCRIPT), 'script present');
|
|
42
|
+
assert.ok(statSync(SCRIPT).mode & 0o111, 'script is executable');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
t('dry-run prints the npm-ci flow in order and exits 0', () => {
|
|
46
|
+
const out = dryRun({ PORT: '3002' });
|
|
47
|
+
const steps = ['git pull --ff-only origin main', 'npm ci --omit=dev', 'migrate.sh', 'deploy-instance complete'];
|
|
48
|
+
let last = -1;
|
|
49
|
+
for (const s of steps) {
|
|
50
|
+
const at = out.indexOf(s);
|
|
51
|
+
assert.ok(at !== -1, `dry-run must mention "${s}"`);
|
|
52
|
+
assert.ok(at > last, `"${s}" must appear after the previous step`);
|
|
53
|
+
last = at;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
t('dry-run NEVER runs `git reset --hard` (the pre-split model it replaces)', () => {
|
|
58
|
+
const out = dryRun();
|
|
59
|
+
// Every executed/echoed step is prefixed "==> ". Assert no such line is a git-reset.
|
|
60
|
+
const echoed = out.split('\n').filter((l) => l.startsWith('==> '));
|
|
61
|
+
assert.ok(!echoed.some((l) => /git reset --hard/.test(l)), 'no deploy step may hard-reset the tree');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
t('with no INSTANCE_SERVICE, dry-run prints the platform-server boot command', () => {
|
|
65
|
+
const out = dryRun({ PORT: '3009' });
|
|
66
|
+
assert.match(out, /platform-server\.js/, 'points at the core platform-server entrypoint');
|
|
67
|
+
assert.match(out, /PORT=3009/, 'threads the configured port');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
t('with INSTANCE_SERVICE set, dry-run restarts the unit but executes no curl/systemctl', () => {
|
|
71
|
+
const out = dryRun({ INSTANCE_SERVICE: 'mercury' });
|
|
72
|
+
assert.match(out, /systemctl restart mercury/, 'restarts the configured unit');
|
|
73
|
+
// dry-run must not actually poll healthz (guarded behind the non-dry branch)
|
|
74
|
+
assert.ok(!/\/healthz: 200/.test(out), 'no real healthz probe in a dry run');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
console.log(`\ndeploy_instance: ${passed} passed, ${failed} failed`);
|
|
78
|
+
process.exit(failed ? 1 : 0);
|