@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,104 @@
|
|
|
1
|
+
// Backup status + trigger routes.
|
|
2
|
+
//
|
|
3
|
+
// GET /backup/status — latest local dump info + offsite indicator (metic+archon)
|
|
4
|
+
// POST /backup/trigger — fire a fresh local dump asynchronously (metic+archon)
|
|
5
|
+
//
|
|
6
|
+
// The server process runs as the `lars` user on the droplet, so it can read
|
|
7
|
+
// /var/backups/gds/ and spawn the existing db-backup-nightly.sh directly —
|
|
8
|
+
// no SSH, no sudo, no extra credentials. A builder with no shell access calls
|
|
9
|
+
// these routes instead.
|
|
10
|
+
//
|
|
11
|
+
// Design notes:
|
|
12
|
+
// - trigger is fire-and-forget: 202 Accepted immediately; the dump runs
|
|
13
|
+
// in the background. The builder polls status to see it land.
|
|
14
|
+
// - concurrent triggers: a simple in-memory flag prevents two dumps from
|
|
15
|
+
// running simultaneously (one droplet, one disk, no need for DB state).
|
|
16
|
+
// - the backup dir and script paths default to the on-droplet locations but
|
|
17
|
+
// can be overridden via env vars for local tests.
|
|
18
|
+
|
|
19
|
+
const express = require('express');
|
|
20
|
+
const fs = require('node:fs');
|
|
21
|
+
const path = require('node:path');
|
|
22
|
+
const { execFile } = require('node:child_process');
|
|
23
|
+
const auth = require('../auth');
|
|
24
|
+
const { branding } = require('../../branding');
|
|
25
|
+
const { asyncHandler } = require('./_helpers');
|
|
26
|
+
|
|
27
|
+
const REPO_ROOT = path.resolve(__dirname, '..', '..', '..');
|
|
28
|
+
const BACKUP_DIR = process.env.GDS_BACKUP_DIR || '/var/backups/gds';
|
|
29
|
+
// The DB name comes from the branding pack (branding.db.database), never a
|
|
30
|
+
// hardcoded host brand (ADR 0062 §3) — a non-OTB instance dumps its own DB.
|
|
31
|
+
const DB_NAME = process.env.GDS_BACKUP_DB
|
|
32
|
+
|| (() => { try { return branding().db && branding().db.database; } catch { return null; } })()
|
|
33
|
+
|| 'gds';
|
|
34
|
+
const BACKUP_SCRIPT = process.env.GDS_BACKUP_SCRIPT
|
|
35
|
+
|| path.join(REPO_ROOT, 'scripts', 'gds', 'db-backup-nightly.sh');
|
|
36
|
+
|
|
37
|
+
// In-memory guard: true while a trigger-initiated dump is running.
|
|
38
|
+
let triggerRunning = false;
|
|
39
|
+
|
|
40
|
+
function latestDump() {
|
|
41
|
+
let files;
|
|
42
|
+
try {
|
|
43
|
+
files = fs.readdirSync(BACKUP_DIR);
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const dumps = files
|
|
48
|
+
.filter(f => f.startsWith(`${DB_NAME}-`) && f.endsWith('.sql.gz'))
|
|
49
|
+
.sort();
|
|
50
|
+
if (!dumps.length) return null;
|
|
51
|
+
const name = dumps[dumps.length - 1];
|
|
52
|
+
const full = path.join(BACKUP_DIR, name);
|
|
53
|
+
let size_bytes = null;
|
|
54
|
+
try { size_bytes = fs.statSync(full).size; } catch { /* ok */ }
|
|
55
|
+
// Filename: <db>-<YYYY-MM-DDTHHMMSSZ>.sql.gz — extract timestamp from it.
|
|
56
|
+
const ts = name.replace(`${DB_NAME}-`, '').replace('.sql.gz', '');
|
|
57
|
+
return { filename: name, timestamp: ts, size_bytes, count: dumps.length };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = function buildBackupRouter() {
|
|
61
|
+
const router = express.Router();
|
|
62
|
+
|
|
63
|
+
// rank: metic+archon — any working builder may check or trigger a backup.
|
|
64
|
+
router.get('/backup/status', auth.requireBuilder, auth.requireRank('metic', 'archon'),
|
|
65
|
+
asyncHandler('GET /backup/status', async (_req, res) => {
|
|
66
|
+
const dump = latestDump();
|
|
67
|
+
res.json({
|
|
68
|
+
backup_dir: BACKUP_DIR,
|
|
69
|
+
db_name: DB_NAME,
|
|
70
|
+
latest_dump: dump,
|
|
71
|
+
trigger_running: triggerRunning,
|
|
72
|
+
});
|
|
73
|
+
}));
|
|
74
|
+
|
|
75
|
+
// rank: metic+archon
|
|
76
|
+
router.post('/backup/trigger', auth.requireBuilder, auth.requireRank('metic', 'archon'),
|
|
77
|
+
asyncHandler('POST /backup/trigger', async (req, res) => {
|
|
78
|
+
if (triggerRunning) {
|
|
79
|
+
return res.fail('backup_already_running', { status: 409, message: 'A backup is already in progress — poll /backup/status to see it land.' });
|
|
80
|
+
}
|
|
81
|
+
triggerRunning = true;
|
|
82
|
+
const startedAt = new Date().toISOString();
|
|
83
|
+
const builderId = req.builder && req.builder.id;
|
|
84
|
+
console.log(`[gds] backup triggered by builder ${builderId} at ${startedAt}`);
|
|
85
|
+
|
|
86
|
+
execFile('bash', [BACKUP_SCRIPT], { cwd: REPO_ROOT, timeout: 120_000 }, (err, stdout, stderr) => {
|
|
87
|
+
triggerRunning = false;
|
|
88
|
+
if (err) {
|
|
89
|
+
console.error(`[gds] backup trigger failed (builder ${builderId}):`, err.message);
|
|
90
|
+
if (stderr) console.error('[gds] backup stderr:', stderr.toString().trim());
|
|
91
|
+
} else {
|
|
92
|
+
console.log(`[gds] backup trigger completed (builder ${builderId})`);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
res.status(202).json({
|
|
97
|
+
ok: true,
|
|
98
|
+
message: 'Backup started — poll GET /api/gds/backup/status to see the new dump land (usually < 30 s).',
|
|
99
|
+
started_at: startedAt,
|
|
100
|
+
});
|
|
101
|
+
}));
|
|
102
|
+
|
|
103
|
+
return router;
|
|
104
|
+
};
|
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
const path = require('node:path');
|
|
2
|
+
const { execFile } = require('node:child_process');
|
|
3
|
+
const express = require('express');
|
|
4
|
+
const auth = require('../auth');
|
|
5
|
+
const db = require('../db');
|
|
6
|
+
const { validateOrRespond, LIMITS, parseId } = require('./_helpers');
|
|
7
|
+
// The onboarding state machine carved into modules/onboarding/ (BV1.R81 / ADR
|
|
8
|
+
// 0093 §1): GET /builders/:id/onboarding resolves the `onboarding` kernel port
|
|
9
|
+
// for the roster-visible checklist (read/shape) — never a direct require.
|
|
10
|
+
const { pool } = require('../pool');
|
|
11
|
+
const seams = require('../../module-seams');
|
|
12
|
+
const { branding } = require('../../branding');
|
|
13
|
+
// The lifecycle (tasks · claims · ship) carved to modules/lifecycle/ (BV1.R86 /
|
|
14
|
+
// ADR 0093 §3): the Archon roster, the per-builder stale-claim view, the
|
|
15
|
+
// per-builder grade breakdown, and the shipped-count read resolve the `lifecycle`
|
|
16
|
+
// kernel PORT (lc()). The rank/identity mutations (setBuilderRank/deactivate/
|
|
17
|
+
// reactivate) stay core db (this domain is builder identity, not the lifecycle).
|
|
18
|
+
const lc = () => seams.resolveOptional('lifecycle');
|
|
19
|
+
// Dev-box "has this builder ever connected a box?" read through the kernel seam
|
|
20
|
+
// instead of a direct `require('../boxes')` (a forbidden core→module edge once
|
|
21
|
+
// dev-box moved to modules/dev-box/, ADR 0083 / BV1.R43). The dev-box module
|
|
22
|
+
// provides the `box.hasEverConnected` port when enabled; degrades to false on a
|
|
23
|
+
// box-less instance (the box_connect onboarding step just never auto-clears).
|
|
24
|
+
const boxHasEverConnected = (builderId) =>
|
|
25
|
+
seams.resolveOptional('box.hasEverConnected', async () => false)(builderId);
|
|
26
|
+
|
|
27
|
+
// The discord "has this builder linked their Discord account?" signal, read
|
|
28
|
+
// through the kernel seam instead of a direct `db.getDiscordLink` (a forbidden
|
|
29
|
+
// core→module edge once discord moved to modules/discord/, ADR 0083 / BV1.R47).
|
|
30
|
+
// The discord module provides the `discord.isLinked` port when enabled; degrades
|
|
31
|
+
// to false on a discord-less instance (the discord onboarding step never clears).
|
|
32
|
+
const discordIsLinked = (builderId) =>
|
|
33
|
+
seams.resolveOptional('discord.isLinked', async () => false)(builderId);
|
|
34
|
+
|
|
35
|
+
// Builder administration routes (V3.R07 #232).
|
|
36
|
+
//
|
|
37
|
+
// PATCH /builders/:id/rank — the SINGLE chokepoint for rank changes. Archon-
|
|
38
|
+
// only (enforced server-side via requireRank — ADR 0016). Promotion AND
|
|
39
|
+
// demotion go through here so there's exactly one audited path that can alter
|
|
40
|
+
// authority. The promotion/demotion ceremony (V3.R28 #249) bolts on three
|
|
41
|
+
// signals after a successful rank change: the credit_log row (handled by
|
|
42
|
+
// db.setBuilderRank — +5 on promotion, 0 on demotion), a Mediterranean-tone
|
|
43
|
+
// Discord broadcast (fired here, best-effort, non-blocking), and a Claude
|
|
44
|
+
// SessionStart greeting (the `.claude/hooks/rank-change-greeting.js` hook
|
|
45
|
+
// picks up the latest credit_log row via GET /me/pending-rank-change). Audit
|
|
46
|
+
// log proper lands later (R36).
|
|
47
|
+
|
|
48
|
+
// Resolve the repo root from this file. Used to invoke scripts/discord/post.js
|
|
49
|
+
// regardless of where the node process was started from.
|
|
50
|
+
const REPO_ROOT = path.resolve(__dirname, '..', '..', '..');
|
|
51
|
+
|
|
52
|
+
// Map a rank id (db enum string) to its display form used in the Discord
|
|
53
|
+
// broadcast — capitalized, no surprises. Centralized here so the wording is
|
|
54
|
+
// consistent everywhere ceremony surfaces the rank.
|
|
55
|
+
function displayRank(rank) {
|
|
56
|
+
if (!rank || typeof rank !== 'string') return rank;
|
|
57
|
+
return rank.charAt(0).toUpperCase() + rank.slice(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Build the Mediterranean-tone Discord message. Promotion is celebratory
|
|
61
|
+
// ("raised to the rank of"); demotion is dignified ("stepped down to the rank
|
|
62
|
+
// of" — no "demoted", no shaming). Lateral (impossible at the call site since
|
|
63
|
+
// RANK_UNCHANGED short-circuits earlier, but defensive) reads as a neutral
|
|
64
|
+
// "moves to". The display_name is what the team sees in Discord.
|
|
65
|
+
function buildRankChangeBroadcast({ displayName, direction, newRank }) {
|
|
66
|
+
const who = displayName || 'a builder';
|
|
67
|
+
const rank = displayRank(newRank);
|
|
68
|
+
// "Citizens of <worldName>" — the salutation reads the instance world name
|
|
69
|
+
// from the branding pack, never a hardcoded host brand (ADR 0062 §3), so a
|
|
70
|
+
// non-OTB instance addresses its own citizens.
|
|
71
|
+
const worldName = (() => { try { return branding().identity?.worldName || 'the city'; } catch { return 'the city'; } })();
|
|
72
|
+
if (direction === 'promotion') {
|
|
73
|
+
return `Citizens of ${worldName} — ${who} has been raised to the rank of ${rank}.`;
|
|
74
|
+
}
|
|
75
|
+
if (direction === 'demotion') {
|
|
76
|
+
return `Citizens of ${worldName} — ${who} has stepped down to the rank of ${rank}.`;
|
|
77
|
+
}
|
|
78
|
+
return `Citizens of ${worldName} — ${who} now holds the rank of ${rank}.`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Fire the rank-change broadcast in the background. Best-effort: a post
|
|
82
|
+
// failure must never undo a successful rank change. We detach (no callback
|
|
83
|
+
// wait) and let stderr surface in server logs if the post script errors.
|
|
84
|
+
// Outbound moved from Google Chat to Discord #ship-news per ADR 0032 / #607
|
|
85
|
+
// (scripts/chat/ is inbound-only now). The CHAT_DRY_RUN env var short-circuits
|
|
86
|
+
// to a "[broadcast dry-run]" log line — used by the smoke path so a test rank
|
|
87
|
+
// flip doesn't actually hit Discord. The name is a legacy artifact; it gates
|
|
88
|
+
// all broadcast transports, not just Chat.
|
|
89
|
+
function fireDiscordBroadcast(text) {
|
|
90
|
+
if (!text) return;
|
|
91
|
+
if (process.env.CHAT_DRY_RUN === '1') {
|
|
92
|
+
console.log(`[gds] [broadcast dry-run] would post: ${text}`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
execFile(
|
|
97
|
+
'node',
|
|
98
|
+
['scripts/discord/post.js', text],
|
|
99
|
+
{ cwd: REPO_ROOT, timeout: 10_000 },
|
|
100
|
+
(err, _stdout, stderr) => {
|
|
101
|
+
if (err) {
|
|
102
|
+
console.log('[gds] rank-change broadcast failed (non-blocking):', err.message);
|
|
103
|
+
if (stderr) console.log('[gds] discord stderr:', stderr.toString().trim());
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
} catch (e) {
|
|
108
|
+
console.log('[gds] rank-change broadcast spawn failed (non-blocking):', e && e.message);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = function buildBuildersRouter() {
|
|
113
|
+
const router = express.Router();
|
|
114
|
+
|
|
115
|
+
// rank: archon — sole chokepoint that mutates builders.rank; ADR 0016 §enforcement.
|
|
116
|
+
router.patch('/builders/:id/rank', auth.requireBuilder, auth.requireRank('archon'), async (req, res) => {
|
|
117
|
+
if (validateOrRespond(req, res, {
|
|
118
|
+
rank: { required: true, type: 'string', maxLength: 32 },
|
|
119
|
+
})) return;
|
|
120
|
+
const targetId = parseId(req, res, { code: 'bad_builder_id', positiveInt: true });
|
|
121
|
+
if (targetId === null) return;
|
|
122
|
+
const newRank = req.body && req.body.rank;
|
|
123
|
+
if (!newRank || !db.RANKS.includes(newRank)) {
|
|
124
|
+
return res.fail('bad_rank', 400, { valid: db.RANKS });
|
|
125
|
+
}
|
|
126
|
+
// #706: `thetes` IS manually grantable by an Archon. It is reachable two
|
|
127
|
+
// ways — the automatic 3-shipped-tasks graduation (db.maybeAutoGraduateToThetes)
|
|
128
|
+
// AND a deliberate Archon promotion through this route. (An earlier #704 cut
|
|
129
|
+
// wrongly refused manual set-to-thetes; that block is removed.)
|
|
130
|
+
// No last-Archon footgun: an Archon cannot change their own rank (this
|
|
131
|
+
// covers self-demotion, which could otherwise strand the system with no
|
|
132
|
+
// Archon). Another Archon must do it.
|
|
133
|
+
//
|
|
134
|
+
// Compare as strings: req.builder.id is a string (node-postgres returns
|
|
135
|
+
// bigint as text) while targetId is a Number, so `===` would never match
|
|
136
|
+
// and the guard would silently fail. (Fixed in #348 after a live self-
|
|
137
|
+
// demotion lockout.)
|
|
138
|
+
if (String(targetId) === String(req.builder.id)) {
|
|
139
|
+
return res.fail('cannot_change_own_rank', 403);
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const result = await db.setBuilderRank({
|
|
143
|
+
builderId: targetId,
|
|
144
|
+
newRank,
|
|
145
|
+
actorBuilderId: req.builder.id,
|
|
146
|
+
});
|
|
147
|
+
// V3.R28 / #249 — ceremony signal #2: Discord broadcast.
|
|
148
|
+
// Fire-and-forget; failure does NOT roll back the rank change. The
|
|
149
|
+
// credit_log ceremony row was already written inside setBuilderRank
|
|
150
|
+
// (signal #1), and the SessionStart hook (signal #3) reads from there.
|
|
151
|
+
const broadcastText = buildRankChangeBroadcast({
|
|
152
|
+
displayName: result.builder.display_name || result.builder.github_login,
|
|
153
|
+
direction: result.direction,
|
|
154
|
+
newRank: result.builder.rank,
|
|
155
|
+
});
|
|
156
|
+
fireDiscordBroadcast(broadcastText);
|
|
157
|
+
// F5 role-sync (ADR 0033 §4): push the new rank to the builder's Discord
|
|
158
|
+
// role badge. Fire-and-forget — a Discord failure must not roll back the
|
|
159
|
+
// rank change. No-op if the builder hasn't linked Discord / the bot is off.
|
|
160
|
+
// Emit to the discord module's listener (ADR 0083 / BV1.R47 — no core→module
|
|
161
|
+
// import). Fire-and-forget; the listener repairs the Discord rank-role badge.
|
|
162
|
+
seams.emit('builder.role-sync-needed', { builderId: targetId });
|
|
163
|
+
res.json({
|
|
164
|
+
builder: result.builder,
|
|
165
|
+
previous_rank: result.previous_rank,
|
|
166
|
+
direction: result.direction,
|
|
167
|
+
credit_delta: result.credit_delta,
|
|
168
|
+
broadcast: broadcastText,
|
|
169
|
+
});
|
|
170
|
+
} catch (err) {
|
|
171
|
+
if (err && err.code === 'BUILDER_NOT_FOUND') {
|
|
172
|
+
return res.fail('builder_not_found', 404);
|
|
173
|
+
}
|
|
174
|
+
if (err && err.code === 'RANK_UNCHANGED') {
|
|
175
|
+
return res.fail('rank_unchanged', 409, { rank: err.rank });
|
|
176
|
+
}
|
|
177
|
+
// #707: a manual promotion may only advance one live rung at a time.
|
|
178
|
+
if (err && err.code === 'MULTI_RUNG_PROMOTION') {
|
|
179
|
+
return res.fail('multi_rung_promotion', { status: 400, message: `Promotions advance one rung at a time. From ${err.from}, the next rung is ${err.next_rung} — promote there first.`, details: { from: err.from, to: err.to, next_rung: err.next_rung } });
|
|
180
|
+
}
|
|
181
|
+
console.error('[gds] PATCH /builders/:id/rank', err);
|
|
182
|
+
res.fail('rank_change_failed', { status: 500, message: 'internal error' });
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// PATCH /builders/:id/status — graceful exit + reactivation (V3.R88 #307).
|
|
187
|
+
// Archon-only. { status: 'inactive', reason? } deactivates (releases active
|
|
188
|
+
// claims, seals their session_logs, rank → xenos, blocks new claims while
|
|
189
|
+
// preserving all credit/history); { status: 'active' } reactivates. Cannot
|
|
190
|
+
// change your own status (no last-Archon footgun — same guard as /rank).
|
|
191
|
+
// rank: archon — deactivation/reactivation; preserves credit history but blocks claims.
|
|
192
|
+
router.patch('/builders/:id/status', auth.requireBuilder, auth.requireRank('archon'), async (req, res) => {
|
|
193
|
+
if (validateOrRespond(req, res, {
|
|
194
|
+
status: { required: true, type: 'string', enum: ['active', 'inactive'] },
|
|
195
|
+
reason: { type: 'string', maxLength: LIMITS.NOTES },
|
|
196
|
+
})) return;
|
|
197
|
+
const targetId = parseId(req, res, { code: 'bad_builder_id', positiveInt: true });
|
|
198
|
+
if (targetId === null) return;
|
|
199
|
+
const status = req.body && req.body.status;
|
|
200
|
+
if (status !== 'inactive' && status !== 'active') {
|
|
201
|
+
return res.fail('bad_status', 400, { valid: ['active', 'inactive'] });
|
|
202
|
+
}
|
|
203
|
+
if (String(targetId) === String(req.builder.id)) {
|
|
204
|
+
return res.fail('cannot_change_own_status', 403);
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
if (status === 'inactive') {
|
|
208
|
+
const result = await db.deactivateBuilder({
|
|
209
|
+
builderId: targetId,
|
|
210
|
+
reason: req.body.reason ?? null,
|
|
211
|
+
actorBuilderId: req.builder.id,
|
|
212
|
+
});
|
|
213
|
+
return res.json(result);
|
|
214
|
+
}
|
|
215
|
+
const result = await db.reactivateBuilder({
|
|
216
|
+
builderId: targetId,
|
|
217
|
+
actorBuilderId: req.builder.id,
|
|
218
|
+
});
|
|
219
|
+
return res.json(result);
|
|
220
|
+
} catch (err) {
|
|
221
|
+
if (err && err.code === 'BUILDER_NOT_FOUND') {
|
|
222
|
+
return res.fail('builder_not_found', 404);
|
|
223
|
+
}
|
|
224
|
+
if (err && err.code === 'ALREADY_INACTIVE') {
|
|
225
|
+
return res.fail('already_inactive', 409);
|
|
226
|
+
}
|
|
227
|
+
if (err && err.code === 'NOT_INACTIVE') {
|
|
228
|
+
return res.fail('not_inactive', 409, { status: err.status });
|
|
229
|
+
}
|
|
230
|
+
console.error('[gds] PATCH /builders/:id/status', err);
|
|
231
|
+
res.fail('status_change_failed', { status: 500, message: 'internal error' });
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// PATCH /builders/:id/budget — set or clear a builder's monthly spend ceiling
|
|
236
|
+
// (V3.R84 #302, criterion C3). Archon-only. Body: { monthly_budget_usd: <num> }
|
|
237
|
+
// sets the per-builder override — the manual emergency brake; a positive value
|
|
238
|
+
// engages the warn/over thresholds. { monthly_budget_usd: null } clears it: the
|
|
239
|
+
// builder becomes UNCAPPED (there is no default cap — ADR 0085). This is the
|
|
240
|
+
// "budget per-builder configurable by Archon" done-when. 404 if no such builder.
|
|
241
|
+
// rank: archon — changes another builder's cost ceiling.
|
|
242
|
+
router.patch('/builders/:id/budget', auth.requireBuilder, auth.requireRank('archon'), async (req, res) => {
|
|
243
|
+
const targetId = parseId(req, res, { code: 'bad_builder_id', positiveInt: true });
|
|
244
|
+
if (targetId === null) return;
|
|
245
|
+
if (validateOrRespond(req, res, { monthly_budget_usd: {} })) return; // number ≥0, or null to clear; validated below
|
|
246
|
+
const raw = req.body ? req.body.monthly_budget_usd : undefined;
|
|
247
|
+
let budget;
|
|
248
|
+
if (raw === null) {
|
|
249
|
+
budget = null; // clear → uncapped (no default cap; ADR 0085)
|
|
250
|
+
} else if (typeof raw === 'number' && Number.isFinite(raw) && raw >= 0) {
|
|
251
|
+
budget = raw;
|
|
252
|
+
} else {
|
|
253
|
+
return res.fail('bad_budget', { status: 400, message: 'monthly_budget_usd must be a non-negative number, or null to clear' });
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
// setBuilderMonthlyBudget carved to modules/economy/ (BV1.R77 / ADR 0093
|
|
257
|
+
// §1-2): resolve the `reward` kernel port (economy is default-on). The
|
|
258
|
+
// archon rank gate on this route is unchanged.
|
|
259
|
+
const updated = await seams.resolveOptional('reward').setBuilderMonthlyBudget(targetId, budget);
|
|
260
|
+
if (!updated) return res.fail('builder_not_found', 404);
|
|
261
|
+
res.json({ builder: updated });
|
|
262
|
+
} catch (err) {
|
|
263
|
+
console.error('[gds] PATCH /builders/:id/budget', err);
|
|
264
|
+
res.fail('budget_change_failed', { status: 500, message: 'internal error' });
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// GET /builders/roster — V3.R14 (#238) onboarding observability.
|
|
269
|
+
//
|
|
270
|
+
// Archon-only roster of every builder with their identity + onboarding
|
|
271
|
+
// signals + active-claim posture. Powers the management panel in the
|
|
272
|
+
// /builders hall so the Archon can promote / demote / release-stale-claim
|
|
273
|
+
// without dropping into psql.
|
|
274
|
+
//
|
|
275
|
+
// Optional query param: ?stale_hours=N (default 24). Defines what counts
|
|
276
|
+
// as "stale" for the per-row stale_claim flag — mirrors the threshold the
|
|
277
|
+
// stale-claim-release sweeper uses but exposed as a roster knob so the
|
|
278
|
+
// Archon can dial it in if needed.
|
|
279
|
+
//
|
|
280
|
+
// rank: archon — surfaces every builder's onboarding state.
|
|
281
|
+
router.get('/builders/roster', auth.requireBuilder, auth.requireRank('archon'), async (req, res) => {
|
|
282
|
+
let staleHours = 24;
|
|
283
|
+
if (req.query && req.query.stale_hours != null) {
|
|
284
|
+
const n = Number(req.query.stale_hours);
|
|
285
|
+
if (!Number.isFinite(n) || n <= 0 || n > 720) {
|
|
286
|
+
return res.fail('bad_stale_hours', 400, { expected: '1..720' });
|
|
287
|
+
}
|
|
288
|
+
staleHours = n;
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
const builders = await lc().getBuildersRoster({ staleHours });
|
|
292
|
+
res.json({ builders, stale_hours: staleHours });
|
|
293
|
+
} catch (err) {
|
|
294
|
+
console.error('[gds] GET /builders/roster', err);
|
|
295
|
+
res.fail('roster_failed', { status: 500, message: 'internal error' });
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// GET /builders/directory — the any-builder-readable picker roster (task 1877):
|
|
300
|
+
// every ACTIVE builder's identity, for a client-side invite dropdown (the Goals
|
|
301
|
+
// invite control, task 1762) that shouldn't be limited to GET /leaderboard's
|
|
302
|
+
// top-100-by-credits window. Deliberately narrower than /builders/roster — no
|
|
303
|
+
// onboarding/stale-claim/box data, which stays Archon-only; id/login/name/
|
|
304
|
+
// avatar/rank is no more sensitive than what /leaderboard already exposes
|
|
305
|
+
// publicly, just without the credits cutoff.
|
|
306
|
+
// rank: any-builder.
|
|
307
|
+
router.get('/builders/directory', auth.requireBuilder, async (req, res) => {
|
|
308
|
+
try {
|
|
309
|
+
const builders = await db.listActiveBuilders();
|
|
310
|
+
res.json({ builders });
|
|
311
|
+
} catch (err) {
|
|
312
|
+
console.error('[gds] GET /builders/directory', err);
|
|
313
|
+
res.fail('directory_failed', { status: 500, message: 'internal error' });
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
// GET /grades/by-builder?days=30 — per-builder grade breakdown (#726).
|
|
318
|
+
//
|
|
319
|
+
// Archon-only monitoring read backing the MARKS section of the /watch page:
|
|
320
|
+
// who is passing/failing the grader, over a window. Aggregated from
|
|
321
|
+
// task_grades joined through tasks.shipped_by. Mirrors the rank gate on the
|
|
322
|
+
// roster + audit-log reads — it exposes cross-builder quality data, so it is
|
|
323
|
+
// the Ruling Hand's alone (the project-wide aggregate stays public via
|
|
324
|
+
// /public/grades; this per-builder split does not).
|
|
325
|
+
//
|
|
326
|
+
// rank: archon.
|
|
327
|
+
router.get('/grades/by-builder', auth.requireBuilder, auth.requireRank('archon'), async (req, res) => {
|
|
328
|
+
let days = 30;
|
|
329
|
+
if (req.query && req.query.days != null) {
|
|
330
|
+
const n = Number(req.query.days);
|
|
331
|
+
if (!Number.isFinite(n) || n <= 0 || n > 365) {
|
|
332
|
+
return res.fail('bad_days', 400, { expected: '1..365' });
|
|
333
|
+
}
|
|
334
|
+
days = Math.floor(n);
|
|
335
|
+
}
|
|
336
|
+
try {
|
|
337
|
+
const builders = await lc().gradeByBuilder(days);
|
|
338
|
+
res.json({ window_days: days, builders });
|
|
339
|
+
} catch (err) {
|
|
340
|
+
console.error('[gds] GET /grades/by-builder', err);
|
|
341
|
+
res.fail('grades_by_builder_failed', { status: 500, message: 'internal error' });
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
// GET /builders/:id/active-claims — V3.R14 (#238).
|
|
346
|
+
//
|
|
347
|
+
// Archon-only detail view of a single builder's active claims, with the
|
|
348
|
+
// same stale_claim flag the roster computes. The roster only carries
|
|
349
|
+
// boolean "has any stale claim?"; this endpoint surfaces *which* claim
|
|
350
|
+
// is stale so the Archon can target the release.
|
|
351
|
+
//
|
|
352
|
+
// rank: archon — privileged read of another builder's work surface.
|
|
353
|
+
router.get('/builders/:id/active-claims', auth.requireBuilder, auth.requireRank('archon'), async (req, res) => {
|
|
354
|
+
const targetId = parseId(req, res, { code: 'bad_builder_id', positiveInt: true });
|
|
355
|
+
if (targetId === null) return;
|
|
356
|
+
let staleHours = 24;
|
|
357
|
+
if (req.query && req.query.stale_hours != null) {
|
|
358
|
+
const n = Number(req.query.stale_hours);
|
|
359
|
+
if (!Number.isFinite(n) || n <= 0 || n > 720) {
|
|
360
|
+
return res.fail('bad_stale_hours', 400, { expected: '1..720' });
|
|
361
|
+
}
|
|
362
|
+
staleHours = n;
|
|
363
|
+
}
|
|
364
|
+
try {
|
|
365
|
+
const claims = await lc().getActiveClaimsForBuilderWithStale(targetId, { staleHours });
|
|
366
|
+
res.json({ builder_id: targetId, claims, stale_hours: staleHours });
|
|
367
|
+
} catch (err) {
|
|
368
|
+
console.error('[gds] GET /builders/:id/active-claims', err);
|
|
369
|
+
res.fail('active_claims_failed', { status: 500, message: 'internal error' });
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// GET /builders/:id/onboarding — V3.R75 (#294) onboarding checklist read.
|
|
374
|
+
//
|
|
375
|
+
// Returns the builder's onboarding state machine row, shaped for the
|
|
376
|
+
// /builders hall checklist UI:
|
|
377
|
+
// {
|
|
378
|
+
// builder_id, current_stage, completed_stages, started_at, completed_at,
|
|
379
|
+
// progress: { cleared, total },
|
|
380
|
+
// stages: [{ id, label, hint, cleared, is_current }, ...],
|
|
381
|
+
// graduated: boolean
|
|
382
|
+
// }
|
|
383
|
+
//
|
|
384
|
+
// Public read (no auth). Spec says the hall renders other builders'
|
|
385
|
+
// checklists read-only — a builder's onboarding progress is roster-visible
|
|
386
|
+
// signal, same posture as rank or drachmae shown on the leaderboard. The
|
|
387
|
+
// builder's own row is also surfaced inside /api/gds/me; this endpoint is
|
|
388
|
+
// what the hall hits for the CURRENT viewer AND for any other builder
|
|
389
|
+
// whose card is rendered.
|
|
390
|
+
//
|
|
391
|
+
// rank: public — onboarding progress is a roster-visible signal.
|
|
392
|
+
router.get('/builders/:id/onboarding', async (req, res) => {
|
|
393
|
+
const targetId = parseId(req, res, { code: 'bad_builder_id', positiveInt: true });
|
|
394
|
+
if (targetId === null) return;
|
|
395
|
+
try {
|
|
396
|
+
// The onboarding state machine carved into modules/onboarding/ (BV1.R81 /
|
|
397
|
+
// ADR 0093 §1): resolve the `onboarding` kernel port for the read + shape —
|
|
398
|
+
// never a direct require of a module. Default-on (present in prod); degrades
|
|
399
|
+
// to a null state row (shapeForApi synthesizes the "nothing cleared" view).
|
|
400
|
+
const onboarding = seams.resolveOptional('onboarding');
|
|
401
|
+
const [state, shipCount, discordLink, boxConnected, cliAuthed] = await Promise.all([
|
|
402
|
+
onboarding ? onboarding.getState(pool, targetId) : null,
|
|
403
|
+
lc().countShippedTasksForBuilder(targetId),
|
|
404
|
+
discordIsLinked(targetId),
|
|
405
|
+
boxHasEverConnected(targetId),
|
|
406
|
+
db.hasCliSession(targetId),
|
|
407
|
+
]);
|
|
408
|
+
// shipCount drives the terminal 'ship_three' stage's "N of 3" counter.
|
|
409
|
+
// The box/discord/cli steps clear from LIVE signals (not the onboarding_state
|
|
410
|
+
// row), so they must be passed in exactly as GET /me does — otherwise they
|
|
411
|
+
// default to false and this route renders box_connect/join_discord/cli_setup
|
|
412
|
+
// perpetually unchecked even after the builder cleared them (task 1444).
|
|
413
|
+
const shaped = onboarding ? onboarding.shapeForApi(state, {
|
|
414
|
+
shipCount,
|
|
415
|
+
discordLinked: !!discordLink,
|
|
416
|
+
boxConnected: !!boxConnected,
|
|
417
|
+
cliAuthed: !!cliAuthed,
|
|
418
|
+
}) : null;
|
|
419
|
+
// Light cache — onboarding state changes a few times per builder, ever.
|
|
420
|
+
res.set('Cache-Control', 'private, max-age=10');
|
|
421
|
+
res.json({ builder_id: targetId, onboarding: shaped });
|
|
422
|
+
} catch (err) {
|
|
423
|
+
console.error('[gds] GET /builders/:id/onboarding', err);
|
|
424
|
+
res.fail('onboarding_read_failed', { status: 500, message: 'internal error' });
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
// GET /builders/:id/profile — the viewable builder profile page's read
|
|
429
|
+
// (task 1467, goal 25 "bx-identity"). Returns ONE builder's public portfolio:
|
|
430
|
+
// identity + rank + economy counters + shipped-work count + recent ships +
|
|
431
|
+
// unlocked achievements. Backs the shareable /builders/profile page.
|
|
432
|
+
//
|
|
433
|
+
// rank: public — every field returned here is ALREADY world-readable: the
|
|
434
|
+
// leaderboard (GET /public/leaderboard, no auth) exposes rank, total_credits,
|
|
435
|
+
// karma, and the top achievement ids; GET /builders/:id/onboarding is likewise
|
|
436
|
+
// an unauthenticated roster-visible read. This route is a per-builder re-
|
|
437
|
+
// presentation of the SAME already-public data, so a portfolio link is
|
|
438
|
+
// shareable without a sign-in wall (that IS the feature). It deliberately
|
|
439
|
+
// WHITELISTS the public column subset off the full builder row — the private
|
|
440
|
+
// columns getBuilderById also returns (anthropic_email / anthropic_user_id /
|
|
441
|
+
// monthly_budget_usd / system_role / box_blocked*) are NEVER spread into the
|
|
442
|
+
// JSON. A leak-prevention unit test (tests/profile_route.mjs) asserts their
|
|
443
|
+
// absence + the 404-on-unknown-id behaviour.
|
|
444
|
+
router.get('/builders/:id/profile', async (req, res) => {
|
|
445
|
+
const targetId = parseId(req, res, { code: 'bad_builder_id', positiveInt: true });
|
|
446
|
+
if (targetId === null) return;
|
|
447
|
+
try {
|
|
448
|
+
const b = await db.getBuilderById(targetId);
|
|
449
|
+
if (!b) return res.fail('builder_not_found', 404);
|
|
450
|
+
// Recent ships + shipped-count read the lifecycle port; the achievement
|
|
451
|
+
// shelf reads the reward port. Both resolveOptional — on a vanilla instance
|
|
452
|
+
// without economy the achievement shelf degrades to empty, not a 500.
|
|
453
|
+
const reward = seams.resolveOptional('reward');
|
|
454
|
+
const [shippedCount, recentShips, achievements] = await Promise.all([
|
|
455
|
+
lc().countShippedTasksForBuilder(targetId),
|
|
456
|
+
lc().recentShippedTasksByBuilder(targetId, 5),
|
|
457
|
+
reward ? reward.getBuilderAchievements(targetId) : [],
|
|
458
|
+
]);
|
|
459
|
+
// WHITELIST — only the leaderboard-equivalent public field set. Never spread
|
|
460
|
+
// the raw row: it carries anthropic_email / anthropic_user_id /
|
|
461
|
+
// monthly_budget_usd / system_role / box_blocked* / deactivated_reason,
|
|
462
|
+
// none of which are public.
|
|
463
|
+
const builder = {
|
|
464
|
+
id: b.id,
|
|
465
|
+
github_login: b.github_login,
|
|
466
|
+
display_name: b.display_name,
|
|
467
|
+
avatar_url: b.avatar_url,
|
|
468
|
+
rank: b.rank,
|
|
469
|
+
total_credits: b.total_credits,
|
|
470
|
+
karma: b.karma,
|
|
471
|
+
created_at: b.created_at,
|
|
472
|
+
preferred_disciplines: b.preferred_disciplines,
|
|
473
|
+
};
|
|
474
|
+
// Identity + counters change rarely; a short public cache matches
|
|
475
|
+
// /public/leaderboard's posture.
|
|
476
|
+
res.set('Cache-Control', 'public, max-age=60');
|
|
477
|
+
res.json({
|
|
478
|
+
builder,
|
|
479
|
+
shipped_count: shippedCount,
|
|
480
|
+
recent_ships: recentShips,
|
|
481
|
+
achievements,
|
|
482
|
+
});
|
|
483
|
+
} catch (err) {
|
|
484
|
+
console.error('[gds] GET /builders/:id/profile', err);
|
|
485
|
+
res.fail('profile_read_failed', { status: 500, message: 'internal error' });
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
// GET /builders/me/pending-rank-change — V3.R28 / #249 ceremony signal #3.
|
|
490
|
+
//
|
|
491
|
+
// Returns the calling builder's most recent rank-change credit_log row, or
|
|
492
|
+
// { change: null } when they've never had a rank change. The local
|
|
493
|
+
// SessionStart hook (`.claude/hooks/rank-change-greeting.js`) calls this on
|
|
494
|
+
// every session start and dedupes via a local "seen" marker — so the
|
|
495
|
+
// server doesn't need to track acknowledgment. That means this endpoint is
|
|
496
|
+
// a pure read; it never mutates anything.
|
|
497
|
+
//
|
|
498
|
+
// Why this lives on /builders/me/* (not /me/*): the route is part of the
|
|
499
|
+
// ceremony surface that V3.R28's touches[] explicitly covers
|
|
500
|
+
// (src/bongos/routes/builders.js). Routing it under /builders avoids editing
|
|
501
|
+
// /me.js (outside touches[]) while keeping the URL semantically clean.
|
|
502
|
+
//
|
|
503
|
+
// rank: any-builder — own rank-change history; mirrors /me/* posture.
|
|
504
|
+
router.get('/builders/me/pending-rank-change', auth.requireBuilder, async (req, res) => {
|
|
505
|
+
try {
|
|
506
|
+
const change = await db.getLatestRankChangeForBuilder(req.builder.id);
|
|
507
|
+
if (!change) {
|
|
508
|
+
return res.json({ change: null });
|
|
509
|
+
}
|
|
510
|
+
// Echo the broadcast text the hook will print. Built the same way the
|
|
511
|
+
// PATCH route built it, so the wording is identical to what went to
|
|
512
|
+
// Discord — that consistency is the ceremony.
|
|
513
|
+
const greeting = buildRankChangeBroadcast({
|
|
514
|
+
displayName: req.builder.display_name || req.builder.github_login,
|
|
515
|
+
direction: change.direction,
|
|
516
|
+
newRank: change.new_rank || req.builder.rank,
|
|
517
|
+
});
|
|
518
|
+
res.json({ change, greeting });
|
|
519
|
+
} catch (err) {
|
|
520
|
+
console.error('[gds] GET /builders/me/pending-rank-change', err);
|
|
521
|
+
res.fail('pending_rank_change_failed', { status: 500, message: 'internal error' });
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
return router;
|
|
526
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const auth = require('../auth');
|
|
3
|
+
|
|
4
|
+
module.exports = function buildHealthzRouter() {
|
|
5
|
+
const router = express.Router();
|
|
6
|
+
|
|
7
|
+
// rank: public — liveness probe; status.amazonprimea.com hits this anonymously.
|
|
8
|
+
router.get('/healthz', async (_req, res) => {
|
|
9
|
+
res.json({
|
|
10
|
+
ok: true,
|
|
11
|
+
auth_configured: auth.authConfigured(),
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return router;
|
|
16
|
+
};
|