@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,418 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Server-owned publish reconciler (task 1134) — the durable cure for the
|
|
4
|
+
// "strands at confirmed" failure class.
|
|
5
|
+
//
|
|
6
|
+
// WHY THIS EXISTS
|
|
7
|
+
// A server-mediated publish (ADR 0055) is ASYNCHRONOUS: a dev box uploads its
|
|
8
|
+
// branch, the server pushes + opens the PR + arms auto-merge, then GitHub runs
|
|
9
|
+
// the required checks, merges, and Actions deploys to prod. The box's ship.js
|
|
10
|
+
// only POLLS for ~9 min (pollServerPublish) and then EXITS, printing "it flips to
|
|
11
|
+
// shipped on its own". But the confirmed→shipped transition lived in exactly ONE
|
|
12
|
+
// place — the GET /tasks/:id/publish-status reconcile-on-read (routes/tasks.js).
|
|
13
|
+
// That flip can ONLY happen while a client keeps issuing that GET. Real CI (check
|
|
14
|
+
// queue + merge queue + deploy) routinely finishes AFTER the box has stopped
|
|
15
|
+
// polling, so nothing ever re-checks and the task row freezes at 'confirmed'
|
|
16
|
+
// forever — even though prod is live. Every prior point-fix (1025/1027/1037/1041/
|
|
17
|
+
// 1045/1046/1049/1050/1052/1068) compensated for a symptom of this one gap:
|
|
18
|
+
// "the box must stay alive and keep polling to finish its OWN ship."
|
|
19
|
+
//
|
|
20
|
+
// THE FIX. Move the last mile to the SERVER, where it belongs. A periodic sweep
|
|
21
|
+
// (this module) finds every 'confirmed' task, derives its branch from the latest
|
|
22
|
+
// claim's worktree_name, asks the server's own publish-status (PR merged + deploy
|
|
23
|
+
// succeeded?), and on a confirmed land runs the EXACT db.shipTask +
|
|
24
|
+
// ship-broadcast.postShipBroadcast the publish-status route already runs. The land
|
|
25
|
+
// no longer depends on the shipper's CLI being alive — it works for EVERY builder,
|
|
26
|
+
// on a box, a laptop, or a desktop session, and retroactively heals strands left
|
|
27
|
+
// by a session that exited early. Idempotent: shipTask throws TASK_NOT_CONFIRMED
|
|
28
|
+
// if a client poll (or a prior sweep) already flipped it, so a sweep racing the
|
|
29
|
+
// route never double-ships nor double-broadcasts.
|
|
30
|
+
//
|
|
31
|
+
// task 1313 — close the residual strand class the PR-keyed land-check still missed.
|
|
32
|
+
// getPublishStatus finds a land by looking up the head branch's PR. Three shapes
|
|
33
|
+
// defeat that and stranded tasks at 'confirmed' even though the work was live on
|
|
34
|
+
// main: (1) a merge that DELETES the branch leaves no PR discoverable by head, so
|
|
35
|
+
// pr_state stays 'none' forever; (2) a claim with no worktree_name has no branch to
|
|
36
|
+
// look up at all (these were dropped from the feed entirely); (3) a corrupt head_sha
|
|
37
|
+
// / branch-name mismatch. The fix adds a head_sha land-check — is the claim's commit
|
|
38
|
+
// an ancestor of origin/main (github-push.isAncestorOfDefaultBranch)? — that proves
|
|
39
|
+
// the land from the COMMIT, not the PR. The feed now also returns no-worktree rows.
|
|
40
|
+
// An 8-strand backlog (incl. a Xenos's onboarding ships that never counted) is what
|
|
41
|
+
// surfaced this.
|
|
42
|
+
//
|
|
43
|
+
// Mirrors the in-process poller precedent (src/bongos/uptime-poller.js) and the
|
|
44
|
+
// Discord reconcile timers (src/bongos/discord-bot.js): unref'd timers (never hold
|
|
45
|
+
// the process open), best-effort (a GitHub/DB hiccup logs and waits for the next
|
|
46
|
+
// sweep), and a no-op when the server holds no push credential (local dev, tests).
|
|
47
|
+
|
|
48
|
+
const githubPush = require('./github-push');
|
|
49
|
+
const seams = require('../../src/module-api');
|
|
50
|
+
const conflictResolve = require('./conflict-resolve');
|
|
51
|
+
|
|
52
|
+
// 5-min cadence: frequent enough that a strand heals within minutes of CI
|
|
53
|
+
// finishing, cheap enough that the GitHub API cost is negligible (2 calls per
|
|
54
|
+
// confirmed task per sweep, a handful of tasks). Override for tests/ops.
|
|
55
|
+
const INTERVAL_MS = Number(process.env.PUBLISH_RECONCILE_MS) || 5 * 60_000;
|
|
56
|
+
// A first sweep shortly after boot so a strand left by the previous process (e.g.
|
|
57
|
+
// a deploy that restarted the server mid-poll) heals fast, not on the next tick.
|
|
58
|
+
const FIRST_SWEEP_DELAY_MS = Number(process.env.PUBLISH_RECONCILE_FIRST_MS) || 30_000;
|
|
59
|
+
// Bound the per-sweep work. There are rarely more than a handful of confirmed
|
|
60
|
+
// tasks; this is a runaway guard, not an expected limit.
|
|
61
|
+
const SWEEP_LIMIT = 100;
|
|
62
|
+
// Observability (task 1546 / blocker 47): a confirmed task the sweep cannot prove
|
|
63
|
+
// landed and that is OLDER than this is a strand — credited but with no provable
|
|
64
|
+
// land — and gets a WARN. Default 30 min; tune/disable via env.
|
|
65
|
+
const STALE_CONFIRMED_MS = Number(process.env.PUBLISH_RECONCILE_STALE_MS) || 30 * 60_000;
|
|
66
|
+
// task 1915: cap the speculative regen-heal per branch so a genuine treadmill (main
|
|
67
|
+
// churning faster than CI clears a re-freshened branch) can't loop forever. In-memory
|
|
68
|
+
// per process — a restart resets the guard, which is fine (heals are idempotent and
|
|
69
|
+
// a persistently-red branch surfaces via the STALE strand WARN above).
|
|
70
|
+
const MAX_STALE_HEAL_ATTEMPTS = Number(process.env.PUBLISH_RECONCILE_MAX_HEAL) || 3;
|
|
71
|
+
const healAttempts = new Map(); // branch -> regen-heal attempts this process
|
|
72
|
+
|
|
73
|
+
let intervalTimer = null;
|
|
74
|
+
let firstTimer = null;
|
|
75
|
+
|
|
76
|
+
// task 1915 — is this mergeIfGreen result the "mergeable but a check is RED" shape
|
|
77
|
+
// whose commonest cause is a STALE generated index (see refreshStaleGenerated)? Only
|
|
78
|
+
// a PR GitHub reports as MERGEABLE (no conflict — a CONFLICTING PR is the
|
|
79
|
+
// resolveBranchConflicts path) whose block reason is a failing check qualifies; a
|
|
80
|
+
// pending/among-computing/review-gated PR is left to settle on its own.
|
|
81
|
+
function couldBeStaleGenerated(m) {
|
|
82
|
+
if (!m || m.merged || m.merged_now) return false;
|
|
83
|
+
if (m.pr_state !== 'open') return false;
|
|
84
|
+
if (m.mergeable !== 'MERGEABLE') return false;
|
|
85
|
+
const reason = String(m.reason || '');
|
|
86
|
+
return /^failing_check:/.test(reason) || /^non_required_check_failing:/.test(reason);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// One sweep. Pure w.r.t. injected deps (db / githubPush / emit / loggers)
|
|
90
|
+
// so the whole thing is unit-tested with no DB and no network. Returns a summary
|
|
91
|
+
// { skipped?, checked, reconciled, errors } for observability + tests.
|
|
92
|
+
async function runSweep(deps = {}) {
|
|
93
|
+
const db = deps.db || require('./db');
|
|
94
|
+
const push = deps.githubPush || githubPush;
|
|
95
|
+
const emit = deps.emit || seams.emitAsync;
|
|
96
|
+
const resolver = deps.conflictResolve || conflictResolve;
|
|
97
|
+
const logFn = deps.log || console.log;
|
|
98
|
+
const errFn = deps.error || console.error;
|
|
99
|
+
|
|
100
|
+
// No server push credential (local dev, tests, an un-provisioned host) → there
|
|
101
|
+
// is nothing to reconcile against, and getPublishStatus would 503. No-op.
|
|
102
|
+
if (!push.isConfigured()) {
|
|
103
|
+
return { skipped: 'unconfigured', checked: 0, reconciled: 0, merged: 0, resolvedConflicts: 0, errors: 0 };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let rows;
|
|
107
|
+
try {
|
|
108
|
+
rows = await db.listConfirmedTasksForReconcile({ limit: deps.limit || SWEEP_LIMIT });
|
|
109
|
+
} catch (e) {
|
|
110
|
+
errFn(`[publish-reconciler] could not list confirmed tasks: ${e && e.message}`);
|
|
111
|
+
return { skipped: 'list_failed', checked: 0, reconciled: 0, merged: 0, resolvedConflicts: 0, errors: 1 };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Safety: a worktree_name can be reused across sequential (released) claims, so
|
|
115
|
+
// two confirmed tasks could derive the SAME branch. We can't tell which task a
|
|
116
|
+
// merged PR belongs to, so we skip ambiguous branches (logged) and leave them
|
|
117
|
+
// for manual handling rather than risk shipping the wrong task's row.
|
|
118
|
+
const branchCount = new Map();
|
|
119
|
+
for (const r of rows) {
|
|
120
|
+
if (!r.worktree_name) continue;
|
|
121
|
+
const b = `claude/${r.worktree_name}`;
|
|
122
|
+
branchCount.set(b, (branchCount.get(b) || 0) + 1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let reconciled = 0;
|
|
126
|
+
let merged = 0;
|
|
127
|
+
let resolvedConflicts = 0;
|
|
128
|
+
let refreshedStale = 0; // task 1915: PRs whose stale generated indexes we regen+pushed
|
|
129
|
+
let errors = 0;
|
|
130
|
+
let unprovable = 0; // confirmed tasks the sweep could not prove landed this pass
|
|
131
|
+
let staleStrands = 0; // of those, the ones older than STALE_CONFIRMED_MS (WARN'd)
|
|
132
|
+
const attempts = deps.healAttempts || healAttempts; // injectable for deterministic tests
|
|
133
|
+
const branchesSeen = new Set(); // to prune the attempts map post-sweep
|
|
134
|
+
const nowMs = Date.now();
|
|
135
|
+
for (const r of rows) {
|
|
136
|
+
const branch = r.worktree_name ? `claude/${r.worktree_name}` : null;
|
|
137
|
+
if (branch) branchesSeen.add(branch);
|
|
138
|
+
const branchUsable = !!branch && push.isSafeBranch(branch) && branchCount.get(branch) === 1;
|
|
139
|
+
if (branch && branchCount.get(branch) > 1) {
|
|
140
|
+
// A reused worktree_name maps a branch to >1 confirmed task, so a merged PR is
|
|
141
|
+
// ambiguous — but each task's OWN head_sha is not, so we skip only the branch/PR
|
|
142
|
+
// path and let the head_sha ancestry land-check below resolve it unambiguously.
|
|
143
|
+
logFn(`[publish-reconciler] task ${r.task_id}: branch ${branch} maps to >1 confirmed task — using head_sha land-check only`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let landed = false;
|
|
147
|
+
let landNote = '';
|
|
148
|
+
let branchStatus = null;
|
|
149
|
+
|
|
150
|
+
if (branchUsable) {
|
|
151
|
+
// Active merge driver (task 1162): GitHub's auto-merge fires on check-completion
|
|
152
|
+
// EVENTS, so a PR whose auto-merge was re-armed AFTER its checks already went
|
|
153
|
+
// green can sit open forever (the PR #125 stall). Before checking for a land,
|
|
154
|
+
// NUDGE the merge — if the PR is mergeable + CLEAN the server merges it itself.
|
|
155
|
+
// Best-effort: a miss (mergeability still computing, a transient API error)
|
|
156
|
+
// just waits for the next sweep; a non-green PR is reported via publish-status,
|
|
157
|
+
// never forced here. Guarded so an older injected deps bundle can't crash.
|
|
158
|
+
if (typeof push.mergeIfGreen === 'function') {
|
|
159
|
+
try {
|
|
160
|
+
const m = await push.mergeIfGreen({ branch });
|
|
161
|
+
if (m && m.merged_now) {
|
|
162
|
+
merged++;
|
|
163
|
+
logFn(
|
|
164
|
+
`[publish-reconciler] task ${r.task_id} (${branch}) PR #${m.number} was green but unmerged — server-merged it (auto-merge stall)`
|
|
165
|
+
);
|
|
166
|
+
} else if (
|
|
167
|
+
m && !m.merged && m.reason === 'merge_conflict' &&
|
|
168
|
+
typeof resolver.resolveBranchConflicts === 'function'
|
|
169
|
+
) {
|
|
170
|
+
// task 1385 (ADR 0082): GitHub's own auto-merge cannot run our custom
|
|
171
|
+
// otb-regen driver, so a PR that conflicts ONLY on generated files /
|
|
172
|
+
// the docs/adr/README.md append-index strands here forever. Do the
|
|
173
|
+
// regenerating merge locally (temp clone, driver + union active) and
|
|
174
|
+
// push the resolution; the PR's required checks re-run on the new head
|
|
175
|
+
// and the NEXT sweep's mergeIfGreen lands it. Best-effort: a genuine
|
|
176
|
+
// hand-written conflict is left untouched for a human.
|
|
177
|
+
try {
|
|
178
|
+
const rr = await resolver.resolveBranchConflicts({ branch });
|
|
179
|
+
if (rr && rr.resolved) {
|
|
180
|
+
resolvedConflicts++;
|
|
181
|
+
logFn(
|
|
182
|
+
`[publish-reconciler] task ${r.task_id} (${branch}) PR #${m.number} conflicted only on generated/index files — server-resolved + pushed; checks re-run, lands next sweep`
|
|
183
|
+
);
|
|
184
|
+
} else if (rr && rr.skipped === 'unresolvable_conflict') {
|
|
185
|
+
logFn(
|
|
186
|
+
`[publish-reconciler] task ${r.task_id} (${branch}) PR #${m.number} has a hand-written conflict (${(rr.conflicted || []).join(', ') || 'unknown'}) — left for a human`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
} catch (e) {
|
|
190
|
+
errFn(`[publish-reconciler] conflict-resolve for task ${r.task_id} (non-blocking): ${e && e.message}`);
|
|
191
|
+
}
|
|
192
|
+
} else if (
|
|
193
|
+
m && couldBeStaleGenerated(m) &&
|
|
194
|
+
typeof resolver.refreshStaleGenerated === 'function'
|
|
195
|
+
) {
|
|
196
|
+
// task 1915 (idea 499; the ADR 0082 gap): the PR is mergeable (no
|
|
197
|
+
// conflict) but a check is RED — commonest cause on a busy fleet is a
|
|
198
|
+
// STALE generated index (CI runs gen-*-map --check on the MERGE REF, so a
|
|
199
|
+
// main merge during the CI window re-stales the branch's committed
|
|
200
|
+
// docs/repo-map.md). mergeIfGreen won't fire (merge_state != CLEAN) and the
|
|
201
|
+
// reason is a failing check, never merge_conflict, so resolveBranchConflicts
|
|
202
|
+
// above never runs. Speculatively heal: merge origin/main + REGENERATE in a
|
|
203
|
+
// temp clone; a regen diff → commit + push (checks re-run, next sweep lands
|
|
204
|
+
// it); NO diff → a real check failure, left for a human. Capped per branch
|
|
205
|
+
// so a genuine treadmill can't loop forever. NEVER ships (the land still
|
|
206
|
+
// goes through landProvenForTask below) — no phantom-ship (idea 359).
|
|
207
|
+
const n = attempts.get(branch) || 0;
|
|
208
|
+
if (n >= MAX_STALE_HEAL_ATTEMPTS) {
|
|
209
|
+
logFn(
|
|
210
|
+
`[publish-reconciler] task ${r.task_id} (${branch}) PR #${m.number} still red after ${n} regen-heal attempt(s) (${m.reason}) — capped (persistent staleness treadmill or a real check failure); left for a human`
|
|
211
|
+
);
|
|
212
|
+
} else {
|
|
213
|
+
try {
|
|
214
|
+
const rr = await resolver.refreshStaleGenerated({ branch });
|
|
215
|
+
// Burn a cap slot ONLY on a tree-level determination (a real push, or a
|
|
216
|
+
// proven no-staleness); a transient/environmental miss (clone/fetch/
|
|
217
|
+
// checkout/merge_conflict/push_failed/…) must NOT count — it just retries
|
|
218
|
+
// next sweep — so infra flakiness can't wrongly cap a branch as "human".
|
|
219
|
+
if (rr && rr.refreshed) {
|
|
220
|
+
refreshedStale++;
|
|
221
|
+
attempts.set(branch, n + 1);
|
|
222
|
+
logFn(
|
|
223
|
+
`[publish-reconciler] task ${r.task_id} (${branch}) PR #${m.number} was mergeable but red (${m.reason}) — regenerated stale generated indexes + pushed; checks re-run, lands next sweep`
|
|
224
|
+
);
|
|
225
|
+
} else if (rr && rr.skipped === 'no_regen_diff') {
|
|
226
|
+
attempts.set(branch, n + 1);
|
|
227
|
+
logFn(
|
|
228
|
+
`[publish-reconciler] task ${r.task_id} (${branch}) PR #${m.number} red (${m.reason}) but regeneration produced no diff — a real check failure, left for a human`
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
} catch (e) {
|
|
232
|
+
errFn(`[publish-reconciler] regen-heal for task ${r.task_id} (non-blocking): ${e && e.message}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
} catch (_) {
|
|
237
|
+
/* best-effort: a merge-driver miss waits for the next sweep */
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
let status = null;
|
|
242
|
+
try {
|
|
243
|
+
status = await push.getPublishStatus({ branch });
|
|
244
|
+
} catch (_) {
|
|
245
|
+
status = null; // transient miss → fall through to the per-task land proof
|
|
246
|
+
}
|
|
247
|
+
if (!push.landConfirmed(status) && status && status.pr_state !== 'none') {
|
|
248
|
+
// A PR exists but hasn't fully landed yet (open / merged-but-deploy-pending /
|
|
249
|
+
// blocked). Respect it — wait for the deploy — rather than risk shipping early.
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
branchStatus = status;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// task 1547 — prove the land belongs to THIS task before shipping. landConfirmed
|
|
256
|
+
// (a branch PR merged+deployed) and the old task-1313 head-on-main ancestry check
|
|
257
|
+
// both key on signals a REUSED worktree branch can satisfy for the WRONG task — and
|
|
258
|
+
// claims.head_sha is the claim-TIME base (already on main for an R03-based task), so
|
|
259
|
+
// an ancestry check on it false-positives (the BV1.R04/R05 strand). The robust
|
|
260
|
+
// per-task proof is the SERVER-pushed tip (claims.published_head_sha) being an
|
|
261
|
+
// ancestor of main; the fallback, when no tip was recorded, is that the matched PR
|
|
262
|
+
// references this task id. landProvenForTask still cures the task-1313 strand class
|
|
263
|
+
// (PR deleted post-merge / no worktree_name / ambiguous branch) — now keyed on the
|
|
264
|
+
// unambiguous published tip rather than the base.
|
|
265
|
+
if (!landed && typeof push.landProvenForTask === 'function') {
|
|
266
|
+
try {
|
|
267
|
+
const proof = await push.landProvenForTask({
|
|
268
|
+
taskId: r.task_id, publishedSha: r.published_head_sha, status: branchStatus,
|
|
269
|
+
});
|
|
270
|
+
if (proof && proof.proven) {
|
|
271
|
+
landed = true;
|
|
272
|
+
landNote = proof.reason;
|
|
273
|
+
}
|
|
274
|
+
} catch (_) {
|
|
275
|
+
/* transient compare-API miss → next sweep */
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (!landed) {
|
|
280
|
+
// Observability (task 1546 / blocker 47): the sweep could not prove this
|
|
281
|
+
// confirmed task landed. Every such miss USED to be a silent `continue`, so
|
|
282
|
+
// blocker 47's 15 strands sat invisible for up to 66h. Count them, and WARN
|
|
283
|
+
// on the ones older than STALE_CONFIRMED_MS — a credited-but-unlanded task
|
|
284
|
+
// (codeless confirm, or a land whose published tip was never recorded on the
|
|
285
|
+
// claim) now surfaces in the logs instead of stranding silently.
|
|
286
|
+
unprovable++;
|
|
287
|
+
const reason = (!branch && !r.published_head_sha) ? 'no_branch_no_tip' : 'land_not_proven';
|
|
288
|
+
const ageMs = r.confirmed_at ? (nowMs - new Date(r.confirmed_at).getTime()) : null;
|
|
289
|
+
if (ageMs != null && ageMs > STALE_CONFIRMED_MS) {
|
|
290
|
+
staleStrands++;
|
|
291
|
+
errFn(
|
|
292
|
+
`[publish-reconciler] STRAND task ${r.task_id}: confirmed ~${Math.round(ageMs / 3_600_000)}h ago, unprovable (${reason}) — credited but no landed proof; needs owner triage`
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
const shipped = await db.shipTask({ taskId: r.task_id, builderId: r.builder_id });
|
|
300
|
+
reconciled++;
|
|
301
|
+
logFn(
|
|
302
|
+
`[publish-reconciler] task ${r.task_id} (${landNote}) landed → shipped`
|
|
303
|
+
);
|
|
304
|
+
// The box that published could not post the Discord broadcast (no webhook
|
|
305
|
+
// secret — ADR 0053). The server holds the secrets, so it fires it here,
|
|
306
|
+
// exactly ONCE on the confirmed→shipped transition. Best-effort: never let
|
|
307
|
+
// a broadcast hiccup turn a successful reconcile into a failure.
|
|
308
|
+
try {
|
|
309
|
+
await emit('task.shipped', shipped);
|
|
310
|
+
} catch (e) {
|
|
311
|
+
errFn(`[publish-reconciler] ship broadcast for task ${r.task_id} (non-blocking): ${e && e.message}`);
|
|
312
|
+
}
|
|
313
|
+
} catch (e) {
|
|
314
|
+
// TASK_NOT_CONFIRMED = a client poll (or a prior sweep) already flipped it
|
|
315
|
+
// in the race window — expected + idempotent, NOT an error.
|
|
316
|
+
if (e && e.code !== 'TASK_NOT_CONFIRMED') {
|
|
317
|
+
errors++;
|
|
318
|
+
errFn(`[publish-reconciler] shipTask ${r.task_id} failed: ${e && e.message}`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Prune the treadmill guard so it can't leak: a branch that left the confirmed set
|
|
324
|
+
// (landed, or released) never returns under the same name, so drop it.
|
|
325
|
+
for (const b of attempts.keys()) {
|
|
326
|
+
if (!branchesSeen.has(b)) attempts.delete(b);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (reconciled || merged || resolvedConflicts || refreshedStale) {
|
|
330
|
+
logFn(
|
|
331
|
+
`[publish-reconciler] swept ${rows.length} confirmed task(s); merged ${merged} stalled PR(s); auto-resolved ${resolvedConflicts} generated/index conflict(s); regen-healed ${refreshedStale} stale-generated PR(s); reconciled ${reconciled} → shipped`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
if (staleStrands) {
|
|
335
|
+
errFn(
|
|
336
|
+
`[publish-reconciler] ${staleStrands} stale strand(s): confirmed >${Math.round(STALE_CONFIRMED_MS / 60_000)}min with no provable land — credited but unlanded; see STRAND lines above`
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
return { checked: rows.length, reconciled, merged, resolvedConflicts, refreshedStale, errors, unprovable, staleStrands };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// task 1366 — server-side session-cost reconcile, piggybacked on the same 5-min
|
|
343
|
+
// sweep. System 1's client cost hook silently skips the MAJORITY of sessions (a
|
|
344
|
+
// cloud box / cowork VM / overnight agent runs with no GDS token, so the
|
|
345
|
+
// SessionEnd hook quiet-skips), so a server pass re-prices the model_usage we
|
|
346
|
+
// ALREADY stored on session_records into a cost_log row — keyed on the SAME
|
|
347
|
+
// (source, source_ref) the client would use, so logCost's ON CONFLICT DO NOTHING
|
|
348
|
+
// prevents any double-count if the client also posted. Unlike the confirmed→
|
|
349
|
+
// shipped work, this is PURE DB — it needs no push credential — so it runs even
|
|
350
|
+
// on a host where getPublishStatus would 503. Best-effort + injected-deps pure.
|
|
351
|
+
async function runCostSweep(deps = {}) {
|
|
352
|
+
const logFn = deps.log || console.log;
|
|
353
|
+
const errFn = deps.error || console.error;
|
|
354
|
+
// reconcileSessionCosts carved into modules/economy/ (BV1.R77 / ADR 0093 §1-2):
|
|
355
|
+
// prefer an injected deps.db (the test seam — tests inject a db with the
|
|
356
|
+
// method), else resolve the `reward` kernel port (production; economy default-on).
|
|
357
|
+
const reconciler = (deps.db && typeof deps.db.reconcileSessionCosts === 'function')
|
|
358
|
+
? deps.db
|
|
359
|
+
: (seams.resolveOptional('reward') || {});
|
|
360
|
+
if (typeof reconciler.reconcileSessionCosts !== 'function') return { skipped: 'unsupported' };
|
|
361
|
+
try {
|
|
362
|
+
const cost = await reconciler.reconcileSessionCosts();
|
|
363
|
+
if (cost && cost.reconciled > 0) {
|
|
364
|
+
const unk = cost.unknownModels && cost.unknownModels.length
|
|
365
|
+
? ` [unpriced→opus: ${cost.unknownModels.join(',')}]`
|
|
366
|
+
: '';
|
|
367
|
+
logFn(
|
|
368
|
+
`[publish-reconciler] session-cost: scanned ${cost.scanned}, reconciled ${cost.reconciled} cost_log row(s) totalling $${Number(cost.totalUsd || 0).toFixed(4)}${unk}`
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
return cost;
|
|
372
|
+
} catch (e) {
|
|
373
|
+
errFn(`[publish-reconciler] session-cost reconcile (non-blocking): ${e && e.message}`);
|
|
374
|
+
return { skipped: 'error', error: e && e.message };
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Start the periodic sweep. Idempotent (a second call is a no-op). Kill-switched
|
|
379
|
+
// by PUBLISH_RECONCILER_DISABLED=1 (purely additive bookkeeping, so it's ON by
|
|
380
|
+
// default whenever a push credential is configured; the route's getPublishStatus
|
|
381
|
+
// 503s without one, so runSweep already no-ops there too). Timers are unref'd so
|
|
382
|
+
// they never hold the process open on a systemd restart.
|
|
383
|
+
function start(deps = {}) {
|
|
384
|
+
if (process.env.PUBLISH_RECONCILER_DISABLED === '1') {
|
|
385
|
+
console.log('[publish-reconciler] disabled (PUBLISH_RECONCILER_DISABLED=1)');
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
if (intervalTimer) return; // already started
|
|
389
|
+
|
|
390
|
+
const tick = () => {
|
|
391
|
+
runSweep(deps).catch((e) => console.error(`[publish-reconciler] sweep crashed: ${e && e.message}`));
|
|
392
|
+
// task 1366 — runs independently of the confirmed→shipped sweep (pure DB, no
|
|
393
|
+
// push credential) and never lets a cost-reconcile error touch that sweep.
|
|
394
|
+
runCostSweep(deps).catch((e) => console.error(`[publish-reconciler] cost sweep crashed: ${e && e.message}`));
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
firstTimer = setTimeout(tick, FIRST_SWEEP_DELAY_MS);
|
|
398
|
+
if (firstTimer.unref) firstTimer.unref();
|
|
399
|
+
intervalTimer = setInterval(tick, INTERVAL_MS);
|
|
400
|
+
if (intervalTimer.unref) intervalTimer.unref();
|
|
401
|
+
|
|
402
|
+
console.log(
|
|
403
|
+
`[publish-reconciler] started — sweeping confirmed→shipped every ${Math.round(INTERVAL_MS / 1000)}s`
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function stop() {
|
|
408
|
+
if (firstTimer) {
|
|
409
|
+
clearTimeout(firstTimer);
|
|
410
|
+
firstTimer = null;
|
|
411
|
+
}
|
|
412
|
+
if (intervalTimer) {
|
|
413
|
+
clearInterval(intervalTimer);
|
|
414
|
+
intervalTimer = null;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
module.exports = { start, stop, runSweep, runCostSweep, couldBeStaleGenerated, INTERVAL_MS };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Builder analytics — the "AI dev curve" (V3.R72 / #291, criterion C5).
|
|
2
|
+
//
|
|
3
|
+
// Two surfaces, deliberately split by trust boundary:
|
|
4
|
+
// - GET /analytics/builder/:id — authenticated. A builder may read their
|
|
5
|
+
// OWN curve; an Archon may read any builder's (the cross-builder aggregate
|
|
6
|
+
// is just every builder's own page, plus the ecosystem feed below).
|
|
7
|
+
// - GET /public/analytics/ecosystem — no auth. Ecosystem-wide aggregate with
|
|
8
|
+
// NO per-builder identity, for status.amazonprimea.com. Individual curves
|
|
9
|
+
// never cross onto the open web (mirrors the public-task privacy gate).
|
|
10
|
+
//
|
|
11
|
+
// All data derives from existing columns (see db.builderAnalytics /
|
|
12
|
+
// db.ecosystemAnalytics) — no migration. JSON only, same Express app.
|
|
13
|
+
|
|
14
|
+
const express = require('express');
|
|
15
|
+
// Intra-module + the published doorway — a module never requires a core internal.
|
|
16
|
+
const api = require('../../../src/module-api');
|
|
17
|
+
const db = require('../db');
|
|
18
|
+
const auth = api;
|
|
19
|
+
const { parseId, corsPublicGet, asyncHandler } = api;
|
|
20
|
+
|
|
21
|
+
// Clamp the trend window to a sane range. Default 90 days. `all` → 365 cap so
|
|
22
|
+
// a single query can never scan an unbounded history.
|
|
23
|
+
function parseDays(raw) {
|
|
24
|
+
const s = (raw || '').toString().trim().toLowerCase();
|
|
25
|
+
if (s === 'all') return 365;
|
|
26
|
+
const n = parseInt(s, 10);
|
|
27
|
+
if (Number.isFinite(n) && n > 0) return Math.min(n, 365);
|
|
28
|
+
return 90;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = function buildAnalyticsRouter() {
|
|
32
|
+
const router = express.Router();
|
|
33
|
+
|
|
34
|
+
// CORS for the public ecosystem feed (mirrors routes/public.js, ADR 0029 /
|
|
35
|
+
// #566) — the off-box status page reads it cross-origin. Read-only, no-auth,
|
|
36
|
+
// no-secret, so a static '*' scoped to '/public/analytics' is safe. Shared
|
|
37
|
+
// middleware: corsPublicGet (_helpers.js) — byte-identical to the public.js mount.
|
|
38
|
+
router.use('/public/analytics', corsPublicGet('/public/analytics'));
|
|
39
|
+
|
|
40
|
+
// rank: public — ecosystem-wide dev-curve aggregate; individuals stripped.
|
|
41
|
+
router.get('/public/analytics/ecosystem', asyncHandler('GET /public/analytics/ecosystem', async (req, res) => {
|
|
42
|
+
const days = parseDays(req.query.days);
|
|
43
|
+
const data = await db.ecosystemAnalytics(days);
|
|
44
|
+
res.set('Cache-Control', 'public, max-age=60');
|
|
45
|
+
res.json(data);
|
|
46
|
+
}, { message: false, errorCode: 'ecosystem_analytics_failed' }));
|
|
47
|
+
|
|
48
|
+
// rank: own-or-archon — a builder's historical AI dev curve. A builder reads
|
|
49
|
+
// their own id; an Archon reads anyone's (powers the cross-builder view).
|
|
50
|
+
router.get('/analytics/builder/:id', auth.requireBuilder, asyncHandler('GET /analytics/builder/:id', async (req, res) => {
|
|
51
|
+
const targetId = parseId(req, res, { code: 'bad_builder_id', positiveInt: true });
|
|
52
|
+
if (targetId === null) return;
|
|
53
|
+
const isSelf = String(targetId) === String(req.builder.id);
|
|
54
|
+
if (!isSelf && req.builder.rank !== 'archon') {
|
|
55
|
+
return res.fail('forbidden', { status: 403, message: 'You can only view your own analytics.' });
|
|
56
|
+
}
|
|
57
|
+
const days = parseDays(req.query.days);
|
|
58
|
+
const data = await db.builderAnalytics(targetId, days);
|
|
59
|
+
res.json({ builder_id: targetId, ...data });
|
|
60
|
+
}, { message: false, errorCode: 'builder_analytics_failed' }));
|
|
61
|
+
|
|
62
|
+
return router;
|
|
63
|
+
};
|