@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,326 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// modules/sessions/db.js — the session-records db slice (BV1.R82 / ADR 0093 §1).
|
|
4
|
+
//
|
|
5
|
+
// The BFG session-inefficiency evaluator's data plane (ADR 0027): the
|
|
6
|
+
// session_records corpus the hall + the BFG search/deep-dive over. Carved out of
|
|
7
|
+
// the ~5k-LOC src/bongos/db.js monolith alongside its route (routes/sessions.js) and
|
|
8
|
+
// the BFG scorer (bfg.js). The module owns the QUERIES; the session_records table
|
|
9
|
+
// + its migrations stay in core migrations/ (pre-module-system; the additive rule
|
|
10
|
+
// — a NEW session migration belongs in modules/sessions/migrations/).
|
|
11
|
+
//
|
|
12
|
+
// THE BOUNDARY (the one rule): this slice reaches the kernel ONLY through the
|
|
13
|
+
// published doorway `../../src/module-api.js` — the shared `pool`, the `withTx`
|
|
14
|
+
// transaction primitive, and the economy `reward` kernel PORT (resolved, never a
|
|
15
|
+
// sibling-module require). It must never `require()` a core internal directly.
|
|
16
|
+
//
|
|
17
|
+
// The token-reward half (upsertSessionRecordWithReward) is the ONE place a
|
|
18
|
+
// session write touches another domain: it resolves the `reward` port and awards
|
|
19
|
+
// the cost-plus session token reward INSIDE its own transaction, passing the tx
|
|
20
|
+
// `client` so the credit write commits atomically with the digest upsert. The
|
|
21
|
+
// economy module computes the drachmae; sessions owns the digest row. This is the
|
|
22
|
+
// kernel-mediated module↔module seam (ADR 0083 / 0093 §2) — no module ever holds
|
|
23
|
+
// a reference to another.
|
|
24
|
+
|
|
25
|
+
const api = require('../../src/module-api');
|
|
26
|
+
const { pool } = api;
|
|
27
|
+
// `seams` is the doorway's kernel-mediated seam surface (resolveOptional/resolve).
|
|
28
|
+
// upsertSessionRecordWithReward resolves the economy `reward` port through it —
|
|
29
|
+
// the module↔module seam, never a sibling-module require (BV1.R77 / ADR 0093 §2).
|
|
30
|
+
const seams = api;
|
|
31
|
+
|
|
32
|
+
// -------------------------------------------------------------------------
|
|
33
|
+
// Session records (BFG session-inefficiency evaluator — 6D.1, ADR 0027)
|
|
34
|
+
// -------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
// upsertSessionRecord — store/refresh one session's scrubbed digest. Keyed on
|
|
37
|
+
// session_id (the Claude Code CLAUDE_CODE_SESSION_ID), so a session that ships
|
|
38
|
+
// several tasks upserts ONCE and accumulates task_ids (set-union) rather than
|
|
39
|
+
// creating duplicate rows. detail + metrics are jsonb; task_ids is bigint[].
|
|
40
|
+
// builderId is taken from the authenticated caller at the route — never the
|
|
41
|
+
// body — so a builder can only ever write their OWN session.
|
|
42
|
+
// upsertSessionRecordTx — the session-digest upsert SQL, parameterized on an
|
|
43
|
+
// `executor` (a pg Pool OR a connected client) so it can run standalone
|
|
44
|
+
// (auto-commit) or inside a transaction alongside the token-reward award.
|
|
45
|
+
// `modelUsage` is the per-model token map (task 1005) stored verbatim as jsonb
|
|
46
|
+
// for audit + priced server-side for the cost-plus reward.
|
|
47
|
+
async function upsertSessionRecordTx(executor, {
|
|
48
|
+
sessionId,
|
|
49
|
+
builderId,
|
|
50
|
+
taskIds = [],
|
|
51
|
+
drachmaeEarned = 0,
|
|
52
|
+
totalTokens = 0,
|
|
53
|
+
durationSeconds = null,
|
|
54
|
+
startedAt = null,
|
|
55
|
+
endedAt = null,
|
|
56
|
+
detail = [],
|
|
57
|
+
metrics = {},
|
|
58
|
+
modelUsage = {},
|
|
59
|
+
}) {
|
|
60
|
+
const ids = Array.isArray(taskIds)
|
|
61
|
+
? taskIds.map((n) => Number(n)).filter(Number.isFinite)
|
|
62
|
+
: [];
|
|
63
|
+
const { rows } = await executor.query(
|
|
64
|
+
`INSERT INTO session_records
|
|
65
|
+
(session_id, builder_id, task_ids, drachmae_earned, total_tokens,
|
|
66
|
+
duration_seconds, started_at, ended_at, detail, metrics, model_usage)
|
|
67
|
+
VALUES ($1, $2, $3::bigint[], $4, $5, $6, $7, $8, $9::jsonb, $10::jsonb, $11::jsonb)
|
|
68
|
+
ON CONFLICT (session_id) DO UPDATE SET
|
|
69
|
+
task_ids = (
|
|
70
|
+
SELECT COALESCE(array_agg(DISTINCT e ORDER BY e), '{}')
|
|
71
|
+
FROM unnest(session_records.task_ids || EXCLUDED.task_ids) AS e
|
|
72
|
+
),
|
|
73
|
+
-- drachmae accumulates: each ship uploads once with the credit_log delta
|
|
74
|
+
-- for THAT ship's task(s), so summing across uploads = the session total.
|
|
75
|
+
drachmae_earned = session_records.drachmae_earned + EXCLUDED.drachmae_earned,
|
|
76
|
+
total_tokens = EXCLUDED.total_tokens,
|
|
77
|
+
duration_seconds = EXCLUDED.duration_seconds,
|
|
78
|
+
started_at = EXCLUDED.started_at,
|
|
79
|
+
ended_at = EXCLUDED.ended_at,
|
|
80
|
+
detail = EXCLUDED.detail,
|
|
81
|
+
metrics = EXCLUDED.metrics,
|
|
82
|
+
model_usage = EXCLUDED.model_usage,
|
|
83
|
+
uploaded_at = now()
|
|
84
|
+
-- Ownership guard: a row can only ever be updated by its own builder, so a
|
|
85
|
+
-- builder who guesses another's session_id cannot overwrite their record.
|
|
86
|
+
WHERE session_records.builder_id = EXCLUDED.builder_id
|
|
87
|
+
RETURNING id, session_id, builder_id, task_ids, drachmae_earned,
|
|
88
|
+
total_tokens, duration_seconds, uploaded_at`,
|
|
89
|
+
[
|
|
90
|
+
sessionId,
|
|
91
|
+
builderId,
|
|
92
|
+
ids,
|
|
93
|
+
Math.trunc(Number(drachmaeEarned) || 0),
|
|
94
|
+
Math.trunc(Number(totalTokens) || 0),
|
|
95
|
+
durationSeconds == null ? null : Math.trunc(Number(durationSeconds)),
|
|
96
|
+
startedAt,
|
|
97
|
+
endedAt,
|
|
98
|
+
JSON.stringify(detail ?? []),
|
|
99
|
+
JSON.stringify(metrics ?? {}),
|
|
100
|
+
JSON.stringify(modelUsage ?? {}),
|
|
101
|
+
]
|
|
102
|
+
);
|
|
103
|
+
return rows[0] || null; // null only on the ownership-guard no-op (foreign session_id)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Standalone (auto-commit) upsert — preserved signature for the backfill script
|
|
107
|
+
// + tests that call it directly on the pool. No token reward on this path.
|
|
108
|
+
async function upsertSessionRecord(opts) {
|
|
109
|
+
return upsertSessionRecordTx(pool, opts);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// upsertSessionRecordWithReward — ONE transaction: upsert the session digest
|
|
113
|
+
// (incl. model_usage), then compute + award the idempotent cost-plus token
|
|
114
|
+
// reward (task 1005, ADR 0054) and mirror token_reward_drachmae onto the row.
|
|
115
|
+
// Returns the record augmented with { tokenReward }. The token reward is a
|
|
116
|
+
// SEPARATE credit_log row (reason='session.token_reward'); total_credits is
|
|
117
|
+
// bumped by the credit_log trigger only, never double-counted here.
|
|
118
|
+
async function upsertSessionRecordWithReward(opts) {
|
|
119
|
+
return api.withTx(async (client) => {
|
|
120
|
+
const record = await upsertSessionRecordTx(client, opts);
|
|
121
|
+
let tokenReward = { drachmae: 0, trueCostUsd: 0, awarded: false, unknownModels: [] };
|
|
122
|
+
if (record) {
|
|
123
|
+
// record is non-null only when the ownership guard passed (the row is the
|
|
124
|
+
// caller's), so the reward is always attributed to the verified owner.
|
|
125
|
+
// Token reward lives in modules/economy/ (BV1.R77 / ADR 0093 §1-2):
|
|
126
|
+
// resolve the `reward` kernel port and award inside this same txn (the
|
|
127
|
+
// module↔module seam — no sibling require).
|
|
128
|
+
// task 1676: pass totalTokens so the reward can fall back to pricing the
|
|
129
|
+
// session's real token total when modelUsage is empty/unpriceable — the
|
|
130
|
+
// dev-box/CI agent path that historically paid $0 cost-plus (ADR 0097).
|
|
131
|
+
tokenReward = await seams.resolveOptional('reward').awardSessionTokenReward(
|
|
132
|
+
client, opts.builderId, opts.sessionId, opts.modelUsage || {}, opts.totalTokens || 0
|
|
133
|
+
);
|
|
134
|
+
if (tokenReward.awarded && tokenReward.drachmae > 0) {
|
|
135
|
+
await client.query(
|
|
136
|
+
`UPDATE session_records
|
|
137
|
+
SET token_reward_drachmae = token_reward_drachmae + $2
|
|
138
|
+
WHERE session_id = $1 AND builder_id = $3`,
|
|
139
|
+
[opts.sessionId, tokenReward.drachmae, opts.builderId]
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return record ? { ...record, tokenReward } : null;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ---- 6D.2: session search + fetch (read side, ADR 0027) -------------------
|
|
148
|
+
|
|
149
|
+
// Safe ORDER BY whitelist — the ONLY value interpolated into the search SQL, so
|
|
150
|
+
// it must never come raw from input. Unknown keys fall back to 'recent'. Pure +
|
|
151
|
+
// exported so the mapping is unit-tested (SQL-injection guard).
|
|
152
|
+
const SESSION_ORDER = Object.freeze({
|
|
153
|
+
recent: 'sr.uploaded_at DESC',
|
|
154
|
+
tool_errors: "COALESCE((sr.metrics->>'tool_error_count')::int, 0) DESC, sr.uploaded_at DESC",
|
|
155
|
+
tokens: 'sr.total_tokens DESC, sr.uploaded_at DESC',
|
|
156
|
+
duration: 'sr.duration_seconds DESC NULLS LAST, sr.uploaded_at DESC',
|
|
157
|
+
drachmae: 'sr.drachmae_earned DESC, sr.uploaded_at DESC',
|
|
158
|
+
});
|
|
159
|
+
function resolveSessionOrder(key) {
|
|
160
|
+
return Object.prototype.hasOwnProperty.call(SESSION_ORDER, key) ? SESSION_ORDER[key] : SESSION_ORDER.recent;
|
|
161
|
+
}
|
|
162
|
+
function clampSessionLimit(n) {
|
|
163
|
+
if (n == null) return 25; // absent → default (null/undefined treated alike)
|
|
164
|
+
const x = Number(n);
|
|
165
|
+
if (!Number.isFinite(x)) return 25;
|
|
166
|
+
return Math.max(1, Math.min(100, Math.trunc(x)));
|
|
167
|
+
}
|
|
168
|
+
// Pagination offset for the corpus search. Absent/garbage → 0 (first page).
|
|
169
|
+
// Floors at 0 and caps at a sane ceiling so a hostile ?offset=1e30 can't ask
|
|
170
|
+
// Postgres to skip an absurd row count. Pure + exported (unit-tested).
|
|
171
|
+
function clampSessionOffset(n) {
|
|
172
|
+
if (n == null) return 0;
|
|
173
|
+
const x = Number(n);
|
|
174
|
+
if (!Number.isFinite(x)) return 0;
|
|
175
|
+
return Math.max(0, Math.min(1_000_000, Math.trunc(x)));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// sessionFilterClause — the shared parameterized WHERE used by BOTH searchSessions
|
|
179
|
+
// (the page) and summarizeSessions (the corpus-wide tally), so the two can never
|
|
180
|
+
// drift out of sync. Every filter is a bound parameter ($1..$7); nothing from the
|
|
181
|
+
// caller is interpolated. Returns { clause, params } where clause is the body of
|
|
182
|
+
// a WHERE (no leading 'WHERE'). Pure.
|
|
183
|
+
function sessionFilterClause(f = {}) {
|
|
184
|
+
const clause = `($1::text IS NULL OR b.rank = $1)
|
|
185
|
+
AND ($2::int IS NULL OR b.karma >= $2)
|
|
186
|
+
AND ($3::int IS NULL OR sr.drachmae_earned >= $3)
|
|
187
|
+
AND ($4::bigint IS NULL OR sr.total_tokens >= $4)
|
|
188
|
+
AND ($5::int IS NULL OR COALESCE((sr.metrics->>'tool_error_count')::int, 0) >= $5)
|
|
189
|
+
AND ($6::int IS NULL OR sr.duration_seconds >= $6)
|
|
190
|
+
AND ($7::int IS NULL OR (now() - b.created_at) <= ($7 * interval '1 day'))`;
|
|
191
|
+
const params = [
|
|
192
|
+
f.rank ?? null,
|
|
193
|
+
f.minKarma ?? null,
|
|
194
|
+
f.minDrachmae ?? null,
|
|
195
|
+
f.minTokens ?? null,
|
|
196
|
+
f.minToolErrors ?? null,
|
|
197
|
+
f.minDurationSec ?? null,
|
|
198
|
+
f.maxTenureDays ?? null,
|
|
199
|
+
];
|
|
200
|
+
return { clause, params };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Summary projection (NO detail jsonb — that's only returned by getSessionById
|
|
204
|
+
// for a deep-dive). Joins builders for the rank/karma/drachmae/tenure facets.
|
|
205
|
+
const SESSION_SUMMARY_COLS = `
|
|
206
|
+
sr.id, sr.session_id, sr.builder_id, b.github_login, b.rank, b.karma,
|
|
207
|
+
b.total_credits AS builder_drachmae,
|
|
208
|
+
ROUND(EXTRACT(EPOCH FROM (now() - b.created_at)) / 86400)::int AS tenure_days,
|
|
209
|
+
sr.task_ids, sr.drachmae_earned, sr.total_tokens, sr.duration_seconds,
|
|
210
|
+
COALESCE((sr.metrics->>'tool_error_count')::int, 0) AS tool_errors,
|
|
211
|
+
COALESCE((sr.metrics->>'assistant_turns')::int, 0) AS assistant_turns,
|
|
212
|
+
sr.uploaded_at`;
|
|
213
|
+
|
|
214
|
+
// searchSessions — cross-builder search over the corpus, filtered by session
|
|
215
|
+
// facets AND joined builder facets (rank / karma / drachmae / tenure). All
|
|
216
|
+
// filters are bound parameters; ORDER BY + LIMIT are whitelisted/clamped, so
|
|
217
|
+
// there is no injection surface. Caller (route) gates this to the BFG principal
|
|
218
|
+
// (Archon for now) and audits it.
|
|
219
|
+
async function searchSessions(filters = {}) {
|
|
220
|
+
const f = filters || {};
|
|
221
|
+
const orderBy = resolveSessionOrder(f.order);
|
|
222
|
+
const limit = clampSessionLimit(f.limit);
|
|
223
|
+
const offset = clampSessionOffset(f.offset);
|
|
224
|
+
const { clause, params } = sessionFilterClause(f);
|
|
225
|
+
// limit/offset are clamped integers, never raw input — safe to interpolate;
|
|
226
|
+
// keeping them out of the param list keeps the $-indices aligned with the
|
|
227
|
+
// shared clause (which owns $1..$7).
|
|
228
|
+
const { rows } = await pool.query(
|
|
229
|
+
`SELECT ${SESSION_SUMMARY_COLS}
|
|
230
|
+
FROM session_records sr
|
|
231
|
+
JOIN builders b ON b.id = sr.builder_id
|
|
232
|
+
WHERE ${clause}
|
|
233
|
+
ORDER BY ${orderBy}
|
|
234
|
+
LIMIT ${limit} OFFSET ${offset}`,
|
|
235
|
+
params
|
|
236
|
+
);
|
|
237
|
+
return rows;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// summarizeSessions — corpus-wide aggregates for the SAME filter set as
|
|
241
|
+
// searchSessions (so the Ledger's "Tally" reflects every matching session, not
|
|
242
|
+
// just the visible page). Returns total row count + summed token/turn/error/
|
|
243
|
+
// drachmae figures + distinct-builder count. Uses the shared filter clause so it
|
|
244
|
+
// can't drift from the page query. Read-only; the route gates + audits it.
|
|
245
|
+
async function summarizeSessions(filters = {}) {
|
|
246
|
+
const { clause, params } = sessionFilterClause(filters || {});
|
|
247
|
+
const { rows } = await pool.query(
|
|
248
|
+
`SELECT
|
|
249
|
+
COUNT(*)::int AS total,
|
|
250
|
+
COUNT(DISTINCT sr.builder_id)::int AS builders,
|
|
251
|
+
COALESCE(SUM(sr.total_tokens), 0)::bigint AS tokens,
|
|
252
|
+
COALESCE(SUM(COALESCE((sr.metrics->>'assistant_turns')::int, 0)),0)::bigint AS turns,
|
|
253
|
+
COALESCE(SUM(COALESCE((sr.metrics->>'tool_error_count')::int, 0)),0)::bigint AS tool_errors,
|
|
254
|
+
COALESCE(SUM(sr.drachmae_earned), 0)::bigint AS drachmae
|
|
255
|
+
FROM session_records sr
|
|
256
|
+
JOIN builders b ON b.id = sr.builder_id
|
|
257
|
+
WHERE ${clause}`,
|
|
258
|
+
params
|
|
259
|
+
);
|
|
260
|
+
const r = rows[0] || {};
|
|
261
|
+
// bigint columns arrive as strings from pg — coerce to Number for the JSON
|
|
262
|
+
// (these totals are well within Number's safe-integer range).
|
|
263
|
+
return {
|
|
264
|
+
total: Number(r.total) || 0,
|
|
265
|
+
builders: Number(r.builders) || 0,
|
|
266
|
+
tokens: Number(r.tokens) || 0,
|
|
267
|
+
turns: Number(r.turns) || 0,
|
|
268
|
+
tool_errors: Number(r.tool_errors) || 0,
|
|
269
|
+
drachmae: Number(r.drachmae) || 0,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// getSessionById — one session's FULL record (incl. detail jsonb) for deep-dive.
|
|
274
|
+
async function getSessionById(id) {
|
|
275
|
+
const { rows } = await pool.query(
|
|
276
|
+
`SELECT ${SESSION_SUMMARY_COLS}, sr.detail, sr.metrics
|
|
277
|
+
FROM session_records sr
|
|
278
|
+
JOIN builders b ON b.id = sr.builder_id
|
|
279
|
+
WHERE sr.id = $1`,
|
|
280
|
+
[Number(id)]
|
|
281
|
+
);
|
|
282
|
+
return rows[0] || null;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// listSessionsByBuilder — a builder's OWN sessions (self-serve summary list).
|
|
286
|
+
async function listSessionsByBuilder(builderId, limit = 25) {
|
|
287
|
+
const { rows } = await pool.query(
|
|
288
|
+
`SELECT ${SESSION_SUMMARY_COLS}
|
|
289
|
+
FROM session_records sr
|
|
290
|
+
JOIN builders b ON b.id = sr.builder_id
|
|
291
|
+
WHERE sr.builder_id = $1
|
|
292
|
+
ORDER BY sr.uploaded_at DESC
|
|
293
|
+
LIMIT ${clampSessionLimit(limit)}`,
|
|
294
|
+
[builderId]
|
|
295
|
+
);
|
|
296
|
+
return rows;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// filterTaskIdsClaimedBy — the subset of taskIds the builder actually claimed
|
|
300
|
+
// (the ownership signal for a session). Used by POST /sessions to drop foreign
|
|
301
|
+
// task IDs so a builder can't pollute their session_records.task_ids with work
|
|
302
|
+
// they never did.
|
|
303
|
+
async function filterTaskIdsClaimedBy(builderId, taskIds) {
|
|
304
|
+
const ids = Array.isArray(taskIds) ? taskIds.map(Number).filter(Number.isFinite) : [];
|
|
305
|
+
if (ids.length === 0) return [];
|
|
306
|
+
const { rows } = await pool.query(
|
|
307
|
+
`SELECT DISTINCT task_id FROM claims WHERE builder_id = $1 AND task_id = ANY($2::bigint[])`,
|
|
308
|
+
[builderId, ids]
|
|
309
|
+
);
|
|
310
|
+
return rows.map((r) => Number(r.task_id));
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
module.exports = {
|
|
314
|
+
// write side (6D.1)
|
|
315
|
+
upsertSessionRecord,
|
|
316
|
+
upsertSessionRecordWithReward, // route entry point — upsert + token reward (task 1005)
|
|
317
|
+
// search + fetch (6D.2)
|
|
318
|
+
searchSessions,
|
|
319
|
+
summarizeSessions,
|
|
320
|
+
getSessionById,
|
|
321
|
+
listSessionsByBuilder,
|
|
322
|
+
filterTaskIdsClaimedBy,
|
|
323
|
+
resolveSessionOrder,
|
|
324
|
+
clampSessionLimit,
|
|
325
|
+
clampSessionOffset,
|
|
326
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"key": "sessions",
|
|
3
|
+
"title": "Sessions & BFG (session corpus · efficiency eval)",
|
|
4
|
+
"description": "The session-records corpus + its data plane (POST /sessions upload, the Archon-gated cross-builder /sessions/search + /sessions/:id deep-dive), the BFG 'read-the-room' cross-builder scorer (ADR 0026 §6B), and the session-pulse / stale-claim heartbeat helpers. A core-domain module carved out of the GDS core in BV1.R82 (ADR 0093 §1); default-on because every instance records its builders' sessions for the BFG. Like the memory module, sessions registers no port — core never calls back into it: the ship-time digest write is an HTTP POST to the module's own /sessions route, and the only outward dependency is the economy `reward` kernel PORT it resolves (session token reward + sumCreditsForTasks) at upload time.",
|
|
5
|
+
"coreVersion": "^1.10.0",
|
|
6
|
+
"default": true,
|
|
7
|
+
"contributes": { "routes": ["sessions"] },
|
|
8
|
+
"provides": [],
|
|
9
|
+
"consumes": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// modules/sessions/pulse.js — GDS session-pulse + stale-claim helpers.
|
|
2
|
+
//
|
|
3
|
+
// Task #37 — BUCKET C (Auto-logging). Provides the SQL plumbing for a
|
|
4
|
+
// heartbeat-driven stale-claim detector. Pure DB helpers; no Express
|
|
5
|
+
// routes here (route wiring is OUT of touches[] for this task and
|
|
6
|
+
// deferred — see follow-up notes below).
|
|
7
|
+
//
|
|
8
|
+
// CARVED into modules/sessions/ (BV1.R82 / ADR 0093 §1) — a session-domain lib.
|
|
9
|
+
// Reaches the kernel only through the published doorway `../../src/module-api.js`
|
|
10
|
+
// (the shared `pool`); the CLI shell stays at scripts/gds/pulse.js.
|
|
11
|
+
//
|
|
12
|
+
// -------------------------------------------------------------------------
|
|
13
|
+
// Open questions resolved per task description:
|
|
14
|
+
//
|
|
15
|
+
// 1. claims.pulse_lost_at column does NOT exist in migration 006
|
|
16
|
+
// (006 only adds the session_pulses table itself with PK claim_id +
|
|
17
|
+
// columns builder_id, last_pulse_at). Per the task's pragmatic-(b)
|
|
18
|
+
// decision, we DO NOT add a new migration here — adding one would
|
|
19
|
+
// introduce migrations/008_*.sql to touches[] and break drift
|
|
20
|
+
// discipline. Instead, sweepStaleClaims() returns the stale claim
|
|
21
|
+
// rows as data; a follow-up task is expected to add the marker
|
|
22
|
+
// column + UPDATE write + builder surface in /builder-start.
|
|
23
|
+
//
|
|
24
|
+
// 2. POST /api/gds/pulse route is NOT wired here — routes.js is out
|
|
25
|
+
// of touches[]. recordPulse() is exported for whichever future
|
|
26
|
+
// request handler is created. The CLI shell at scripts/gds/pulse.js
|
|
27
|
+
// posts to the intended endpoint and will start working once the
|
|
28
|
+
// route is mounted.
|
|
29
|
+
//
|
|
30
|
+
// Follow-up work (file new tasks when picked up):
|
|
31
|
+
// a) New migration adding claims.pulse_lost_at timestamptz.
|
|
32
|
+
// b) Route: POST /api/gds/pulse → recordPulse() (auth + claim
|
|
33
|
+
// ownership check).
|
|
34
|
+
// c) sweepStaleClaims() side-effect: UPDATE claims
|
|
35
|
+
// SET pulse_lost_at = now() WHERE id = ANY(...).
|
|
36
|
+
// d) Periodic sweep — 5-min setInterval inside the running Node
|
|
37
|
+
// process, or scheduled task.
|
|
38
|
+
// e) /builder-start surfaces "your previous claim went silent" using
|
|
39
|
+
// getStaleClaimsForBuilder().
|
|
40
|
+
// -------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
const { pool } = require('../../src/module-api');
|
|
43
|
+
|
|
44
|
+
// Record a heartbeat for a claim. Idempotent UPSERT — the PK is
|
|
45
|
+
// claim_id so repeated pulses just bump last_pulse_at.
|
|
46
|
+
//
|
|
47
|
+
// Caller is responsible for verifying the builder actually owns the
|
|
48
|
+
// claim (do this in the route handler, not here).
|
|
49
|
+
async function recordPulse(claimId, builderId) {
|
|
50
|
+
if (!Number.isFinite(Number(claimId)) || !Number.isFinite(Number(builderId))) {
|
|
51
|
+
throw new Error('recordPulse: claimId and builderId must be numeric');
|
|
52
|
+
}
|
|
53
|
+
const { rows } = await pool.query(
|
|
54
|
+
`INSERT INTO session_pulses (claim_id, builder_id, last_pulse_at)
|
|
55
|
+
VALUES ($1, $2, now())
|
|
56
|
+
ON CONFLICT (claim_id) DO UPDATE
|
|
57
|
+
SET last_pulse_at = now(),
|
|
58
|
+
builder_id = EXCLUDED.builder_id
|
|
59
|
+
RETURNING claim_id, builder_id, last_pulse_at`,
|
|
60
|
+
[Number(claimId), Number(builderId)]
|
|
61
|
+
);
|
|
62
|
+
return rows[0];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Identify claims that have gone silent. A claim is stale when it is
|
|
66
|
+
// still open (released_at IS NULL) AND either:
|
|
67
|
+
// (a) it has a pulse row whose last_pulse_at is older than the
|
|
68
|
+
// threshold, or
|
|
69
|
+
// (b) it has no pulse row at all AND was claimed_at longer ago than
|
|
70
|
+
// the threshold (i.e. the builder never pulsed once, and they've
|
|
71
|
+
// had long enough that we assume they crashed).
|
|
72
|
+
//
|
|
73
|
+
// Returns: array of { claim_id, task_id, builder_id, claimed_at,
|
|
74
|
+
// last_pulse_at } — caller (a future scheduled job) decides whether to
|
|
75
|
+
// stamp a marker, release the claim, or notify the builder.
|
|
76
|
+
//
|
|
77
|
+
// This function is READ-ONLY by design (see open question #1 above);
|
|
78
|
+
// the write-side marker is deferred to a follow-up task that owns
|
|
79
|
+
// the migration.
|
|
80
|
+
async function sweepStaleClaims({ thresholdMin = 30 } = {}) {
|
|
81
|
+
const threshold = Number(thresholdMin);
|
|
82
|
+
if (!Number.isFinite(threshold) || threshold <= 0) {
|
|
83
|
+
throw new Error('sweepStaleClaims: thresholdMin must be a positive number');
|
|
84
|
+
}
|
|
85
|
+
const { rows } = await pool.query(
|
|
86
|
+
`SELECT c.id AS claim_id,
|
|
87
|
+
c.task_id AS task_id,
|
|
88
|
+
c.builder_id AS builder_id,
|
|
89
|
+
c.claimed_at AS claimed_at,
|
|
90
|
+
sp.last_pulse_at AS last_pulse_at
|
|
91
|
+
FROM claims c
|
|
92
|
+
LEFT JOIN session_pulses sp ON sp.claim_id = c.id
|
|
93
|
+
WHERE c.released_at IS NULL
|
|
94
|
+
AND (
|
|
95
|
+
(sp.last_pulse_at IS NOT NULL
|
|
96
|
+
AND sp.last_pulse_at < now() - ($1::int * interval '1 minute'))
|
|
97
|
+
OR (sp.last_pulse_at IS NULL
|
|
98
|
+
AND c.claimed_at < now() - ($1::int * interval '1 minute'))
|
|
99
|
+
)
|
|
100
|
+
ORDER BY c.claimed_at ASC`,
|
|
101
|
+
[threshold]
|
|
102
|
+
);
|
|
103
|
+
return rows;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Stale claims that belong to a specific builder. Used by the future
|
|
107
|
+
// /builder-start surface to warn the builder when their previous
|
|
108
|
+
// claim has gone silent and may need release/reclaim.
|
|
109
|
+
//
|
|
110
|
+
// Today, "stale" is computed the same way as sweepStaleClaims() —
|
|
111
|
+
// once a marker column exists (follow-up a), this can pivot to read
|
|
112
|
+
// claims.pulse_lost_at IS NOT NULL instead.
|
|
113
|
+
async function getStaleClaimsForBuilder(builderId, { thresholdMin = 30 } = {}) {
|
|
114
|
+
const builder = Number(builderId);
|
|
115
|
+
const threshold = Number(thresholdMin);
|
|
116
|
+
if (!Number.isFinite(builder)) {
|
|
117
|
+
throw new Error('getStaleClaimsForBuilder: builderId must be numeric');
|
|
118
|
+
}
|
|
119
|
+
if (!Number.isFinite(threshold) || threshold <= 0) {
|
|
120
|
+
throw new Error('getStaleClaimsForBuilder: thresholdMin must be a positive number');
|
|
121
|
+
}
|
|
122
|
+
const { rows } = await pool.query(
|
|
123
|
+
`SELECT c.id AS claim_id,
|
|
124
|
+
c.task_id AS task_id,
|
|
125
|
+
c.builder_id AS builder_id,
|
|
126
|
+
c.claimed_at AS claimed_at,
|
|
127
|
+
c.worktree_name AS worktree_name,
|
|
128
|
+
sp.last_pulse_at AS last_pulse_at
|
|
129
|
+
FROM claims c
|
|
130
|
+
LEFT JOIN session_pulses sp ON sp.claim_id = c.id
|
|
131
|
+
WHERE c.released_at IS NULL
|
|
132
|
+
AND c.builder_id = $1
|
|
133
|
+
AND (
|
|
134
|
+
(sp.last_pulse_at IS NOT NULL
|
|
135
|
+
AND sp.last_pulse_at < now() - ($2::int * interval '1 minute'))
|
|
136
|
+
OR (sp.last_pulse_at IS NULL
|
|
137
|
+
AND c.claimed_at < now() - ($2::int * interval '1 minute'))
|
|
138
|
+
)
|
|
139
|
+
ORDER BY c.claimed_at ASC`,
|
|
140
|
+
[builder, threshold]
|
|
141
|
+
);
|
|
142
|
+
return rows;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
module.exports = {
|
|
146
|
+
recordPulse,
|
|
147
|
+
sweepStaleClaims,
|
|
148
|
+
getStaleClaimsForBuilder,
|
|
149
|
+
};
|