@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,430 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Credit allocation — the cost-plus + kind-multiplier reward model, the
|
|
4
|
+
// idea-promotion bonus, the flat session-token reward, and the net-negative
|
|
5
|
+
// (simplification) ship bonus. Carved out of the GDS core src/bongos/db.js into
|
|
6
|
+
// modules/economy/ (BV1.R77 / ADR 0093 §1-2) byte-for-byte — only the require()
|
|
7
|
+
// paths changed (the shared pool + token pricing reach through the published
|
|
8
|
+
// doorway; the achievements sibling is an intra-module require). The lifecycle
|
|
9
|
+
// (db.applyGrade/confirmTask/upsertSessionRecordWithReward) resolves these
|
|
10
|
+
// through the `reward` kernel PORT rather than importing this module.
|
|
11
|
+
|
|
12
|
+
const { pool, branding } = require('../../src/module-api');
|
|
13
|
+
const { priceModelUsage, PRICES } = require('../../src/module-api').llmPricing; // cost-plus session reward (task 1005)
|
|
14
|
+
const achievements = require('./achievements');
|
|
15
|
+
|
|
16
|
+
async function leaderboard(limit = 20) {
|
|
17
|
+
// `rank` is in the row so /builders can render the rank badge next to each
|
|
18
|
+
// citizen and offer a sort-by-rank column (V3.R16 #240).
|
|
19
|
+
// V3.R26 (#246): `karma` is included too so the leaderboard can offer a
|
|
20
|
+
// "sort by karma" toggle. Server still returns the row in drachmae order
|
|
21
|
+
// (the historical default); the client re-sorts when a non-default mode
|
|
22
|
+
// is picked.
|
|
23
|
+
// task 1531: each row also carries an `achievements` string[] (top 5 unlocked
|
|
24
|
+
// ids by sort_order) so the hall's /leaderboard renderAchievementRow() shows
|
|
25
|
+
// laurels inline. Without it b.achievements was undefined and the laurels
|
|
26
|
+
// never rendered — this mirrors the /public/leaderboard query
|
|
27
|
+
// (getLeaderboardWithAchievements) so both leaderboard surfaces match.
|
|
28
|
+
const { rows } = await pool.query(
|
|
29
|
+
`SELECT id, github_login, display_name, avatar_url, total_credits, karma, rank,
|
|
30
|
+
COALESCE((
|
|
31
|
+
SELECT array_agg(t.achievement_id ORDER BY t.sort_order)
|
|
32
|
+
FROM (
|
|
33
|
+
SELECT ba.achievement_id, a.sort_order
|
|
34
|
+
FROM builder_achievements ba
|
|
35
|
+
JOIN achievements a ON a.id = ba.achievement_id
|
|
36
|
+
WHERE ba.builder_id = builders.id
|
|
37
|
+
ORDER BY a.sort_order
|
|
38
|
+
LIMIT 5
|
|
39
|
+
) t
|
|
40
|
+
), ARRAY[]::text[]) AS achievements
|
|
41
|
+
FROM builders
|
|
42
|
+
ORDER BY total_credits DESC, created_at ASC
|
|
43
|
+
LIMIT $1`,
|
|
44
|
+
[limit]
|
|
45
|
+
);
|
|
46
|
+
return rows;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// =========================================================================
|
|
50
|
+
// Kind multipliers + idea-promotion bonus — V3.R27 (#247).
|
|
51
|
+
// =========================================================================
|
|
52
|
+
//
|
|
53
|
+
// All credits_reward values on tasks are author-estimated in raw drachmae;
|
|
54
|
+
// historically every kind paid 1:1. V3.R27 introduces a small per-kind
|
|
55
|
+
// weighting so the system over-rewards the kinds we want more of (bugs caught,
|
|
56
|
+
// learnings captured, blocker-resolutions landed, decisions documented) and
|
|
57
|
+
// under-rewards routine maintenance (cleanup, refactor). The shape is
|
|
58
|
+
// intentionally narrow — values are clamped between 0.8x and 1.5x — so
|
|
59
|
+
// builders cannot game it by misclassifying a task to chase 3x reward.
|
|
60
|
+
//
|
|
61
|
+
// The multiplier is applied at credit-grant time inside the SAME transaction
|
|
62
|
+
// that writes the credit_log row, so the audit trail is atomic. The
|
|
63
|
+
// description column (added in migration 031) records the math inline:
|
|
64
|
+
// "40c × 1.0 = 40c (feature)"
|
|
65
|
+
// Old credit_log rows have NULL description; they stay valid — this is a
|
|
66
|
+
// forward-looking convention only.
|
|
67
|
+
//
|
|
68
|
+
// Staged idea-bonus: when an idea was captured in idea_inbox and later
|
|
69
|
+
// promoted (idea_inbox.promoted_to_task_id = task.id), the original capturer
|
|
70
|
+
// earns a slice when the resulting task ships. Slice is 25% of the
|
|
71
|
+
// multiplier-adjusted reward, rounded to nearest integer drachma, paid to the
|
|
72
|
+
// idea's captured_by builder. Idempotent on (task_id, reason='idea_promotion_bonus')
|
|
73
|
+
// — a re-grade is a no-op. No self-bonus: if the same builder captured the
|
|
74
|
+
// idea AND shipped the task, no bonus is paid (the task reward already paid
|
|
75
|
+
// them in full).
|
|
76
|
+
//
|
|
77
|
+
// Configurable? Yes — by editing this constant table. We deliberately did NOT
|
|
78
|
+
// build a kind_multipliers DB table for V3.R27 because:
|
|
79
|
+
// (a) values are policy decisions that deserve a code review + ADR + commit
|
|
80
|
+
// trail, not a hot-path UPDATE that bypasses peer review.
|
|
81
|
+
// (b) the surface is tiny (9 entries) and changes rarely.
|
|
82
|
+
// (c) the deterministic-constant form is what the grader, achievement
|
|
83
|
+
// evaluators, and analytics queries can read without an extra round-trip.
|
|
84
|
+
// If this calculus changes (per-builder multipliers, per-version overrides),
|
|
85
|
+
// a future migration can promote this to a table.
|
|
86
|
+
const KIND_MULTIPLIERS = Object.freeze({
|
|
87
|
+
feature: 1.0,
|
|
88
|
+
bug: 1.2,
|
|
89
|
+
'learning-capture': 1.5,
|
|
90
|
+
'blocker-resolution':1.5,
|
|
91
|
+
decision: 1.3,
|
|
92
|
+
infra: 1.0,
|
|
93
|
+
refactor: 0.9,
|
|
94
|
+
cleanup: 0.8,
|
|
95
|
+
spike: 1.1,
|
|
96
|
+
verify: 1.0, // task 1053 (F): verification tasks reward like infra
|
|
97
|
+
unclassified: 1.0,
|
|
98
|
+
});
|
|
99
|
+
const IDEA_BONUS_FRACTION = 0.25; // 25% slice to the idea's original capturer
|
|
100
|
+
|
|
101
|
+
// =========================================================================
|
|
102
|
+
// Session token reward (flat cost-plus) — task 1005 (ADR 0054).
|
|
103
|
+
// =========================================================================
|
|
104
|
+
//
|
|
105
|
+
// A SHIPPED session earns drachmae proportional to its TRUE API token cost:
|
|
106
|
+
// drachmae = round(true_cost_usd * (1 + REWARD_MARGIN_PCT/100))
|
|
107
|
+
// i.e. cost + 20%, with 1 DRACHMA = $1 (owner re-denomination 2026-06-15,
|
|
108
|
+
// task 1138 — see the ADR 0054 amendment). This reward was originally minted in
|
|
109
|
+
// integer CENTS (the formula carried a trailing ×100); that 100× factor was
|
|
110
|
+
// dropped so a token-reward drachma reads as a whole DOLLAR of cost-plus value
|
|
111
|
+
// — de-inflating balances ~100× and bringing this path onto the same scale as
|
|
112
|
+
// the per-task credits_reward path above (still a unitless author estimate).
|
|
113
|
+
// Both accrue to builders.total_credits (= equity drachmae); ADR 0054 (+ its
|
|
114
|
+
// 2026-06-15 amendment) records the convention and why the cents form existed.
|
|
115
|
+
//
|
|
116
|
+
// REWARD_MARGIN_PCT (and the 1 drachma = $1 peg) are the code-default reward
|
|
117
|
+
// POLICY. They stay a code-reviewed default — not a live UI knob — for the same
|
|
118
|
+
// reasons KIND_MULTIPLIERS does: a policy decision deserves a commit trail and
|
|
119
|
+
// the grader reads it deterministically. But the reward policy is also
|
|
120
|
+
// PER-INSTANCE config (task 2009 / BONGOS-V1): an instance overrides the margin
|
|
121
|
+
// + the drachmae:USD peg in `config/branding.json` `reward.{marginPct,usdPeg}`
|
|
122
|
+
// (still a committed, code-reviewed change — just in the instance's config, not
|
|
123
|
+
// the vendored core module). `rewardConfig()` resolves the instance value over
|
|
124
|
+
// these defaults; the pure helper keeps its code defaults so tests stay
|
|
125
|
+
// deterministic and the call site passes the resolved config. The currency LABEL
|
|
126
|
+
// is `branding.currency.label`.
|
|
127
|
+
const REWARD_MARGIN_PCT = 20; // cost-plus margin, percent — DEFAULT (task 1005)
|
|
128
|
+
|
|
129
|
+
// Per-instance reward policy, resolved over the code defaults. Best-effort: a
|
|
130
|
+
// branding hiccup falls back to the defaults so reward accrual never crashes.
|
|
131
|
+
function rewardConfig() {
|
|
132
|
+
let r = {};
|
|
133
|
+
try { r = (branding().reward) || {}; } catch { r = {}; }
|
|
134
|
+
const marginPct = Number.isFinite(Number(r.marginPct)) ? Number(r.marginPct) : REWARD_MARGIN_PCT;
|
|
135
|
+
const usdPeg = Number.isFinite(Number(r.usdPeg)) && Number(r.usdPeg) > 0 ? Number(r.usdPeg) : 1;
|
|
136
|
+
return { marginPct, usdPeg };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Pure helper — exported for tests. Returns { trueCostUsd, marginPct, drachmae,
|
|
140
|
+
// description }. drachmae = round(cost × (1+margin) × usdPeg); at the 1:1 peg a
|
|
141
|
+
// drachma is a whole dollar of cost-plus value (task 1138), e.g.
|
|
142
|
+
// "$15.00 true cost × 1.20 = 18 drachmae (token reward)"
|
|
143
|
+
// NOTE a sub-$0.42 session (at the 1:1 peg) rounds to 0 drachmae — intended:
|
|
144
|
+
// sub-dollar sessions earn nothing. Kept pure (code-default params); the call
|
|
145
|
+
// site resolves per-instance policy via rewardConfig() and passes it in.
|
|
146
|
+
function computeSessionTokenReward(trueCostUsd, marginPct = REWARD_MARGIN_PCT, usdPeg = 1) {
|
|
147
|
+
const cost = Number(trueCostUsd) || 0;
|
|
148
|
+
const pct = Number(marginPct) || 0;
|
|
149
|
+
const peg = Number.isFinite(Number(usdPeg)) && Number(usdPeg) > 0 ? Number(usdPeg) : 1;
|
|
150
|
+
const mult = 1 + pct / 100;
|
|
151
|
+
const drachmae = Math.round(cost * mult * peg);
|
|
152
|
+
const pegNote = peg !== 1 ? ` × ${peg} peg` : '';
|
|
153
|
+
const description =
|
|
154
|
+
`$${cost.toFixed(2)} true cost × ${mult.toFixed(2)}${pegNote} = ${drachmae} drachmae (token reward)`;
|
|
155
|
+
return { trueCostUsd: cost, marginPct: pct, drachmae, description };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Pure helper — exported for tests. Returns { raw, multiplier, effective,
|
|
159
|
+
// description } for a given task kind + raw credit value. Unknown kinds fall
|
|
160
|
+
// back to 1.0× and a description that flags the fallback so an audit reader
|
|
161
|
+
// can spot misclassification.
|
|
162
|
+
function applyKindMultiplier(rawCredits, kind) {
|
|
163
|
+
const raw = Number(rawCredits) || 0;
|
|
164
|
+
const k = (kind == null || kind === '') ? 'unclassified' : String(kind);
|
|
165
|
+
const known = Object.prototype.hasOwnProperty.call(KIND_MULTIPLIERS, k);
|
|
166
|
+
const multiplier = known ? KIND_MULTIPLIERS[k] : 1.0;
|
|
167
|
+
const effective = Math.round(raw * multiplier);
|
|
168
|
+
// Format multiplier without trailing zero noise: 1.0 → "1.0", 1.25 → "1.25".
|
|
169
|
+
const multStr = multiplier.toFixed(2).replace(/0$/, '').replace(/\.$/, '.0');
|
|
170
|
+
const kindLabel = known ? k : `${k} (unknown — defaulted to 1.0×)`;
|
|
171
|
+
const description = `${raw}c × ${multStr} = ${effective}c (${kindLabel})`;
|
|
172
|
+
return { raw, multiplier, effective, description, kind: k };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Write the primary task-ship credit_log row, applying the kind multiplier.
|
|
176
|
+
// Caller must already have verified that no prior 'task.confirmed' row exists
|
|
177
|
+
// for this task. Returns { creditsAwarded, multiplier, raw } where
|
|
178
|
+
// creditsAwarded is the multiplier-adjusted integer that landed.
|
|
179
|
+
async function insertMultipliedConfirmCredit(client, builderId, taskId, rawCredits, kind) {
|
|
180
|
+
const result = applyKindMultiplier(rawCredits, kind);
|
|
181
|
+
if (result.effective <= 0) {
|
|
182
|
+
return { creditsAwarded: 0, multiplier: result.multiplier, raw: result.raw };
|
|
183
|
+
}
|
|
184
|
+
await client.query(
|
|
185
|
+
`INSERT INTO credit_log (builder_id, task_id, delta, reason, description)
|
|
186
|
+
VALUES ($1, $2, $3, 'task.confirmed', $4)`,
|
|
187
|
+
[builderId, taskId, result.effective, result.description]
|
|
188
|
+
);
|
|
189
|
+
return {
|
|
190
|
+
creditsAwarded: result.effective,
|
|
191
|
+
multiplier: result.multiplier,
|
|
192
|
+
raw: result.raw,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Idea-promotion bonus. Look up idea_inbox.promoted_to_task_id = task.id; if
|
|
197
|
+
// found AND captured_by != shipper AND no prior bonus exists for this task,
|
|
198
|
+
// grant the idea-capturer a slice of `multipliedCredits`. Returns
|
|
199
|
+
// { ideaBonusAwarded, bonusBuilderId, ideaId } — all null if nothing was paid.
|
|
200
|
+
//
|
|
201
|
+
// Guard order matters: idempotency check runs FIRST so a re-grade is a true
|
|
202
|
+
// no-op (no fresh idea lookup, no second log row). The self-bonus refusal
|
|
203
|
+
// runs SECOND so the audit trail still records the lookup-then-skip in a
|
|
204
|
+
// re-grade scenario.
|
|
205
|
+
async function maybeAwardIdeaPromotionBonus(client, taskId, shipperBuilderId, multipliedCredits) {
|
|
206
|
+
if (!Number.isFinite(multipliedCredits) || multipliedCredits <= 0) {
|
|
207
|
+
return { ideaBonusAwarded: 0, bonusBuilderId: null, ideaId: null };
|
|
208
|
+
}
|
|
209
|
+
// Idempotency guard: already paid? bail.
|
|
210
|
+
const { rows: existing } = await client.query(
|
|
211
|
+
`SELECT 1 FROM credit_log
|
|
212
|
+
WHERE task_id = $1 AND reason = 'idea_promotion_bonus' LIMIT 1`,
|
|
213
|
+
[taskId]
|
|
214
|
+
);
|
|
215
|
+
if (existing.length > 0) {
|
|
216
|
+
return { ideaBonusAwarded: 0, bonusBuilderId: null, ideaId: null };
|
|
217
|
+
}
|
|
218
|
+
// Find the idea_inbox row this task was promoted from, if any. Prefer the
|
|
219
|
+
// most recent if the (degenerate) case of multiple ideas pointing at the
|
|
220
|
+
// same task ever arises.
|
|
221
|
+
const { rows: ideaRows } = await client.query(
|
|
222
|
+
`SELECT id, captured_by
|
|
223
|
+
FROM idea_inbox
|
|
224
|
+
WHERE promoted_to_task_id = $1 AND captured_by IS NOT NULL
|
|
225
|
+
ORDER BY captured_at DESC
|
|
226
|
+
LIMIT 1`,
|
|
227
|
+
[taskId]
|
|
228
|
+
);
|
|
229
|
+
if (ideaRows.length === 0) {
|
|
230
|
+
return { ideaBonusAwarded: 0, bonusBuilderId: null, ideaId: null };
|
|
231
|
+
}
|
|
232
|
+
const idea = ideaRows[0];
|
|
233
|
+
// No self-bonus: the shipper already collected the task reward in full.
|
|
234
|
+
if (Number(idea.captured_by) === Number(shipperBuilderId)) {
|
|
235
|
+
return { ideaBonusAwarded: 0, bonusBuilderId: null, ideaId: idea.id };
|
|
236
|
+
}
|
|
237
|
+
const bonus = Math.round(Number(multipliedCredits) * IDEA_BONUS_FRACTION);
|
|
238
|
+
if (bonus <= 0) {
|
|
239
|
+
return { ideaBonusAwarded: 0, bonusBuilderId: idea.captured_by, ideaId: idea.id };
|
|
240
|
+
}
|
|
241
|
+
const description = `idea-promotion bonus: ${Math.round(IDEA_BONUS_FRACTION * 100)}% of ${multipliedCredits}c = ${bonus}c (idea #${idea.id} → task #${taskId})`;
|
|
242
|
+
await client.query(
|
|
243
|
+
`INSERT INTO credit_log (builder_id, task_id, delta, reason, description)
|
|
244
|
+
VALUES ($1, $2, $3, 'idea_promotion_bonus', $4)`,
|
|
245
|
+
[idea.captured_by, taskId, bonus, description]
|
|
246
|
+
);
|
|
247
|
+
return {
|
|
248
|
+
ideaBonusAwarded: bonus,
|
|
249
|
+
bonusBuilderId: Number(idea.captured_by),
|
|
250
|
+
ideaId: Number(idea.id),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Award the flat cost-plus session token reward, idempotent per session_id
|
|
255
|
+
// (task 1005, ADR 0054). Called inside the same transaction as the session
|
|
256
|
+
// upsert (see upsertSessionRecordWithReward).
|
|
257
|
+
// - client : a connected pg client (transaction-aware), client-first like
|
|
258
|
+
// insertMultipliedConfirmCredit so it's unit-testable with a fake.
|
|
259
|
+
// - builderId : authoritative owner (verified at the route), never the body.
|
|
260
|
+
// - sessionId : CLAUDE_CODE_SESSION_ID — the idempotency key.
|
|
261
|
+
// - modelUsage : { modelId: {input,output,cache_read,cache_creation} } from the
|
|
262
|
+
// uploaded digest. Priced SERVER-SIDE; never a client dollar value.
|
|
263
|
+
// - totalTokens: (task 1676) the session's authoritative total token count (the
|
|
264
|
+
// column the route's empty-session guard checks). Used ONLY as a
|
|
265
|
+
// fallback: when modelUsage prices to $0 but the session carried
|
|
266
|
+
// real tokens, the reward is priced from totalTokens at the opus
|
|
267
|
+
// rate so the dev-box/CI agent path (which historically uploaded
|
|
268
|
+
// empty/unpriceable model_usage → $0 reward; ADR 0097) still pays
|
|
269
|
+
// the real cost-plus amount. This is NOT a fabricated dollar value
|
|
270
|
+
// — it prices REAL token counts via the same locked PRICES table.
|
|
271
|
+
// Returns { drachmae, trueCostUsd, awarded, unknownModels, pricedFromTotalTokens }.
|
|
272
|
+
// awarded=false means a prior reward row for this session already existed
|
|
273
|
+
// (re-upload / re-ship) — a true no-op, no second credit, no double payout.
|
|
274
|
+
async function awardSessionTokenReward(client, builderId, sessionId, modelUsage, totalTokens = 0) {
|
|
275
|
+
const { true_cost_usd: pricedCostUsd, unknown_models: unknownModels } =
|
|
276
|
+
priceModelUsage(modelUsage);
|
|
277
|
+
// Cost-plus zero-out fallback (task 1676). priceModelUsage returns $0 when
|
|
278
|
+
// model_usage is empty or carries no token counts — the exact dev-box/CI symptom
|
|
279
|
+
// ADR 0097 records ("upload no priced model usage"). When that happens but the
|
|
280
|
+
// session DID carry real tokens, price the total at the opus rate so the reward
|
|
281
|
+
// reflects the real spend instead of silently rounding to 0. The blend assumes a
|
|
282
|
+
// marathon agent session is cache_read-dominated (the real cost driver — a large
|
|
283
|
+
// context re-read each turn), so this conservatively UNDER-estimates rather than
|
|
284
|
+
// over-pays vs. a true per-tier split.
|
|
285
|
+
let trueCostUsd = pricedCostUsd;
|
|
286
|
+
let pricedFromTotalTokens = false;
|
|
287
|
+
const tt = Math.max(0, Math.trunc(Number(totalTokens) || 0));
|
|
288
|
+
if (!(pricedCostUsd > 0) && tt > 0) {
|
|
289
|
+
trueCostUsd = Math.round(((tt * PRICES.opus.cache_read) / 1e6) * 10000) / 10000;
|
|
290
|
+
pricedFromTotalTokens = true;
|
|
291
|
+
}
|
|
292
|
+
const { marginPct, usdPeg } = rewardConfig();
|
|
293
|
+
const { drachmae, description } = computeSessionTokenReward(trueCostUsd, marginPct, usdPeg);
|
|
294
|
+
|
|
295
|
+
// Nothing priced (no real tokens) — record nothing, report cleanly.
|
|
296
|
+
if (!(drachmae > 0)) {
|
|
297
|
+
return { drachmae: 0, trueCostUsd, awarded: false, unknownModels, pricedFromTotalTokens };
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Fast-path idempotency guard (the partial-unique index is the hard backstop
|
|
301
|
+
// against a race). Keyed on the literal reason + session_id.
|
|
302
|
+
const { rows: existing } = await client.query(
|
|
303
|
+
`SELECT 1 FROM credit_log
|
|
304
|
+
WHERE reason = 'session.token_reward' AND session_id = $1 LIMIT 1`,
|
|
305
|
+
[sessionId]
|
|
306
|
+
);
|
|
307
|
+
if (existing.length > 0) {
|
|
308
|
+
return { drachmae: 0, trueCostUsd, awarded: false, unknownModels, pricedFromTotalTokens };
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Append-only ledger row. task_id = NULL (session-level, not task-level).
|
|
312
|
+
// ON CONFLICT DO NOTHING on the partial-unique index closes the race window:
|
|
313
|
+
// if a parallel upload inserted between our SELECT and here, we no-op cleanly.
|
|
314
|
+
const { rows } = await client.query(
|
|
315
|
+
`INSERT INTO credit_log (builder_id, task_id, delta, reason, description, session_id)
|
|
316
|
+
VALUES ($1, NULL, $2, 'session.token_reward', $3, $4)
|
|
317
|
+
ON CONFLICT (session_id) WHERE reason = 'session.token_reward' DO NOTHING
|
|
318
|
+
RETURNING id`,
|
|
319
|
+
[builderId, drachmae, description, sessionId]
|
|
320
|
+
);
|
|
321
|
+
const awarded = rows.length > 0;
|
|
322
|
+
return { drachmae: awarded ? drachmae : 0, trueCostUsd, awarded, unknownModels, pricedFromTotalTokens };
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// net-negative ship bonus — V3.R93 (#354). Simplification reward.
|
|
326
|
+
//
|
|
327
|
+
// The v1 grader's scoreLocNetNegative concept (a ship that removes more lines
|
|
328
|
+
// than it adds is a win) was only ever expressed as a rubric SCORE in the
|
|
329
|
+
// deprecated deterministic grader — it never moved credits. Here we revive the
|
|
330
|
+
// idea as a small, real credit bonus routed through the SAME credit_log path
|
|
331
|
+
// applyGrade already uses for task.confirmed.
|
|
332
|
+
//
|
|
333
|
+
// The bonus is a flat +1 drachma when lines_removed > lines_added in the ship's
|
|
334
|
+
// diff_stats (the same shortstat the grader already records in
|
|
335
|
+
// signals.diff_stats — see scripts/gds/ship.js computeDiffShortstat). Net-zero
|
|
336
|
+
// or net-positive ships get nothing. The credit_log description embeds the raw
|
|
337
|
+
// removed/added values and the reason so the audit trail is self-explaining.
|
|
338
|
+
//
|
|
339
|
+
// Idempotent: keyed on (task_id, reason='ship.net_negative') so a re-grade
|
|
340
|
+
// can't double-award. Returns { bonus, justUnlocked } — bonus is the integer
|
|
341
|
+
// credit awarded (0 if not eligible / already awarded); justUnlocked is the
|
|
342
|
+
// array of achievements unlocked by this award (the "Subtractor" achievement,
|
|
343
|
+
// if the threshold was crossed on this ship).
|
|
344
|
+
//
|
|
345
|
+
// The "Subtractor" achievement (seeded in migration 031) is awarded here via
|
|
346
|
+
// the EXISTING builder_achievements mechanism (achievements.unlockAchievement)
|
|
347
|
+
// rather than in achievements.evaluateAfterShip, because the count it depends on
|
|
348
|
+
// (this builder's net-negative ship bonuses) only becomes correct after THIS
|
|
349
|
+
// ship's bonus row is inserted — and that insert lives here. Doing the unlock
|
|
350
|
+
// inline keeps the read-then-unlock atomic with the insert in one transaction.
|
|
351
|
+
const NET_NEGATIVE_BONUS = 1;
|
|
352
|
+
const SUBTRACTOR_THRESHOLD = 3; // net-negative ships needed to unlock Subtractor
|
|
353
|
+
function netNegativeBonusAmount(diffStats) {
|
|
354
|
+
if (!diffStats) return 0;
|
|
355
|
+
const added = Number(diffStats.lines_added) || 0;
|
|
356
|
+
const removed = Number(diffStats.lines_removed) || 0;
|
|
357
|
+
return removed > added ? NET_NEGATIVE_BONUS : 0;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
async function awardNetNegativeBonus(client, builderId, taskId, diffStats) {
|
|
361
|
+
const bonus = netNegativeBonusAmount(diffStats);
|
|
362
|
+
if (bonus <= 0) return { bonus: 0, justUnlocked: [] };
|
|
363
|
+
|
|
364
|
+
const { rows: existing } = await client.query(
|
|
365
|
+
`SELECT 1 FROM credit_log WHERE task_id = $1 AND reason = 'ship.net_negative' LIMIT 1`,
|
|
366
|
+
[taskId]
|
|
367
|
+
);
|
|
368
|
+
if (existing.length > 0) return { bonus: 0, justUnlocked: [] };
|
|
369
|
+
|
|
370
|
+
const added = Number(diffStats.lines_added) || 0;
|
|
371
|
+
const removed = Number(diffStats.lines_removed) || 0;
|
|
372
|
+
const description = `net-negative ship bonus: +${bonus} (removed ${removed} > added ${added} lines — simplification reward)`;
|
|
373
|
+
|
|
374
|
+
await client.query(
|
|
375
|
+
`INSERT INTO credit_log (builder_id, task_id, delta, reason, description)
|
|
376
|
+
VALUES ($1, $2, $3, 'ship.net_negative', $4)`,
|
|
377
|
+
[builderId, taskId, bonus, description]
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
// Subtractor: >= 3 net-negative ships (this one now counted above).
|
|
381
|
+
const justUnlocked = [];
|
|
382
|
+
if (!(await achievements.alreadyUnlocked(client, builderId, 'subtractor'))) {
|
|
383
|
+
const { rows } = await client.query(
|
|
384
|
+
`SELECT COUNT(*)::int AS n FROM credit_log
|
|
385
|
+
WHERE builder_id = $1 AND reason = 'ship.net_negative'`,
|
|
386
|
+
[builderId]
|
|
387
|
+
);
|
|
388
|
+
if (Number(rows[0].n) >= SUBTRACTOR_THRESHOLD) {
|
|
389
|
+
const unlocked = await achievements.unlockAchievement(client, builderId, 'subtractor', taskId);
|
|
390
|
+
if (unlocked) justUnlocked.push(unlocked);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return { bonus, justUnlocked };
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// sumCreditsForTasks — the drachmae (credit_log delta) a builder actually earned
|
|
398
|
+
// for a set of tasks. POST /sessions uses this to populate drachmae_earned from
|
|
399
|
+
// the authoritative ledger server-side, rather than trusting a client value or
|
|
400
|
+
// the configured credits_reward (which diverges once kind multipliers / idea
|
|
401
|
+
// bonuses apply — ADR 0023).
|
|
402
|
+
async function sumCreditsForTasks(builderId, taskIds) {
|
|
403
|
+
const ids = Array.isArray(taskIds) ? taskIds.map(Number).filter(Number.isFinite) : [];
|
|
404
|
+
if (ids.length === 0) return 0;
|
|
405
|
+
const { rows } = await pool.query(
|
|
406
|
+
`SELECT COALESCE(SUM(delta), 0)::int AS total
|
|
407
|
+
FROM credit_log
|
|
408
|
+
WHERE builder_id = $1 AND task_id = ANY($2::bigint[])`,
|
|
409
|
+
[builderId, ids]
|
|
410
|
+
);
|
|
411
|
+
return rows[0] ? rows[0].total : 0;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
module.exports = {
|
|
415
|
+
leaderboard,
|
|
416
|
+
KIND_MULTIPLIERS,
|
|
417
|
+
IDEA_BONUS_FRACTION,
|
|
418
|
+
REWARD_MARGIN_PCT,
|
|
419
|
+
rewardConfig,
|
|
420
|
+
computeSessionTokenReward,
|
|
421
|
+
applyKindMultiplier,
|
|
422
|
+
insertMultipliedConfirmCredit,
|
|
423
|
+
maybeAwardIdeaPromotionBonus,
|
|
424
|
+
awardSessionTokenReward,
|
|
425
|
+
NET_NEGATIVE_BONUS,
|
|
426
|
+
SUBTRACTOR_THRESHOLD,
|
|
427
|
+
netNegativeBonusAmount,
|
|
428
|
+
awardNetNegativeBonus,
|
|
429
|
+
sumCreditsForTasks,
|
|
430
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
-- economy_001_fix_gds_shipper_description.sql — task #1679.
|
|
2
|
+
--
|
|
3
|
+
-- Two data fixes for the broken-achievements bug, both idempotent and safe to
|
|
4
|
+
-- re-run / no-op on a fresh instance.
|
|
5
|
+
--
|
|
6
|
+
-- 1) gds-shipper DESCRIPTION still pointed at src/pms/ / scripts/pms/, paths that
|
|
7
|
+
-- ceased to exist in the PMS -> GDS rename (V3.R01, migration 019). The
|
|
8
|
+
-- EVALUATOR was re-pointed at the time but the seeded description was missed
|
|
9
|
+
-- (idea 50). Correct it so the hall, CLI banners, and locked-progress hints
|
|
10
|
+
-- describe what actually unlocks the badge.
|
|
11
|
+
--
|
|
12
|
+
-- 2) BACKFILL the achievements that should already be unlocked. Until this task,
|
|
13
|
+
-- the dominant ship path (confirmTask / --skip-grade / grader_bypass) never
|
|
14
|
+
-- evaluated achievements, and breaking-the-100c-bar was a boundary check on a
|
|
15
|
+
-- credit branch the session reward never hit — so the board was effectively
|
|
16
|
+
-- dead (e.g. nobody held breaking-the-100c-bar despite multiple builders far
|
|
17
|
+
-- past 100c). The forward fix (state-based reconcile on every ship path) heals
|
|
18
|
+
-- builders on their next ship; this backfills everyone NOW, on deploy, so the
|
|
19
|
+
-- hall is correct immediately.
|
|
20
|
+
--
|
|
21
|
+
-- The predicates here are a ONE-SHOT SQL mirror of modules/economy/
|
|
22
|
+
-- achievements.js STATE_EVALUATORS. A migration is immutable and runs once, so
|
|
23
|
+
-- this copy cannot drift the way the THREE long-lived copies did (idea 44/50);
|
|
24
|
+
-- the JS list remains the single forward source of truth. Streak-3/streak-7
|
|
25
|
+
-- are intentionally OMITTED here (their timezone-aware consecutive-day math is
|
|
26
|
+
-- not worth duplicating in SQL) — they backfill via the JS reconcile on a
|
|
27
|
+
-- builder's next ship, or immediately via `node scripts/gds/diagnose-achievements.js --apply`.
|
|
28
|
+
--
|
|
29
|
+
-- Idempotent: ON CONFLICT DO NOTHING means re-running unlocks nothing new, and
|
|
30
|
+
-- the credit bonus is inserted ONLY for rows the INSERT actually created
|
|
31
|
+
-- (RETURNING), so totals never double-count. The credit_log trigger rolls each
|
|
32
|
+
-- bonus into builders.total_credits exactly as a live unlock would.
|
|
33
|
+
|
|
34
|
+
UPDATE achievements
|
|
35
|
+
SET description = 'Ship a task whose touches[] include src/bongos/ or scripts/gds/.'
|
|
36
|
+
WHERE id = 'gds-shipper';
|
|
37
|
+
|
|
38
|
+
WITH eligible AS (
|
|
39
|
+
-- first-claim: has ever claimed
|
|
40
|
+
SELECT b.id AS builder_id, 'first-claim'::text AS achievement_id
|
|
41
|
+
FROM builders b
|
|
42
|
+
WHERE EXISTS (SELECT 1 FROM claims c WHERE c.builder_id = b.id)
|
|
43
|
+
UNION
|
|
44
|
+
-- first-ship: has ever shipped a claim
|
|
45
|
+
SELECT DISTINCT c.builder_id, 'first-ship'
|
|
46
|
+
FROM claims c
|
|
47
|
+
WHERE c.outcome = 'shipped'
|
|
48
|
+
UNION
|
|
49
|
+
-- art-pipeline-shipper: a shipped task touching art/
|
|
50
|
+
SELECT DISTINCT c.builder_id, 'art-pipeline-shipper'
|
|
51
|
+
FROM claims c JOIN tasks t ON t.id = c.task_id
|
|
52
|
+
WHERE c.outcome = 'shipped'
|
|
53
|
+
AND EXISTS (SELECT 1 FROM unnest(t.touches) AS p WHERE p LIKE 'art/%')
|
|
54
|
+
UNION
|
|
55
|
+
-- gds-shipper: a shipped task touching src/bongos/ or scripts/gds/
|
|
56
|
+
SELECT DISTINCT c.builder_id, 'gds-shipper'
|
|
57
|
+
FROM claims c JOIN tasks t ON t.id = c.task_id
|
|
58
|
+
WHERE c.outcome = 'shipped'
|
|
59
|
+
AND EXISTS (SELECT 1 FROM unnest(t.touches) AS p
|
|
60
|
+
WHERE p LIKE 'src/bongos/%' OR p LIKE 'scripts/gds/%')
|
|
61
|
+
UNION
|
|
62
|
+
-- first-parallel-claim: two shipped claims whose windows overlap
|
|
63
|
+
SELECT DISTINCT a.builder_id, 'first-parallel-claim'
|
|
64
|
+
FROM claims a JOIN claims b2
|
|
65
|
+
ON b2.builder_id = a.builder_id AND b2.id <> a.id
|
|
66
|
+
WHERE a.outcome = 'shipped' AND a.released_at IS NOT NULL
|
|
67
|
+
AND b2.outcome = 'shipped' AND b2.released_at IS NOT NULL
|
|
68
|
+
AND tstzrange(a.claimed_at, a.released_at) && tstzrange(b2.claimed_at, b2.released_at)
|
|
69
|
+
UNION
|
|
70
|
+
-- breaking-the-100c-bar: at or past 100 total credits
|
|
71
|
+
SELECT b.id, 'breaking-the-100c-bar'
|
|
72
|
+
FROM builders b
|
|
73
|
+
WHERE b.total_credits >= 100
|
|
74
|
+
UNION
|
|
75
|
+
-- subtractor: >= 3 net-negative ship bonuses
|
|
76
|
+
SELECT cl.builder_id, 'subtractor'
|
|
77
|
+
FROM credit_log cl
|
|
78
|
+
WHERE cl.reason = 'ship.net_negative'
|
|
79
|
+
GROUP BY cl.builder_id
|
|
80
|
+
HAVING COUNT(*) >= 3
|
|
81
|
+
),
|
|
82
|
+
ins AS (
|
|
83
|
+
INSERT INTO builder_achievements (builder_id, achievement_id, unlocked_at, unlocked_by_task_id)
|
|
84
|
+
SELECT builder_id, achievement_id, now(), NULL FROM eligible
|
|
85
|
+
ON CONFLICT (builder_id, achievement_id) DO NOTHING
|
|
86
|
+
RETURNING builder_id, achievement_id
|
|
87
|
+
)
|
|
88
|
+
INSERT INTO credit_log (builder_id, task_id, delta, reason, recorded_at)
|
|
89
|
+
SELECT ins.builder_id, NULL, a.credit_bonus, 'achievement.' || ins.achievement_id, now()
|
|
90
|
+
FROM ins JOIN achievements a ON a.id = ins.achievement_id
|
|
91
|
+
WHERE a.credit_bonus > 0;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"key": "economy",
|
|
3
|
+
"title": "Economy",
|
|
4
|
+
"description": "Credit allocation (the cost-plus + kind-multiplier reward model), the cost ledger + dashboard rollups, builder streaks, achievements/gamification, and the leaderboard. A core-domain module carved out of the GDS core in BV1.R77 (ADR 0093 §1-2); default-on because every instance rewards its own builders. Registers the `reward` kernel PORT the lifecycle resolves at confirm/ship/claim time.",
|
|
5
|
+
"coreVersion": "^1.7.0",
|
|
6
|
+
"default": true,
|
|
7
|
+
"contributes": { "routes": ["cost", "leaderboard", "reward"] },
|
|
8
|
+
"provides": ["reward"],
|
|
9
|
+
"consumes": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// The `reward` kernel PORT provider surface (BV1.R77 / ADR 0093 §1-2).
|
|
4
|
+
//
|
|
5
|
+
// economy registers ONE port — `reward` — that the lifecycle + the core read
|
|
6
|
+
// routes resolve. It is a TRANSACTION-PARTICIPANT port for the credit-allocation
|
|
7
|
+
// half: the caller (db.applyGrade / confirmTask / upsertSessionRecordWithReward,
|
|
8
|
+
// inside its own withTx) passes its tx `client` as the first arg, so the credit
|
|
9
|
+
// write commits atomically with the state-machine SQL that stays in the core
|
|
10
|
+
// lifecycle (ADR 0093 §2 — extract the capability, keep the state machine). The
|
|
11
|
+
// gamification + read half is stateless.
|
|
12
|
+
//
|
|
13
|
+
// We DELEGATE (do NOT spread) every method so a test that stubs a method on the
|
|
14
|
+
// live `achievements`/`credits` object (e.g. tests/grade_attribution.mjs sets
|
|
15
|
+
// achievements.evaluateAfterShip = async () => []) still bites at call time —
|
|
16
|
+
// a spread would capture the original reference at module-load and ignore the stub.
|
|
17
|
+
|
|
18
|
+
const credits = require('./credits');
|
|
19
|
+
const achievements = require('./achievements');
|
|
20
|
+
const cost = require('./cost');
|
|
21
|
+
const streak = require('./streak');
|
|
22
|
+
|
|
23
|
+
module.exports = {
|
|
24
|
+
// credit allocation — transaction-participant: caller passes its tx `client`
|
|
25
|
+
insertMultipliedConfirmCredit: (...a) => credits.insertMultipliedConfirmCredit(...a),
|
|
26
|
+
maybeAwardIdeaPromotionBonus: (...a) => credits.maybeAwardIdeaPromotionBonus(...a),
|
|
27
|
+
awardNetNegativeBonus: (...a) => credits.awardNetNegativeBonus(...a),
|
|
28
|
+
awardSessionTokenReward: (...a) => credits.awardSessionTokenReward(...a),
|
|
29
|
+
// gamification hooks the lifecycle fires at claim/ship
|
|
30
|
+
evaluateAfterClaim: (...a) => achievements.evaluateAfterClaim(...a),
|
|
31
|
+
evaluateAfterShip: (...a) => achievements.evaluateAfterShip(...a),
|
|
32
|
+
evaluateAfterCreditAward: (...a) => achievements.evaluateAfterCreditAward(...a),
|
|
33
|
+
// task 1679: state-based, idempotent reconcile — the durable replacement that
|
|
34
|
+
// fires on EVERY ship path (incl. confirmTask / grader_bypass, which never
|
|
35
|
+
// evaluated achievements before, so most builders only ever got first-claim).
|
|
36
|
+
reconcileBuilderAchievements: (...a) => achievements.reconcileBuilderAchievements(...a),
|
|
37
|
+
// pure helpers + constants (display / tests)
|
|
38
|
+
applyKindMultiplier: (...a) => credits.applyKindMultiplier(...a),
|
|
39
|
+
computeSessionTokenReward: (...a) => credits.computeSessionTokenReward(...a),
|
|
40
|
+
get KIND_MULTIPLIERS() { return credits.KIND_MULTIPLIERS; },
|
|
41
|
+
get IDEA_BONUS_FRACTION() { return credits.IDEA_BONUS_FRACTION; },
|
|
42
|
+
get REWARD_MARGIN_PCT() { return credits.REWARD_MARGIN_PCT; },
|
|
43
|
+
|
|
44
|
+
// --- READ surface the core me/public/builders/sessions routes resolve through
|
|
45
|
+
// this same port (one economy port; the grading precedent registers the
|
|
46
|
+
// whole module surface on its single port too).
|
|
47
|
+
costSummary: (...a) => cost.costSummary(...a),
|
|
48
|
+
costCalibrationSummary: (...a) => cost.costCalibrationSummary(...a),
|
|
49
|
+
getBuilderCostStatus: (...a) => cost.getBuilderCostStatus(...a),
|
|
50
|
+
setBuilderMonthlyBudget: (...a) => cost.setBuilderMonthlyBudget(...a),
|
|
51
|
+
reconcileSessionCosts: (...a) => cost.reconcileSessionCosts(...a),
|
|
52
|
+
autonomousApiSpendMtd: (...a) => cost.autonomousApiSpendMtd(...a),
|
|
53
|
+
leaderboard: (...a) => credits.leaderboard(...a),
|
|
54
|
+
getLeaderboardWithAchievements: (...a) => achievements.getLeaderboardWithAchievements(...a),
|
|
55
|
+
listAchievements: (...a) => achievements.listAchievements(...a),
|
|
56
|
+
getBuilderAchievements: (...a) => achievements.getBuilderAchievements(...a),
|
|
57
|
+
getLockedAchievementsProgress: (...a) => achievements.getLockedAchievementsProgress(...a),
|
|
58
|
+
sumCreditsForTasks: (...a) => credits.sumCreditsForTasks(...a),
|
|
59
|
+
computeStreak: (...a) => streak.computeStreak(...a),
|
|
60
|
+
wouldExtendStreak: (...a) => streak.wouldExtendStreak(...a),
|
|
61
|
+
};
|