@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,133 @@
|
|
|
1
|
+
// modules/lifecycle/goal-conflicts.js — the PURE goal task-conflict detector
|
|
2
|
+
// (task 1736). Server-side replacement for the hall Goals page's client-side
|
|
3
|
+
// exact-string overlap approximation: glob-aware touches[] intersection via the
|
|
4
|
+
// ONE canonical prefix-aware matcher (path-match.js, task 880 — reached through
|
|
5
|
+
// the published doorway), active-claim severity, and cross-goal overlaps
|
|
6
|
+
// against other open goals sharing scope_modules.
|
|
7
|
+
//
|
|
8
|
+
// Pure on purpose (the goal-scope-check precedent): the route fetches tasks /
|
|
9
|
+
// claims / sibling goals and calls computeGoalConflicts; every branch is pinned
|
|
10
|
+
// by a DB-free unit test (tests/goal_conflicts.mjs).
|
|
11
|
+
//
|
|
12
|
+
// Conflict = two OPEN tasks (not completed/confirmed/shipped/abandoned) whose
|
|
13
|
+
// DECLARED touches[] overlap. Declared touches are ADVISORY (ADR 0049 — git
|
|
14
|
+
// merge is the authoritative collision detector at land time); this detector is
|
|
15
|
+
// the PLANNING-time view a goal owner/manager resolves conflicts from, so pairs
|
|
16
|
+
// carry the overlap paths + a claim-aware severity, not a verdict.
|
|
17
|
+
|
|
18
|
+
const api = require('../../src/module-api');
|
|
19
|
+
const { matchOne } = api.pathMatch;
|
|
20
|
+
|
|
21
|
+
// Terminal statuses — a task here can no longer collide (its diff has landed,
|
|
22
|
+
// is landing, or never will). Mirrors the hall page's DONE_STATUSES + abandoned.
|
|
23
|
+
const RESOLVED_STATUSES = new Set(['completed', 'confirmed', 'shipped', 'abandoned']);
|
|
24
|
+
|
|
25
|
+
// A task participates in conflict detection only if it is open AND declares a
|
|
26
|
+
// blast radius. No touches → nothing to intersect (the client-side
|
|
27
|
+
// approximation skips these too; R60 goal-authored tasks always declare).
|
|
28
|
+
function isOpenWithTouches(t) {
|
|
29
|
+
return t && !RESOLVED_STATUSES.has(t.status)
|
|
30
|
+
&& Array.isArray(t.touches) && t.touches.length > 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Normalize one touches[] entry for the prefix matcher: tolerate the glob tail
|
|
34
|
+
// convention ('src/bongos/*', 'modules/hall-ui/**') by trimming it to the
|
|
35
|
+
// directory prefix matchOne already understands. Deeper glob syntax is not in
|
|
36
|
+
// the touches vocabulary (path-match.js is the canonical matcher, and it is
|
|
37
|
+
// prefix-based); an entry that trims to nothing is skipped.
|
|
38
|
+
function normalizeEntry(e) {
|
|
39
|
+
return String(e || '').trim().replace(/\/?\*+$/, '');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// The overlapping entries between two touches[] sets — the pairwise application
|
|
43
|
+
// of matchOne in both directions, keeping the MORE SPECIFIC side of each hit
|
|
44
|
+
// (matches what the hall renders: 'src/bongos/db.js', not the 'src/bongos/' that
|
|
45
|
+
// covers it). Returns a deduped, sorted list.
|
|
46
|
+
function overlappingPaths(a, b) {
|
|
47
|
+
const hits = new Set();
|
|
48
|
+
for (const rawA of a || []) {
|
|
49
|
+
const na = normalizeEntry(rawA);
|
|
50
|
+
if (!na) continue;
|
|
51
|
+
for (const rawB of b || []) {
|
|
52
|
+
const nb = normalizeEntry(rawB);
|
|
53
|
+
if (!nb) continue;
|
|
54
|
+
if (matchOne(nb, [na])) hits.add(nb); // na covers nb → nb is more specific (or equal)
|
|
55
|
+
else if (matchOne(na, [nb])) hits.add(na); // nb covers na → na is more specific
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return [...hits].sort();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Claim-aware severity: two colliding tasks BOTH actively claimed are colliding
|
|
62
|
+
// right now ('high'); one claimed means new work would land under someone's
|
|
63
|
+
// feet ('medium'); neither claimed is a planning-time heads-up ('low').
|
|
64
|
+
function severityFor(aClaimed, bClaimed) {
|
|
65
|
+
if (aClaimed && bClaimed) return 'high';
|
|
66
|
+
if (aClaimed || bClaimed) return 'medium';
|
|
67
|
+
return 'low';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const SEVERITY_ORDER = { high: 0, medium: 1, low: 2 };
|
|
71
|
+
|
|
72
|
+
// computeGoalConflicts — the detector.
|
|
73
|
+
// goalTasks: this goal's tasks (any status; filtered here)
|
|
74
|
+
// activeClaimTaskIds: Set of task ids (any type; compared as strings) holding
|
|
75
|
+
// an active claim (claims.released_at IS NULL)
|
|
76
|
+
// crossGoal: [{ goal: {id,title}, tasks: [...] }] — other OPEN goals
|
|
77
|
+
// sharing scope_modules, whose open tasks are checked
|
|
78
|
+
// against THIS goal's open tasks (never against each other
|
|
79
|
+
// — those pairs belong to that goal's own conflict view)
|
|
80
|
+
// Returns pairs sorted most-severe first:
|
|
81
|
+
// { task_a, task_b, title_a, title_b, overlapping_paths, severity,
|
|
82
|
+
// has_active_claims, cross_goal, goal_b?, goal_b_title? }
|
|
83
|
+
function computeGoalConflicts({ goalTasks = [], activeClaimTaskIds = new Set(), crossGoal = [] } = {}) {
|
|
84
|
+
const open = goalTasks.filter(isOpenWithTouches);
|
|
85
|
+
const claimed = (t) => activeClaimTaskIds.has(String(t.id));
|
|
86
|
+
const pair = (a, b, paths, extra) => ({
|
|
87
|
+
task_a: Number(a.id),
|
|
88
|
+
task_b: Number(b.id),
|
|
89
|
+
title_a: a.title || '',
|
|
90
|
+
title_b: b.title || '',
|
|
91
|
+
overlapping_paths: paths,
|
|
92
|
+
severity: severityFor(claimed(a), claimed(b)),
|
|
93
|
+
has_active_claims: claimed(a) || claimed(b),
|
|
94
|
+
cross_goal: false,
|
|
95
|
+
...extra,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const out = [];
|
|
99
|
+
for (let i = 0; i < open.length; i++) {
|
|
100
|
+
for (let j = i + 1; j < open.length; j++) {
|
|
101
|
+
const paths = overlappingPaths(open[i].touches, open[j].touches);
|
|
102
|
+
if (paths.length) out.push(pair(open[i], open[j], paths));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
for (const { goal, tasks } of crossGoal) {
|
|
106
|
+
const others = (tasks || []).filter(isOpenWithTouches);
|
|
107
|
+
for (const a of open) {
|
|
108
|
+
for (const b of others) {
|
|
109
|
+
const paths = overlappingPaths(a.touches, b.touches);
|
|
110
|
+
if (paths.length) {
|
|
111
|
+
out.push(pair(a, b, paths, {
|
|
112
|
+
cross_goal: true,
|
|
113
|
+
goal_b: Number(goal.id),
|
|
114
|
+
goal_b_title: goal.title || '',
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
out.sort((x, y) =>
|
|
121
|
+
SEVERITY_ORDER[x.severity] - SEVERITY_ORDER[y.severity]
|
|
122
|
+
|| x.task_a - y.task_a || x.task_b - y.task_b);
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = {
|
|
127
|
+
RESOLVED_STATUSES,
|
|
128
|
+
isOpenWithTouches,
|
|
129
|
+
normalizeEntry,
|
|
130
|
+
overlappingPaths,
|
|
131
|
+
severityFor,
|
|
132
|
+
computeGoalConflicts,
|
|
133
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// GDS task hierarchy — shallow (one-level) parent/child tree.
|
|
2
|
+
//
|
|
3
|
+
// V2 introduces tasks.parent_task_id so a piece of work can decompose into
|
|
4
|
+
// a parent task plus N child tasks (e.g., "F1: schema migration" with
|
|
5
|
+
// children "table-x", "view-y", "seed-z"). The depth is intentionally
|
|
6
|
+
// capped at one level — a parent cannot itself have a parent, and a task
|
|
7
|
+
// that already has children cannot become a child. This module enforces
|
|
8
|
+
// those invariants in app code; the DB enforces atomic ship-rollup via
|
|
9
|
+
// the trigger added in migration 007_pms_v2_hierarchy_trigger.sql.
|
|
10
|
+
//
|
|
11
|
+
// See limitations/pms-v2.md (Activity 1 C2).
|
|
12
|
+
|
|
13
|
+
const { pool } = require('../../src/module-api');
|
|
14
|
+
|
|
15
|
+
// -------------------------------------------------------------------------
|
|
16
|
+
// attachParent(taskId, parentTaskId)
|
|
17
|
+
//
|
|
18
|
+
// Sets tasks.parent_task_id = parentTaskId on the target task, after
|
|
19
|
+
// validating:
|
|
20
|
+
// - both tasks exist
|
|
21
|
+
// - target !== parent (no self-reference)
|
|
22
|
+
// - target.version_id === parent.version_id (no cross-version trees)
|
|
23
|
+
// - parent.parent_task_id IS NULL (depth cap, side 1)
|
|
24
|
+
// - target has no children of its own (depth cap, side 2)
|
|
25
|
+
//
|
|
26
|
+
// Pass parentTaskId=null to detach (always allowed if the task exists).
|
|
27
|
+
// Throws { code: 'TASK_NOT_FOUND' | 'PARENT_NOT_FOUND' | 'SELF_PARENT'
|
|
28
|
+
// | 'VERSION_MISMATCH' | 'PARENT_HAS_PARENT' | 'TARGET_HAS_CHILDREN' }.
|
|
29
|
+
// -------------------------------------------------------------------------
|
|
30
|
+
async function attachParent(taskId, parentTaskId) {
|
|
31
|
+
const targetId = Number(taskId);
|
|
32
|
+
if (!Number.isInteger(targetId) || targetId <= 0) {
|
|
33
|
+
throw { code: 'TASK_NOT_FOUND' };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Detach path — no parent validation needed.
|
|
37
|
+
if (parentTaskId === null || parentTaskId === undefined) {
|
|
38
|
+
const { rowCount, rows } = await pool.query(
|
|
39
|
+
`UPDATE tasks SET parent_task_id = NULL WHERE id = $1 RETURNING *`,
|
|
40
|
+
[targetId]
|
|
41
|
+
);
|
|
42
|
+
if (rowCount === 0) throw { code: 'TASK_NOT_FOUND' };
|
|
43
|
+
return rows[0];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const parentId = Number(parentTaskId);
|
|
47
|
+
if (!Number.isInteger(parentId) || parentId <= 0) {
|
|
48
|
+
throw { code: 'PARENT_NOT_FOUND' };
|
|
49
|
+
}
|
|
50
|
+
if (parentId === targetId) {
|
|
51
|
+
throw { code: 'SELF_PARENT' };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const client = await pool.connect();
|
|
55
|
+
try {
|
|
56
|
+
await client.query('BEGIN');
|
|
57
|
+
|
|
58
|
+
const { rows: targetRows } = await client.query(
|
|
59
|
+
`SELECT id, version_id, parent_task_id FROM tasks WHERE id = $1 FOR UPDATE`,
|
|
60
|
+
[targetId]
|
|
61
|
+
);
|
|
62
|
+
if (targetRows.length === 0) throw { code: 'TASK_NOT_FOUND' };
|
|
63
|
+
const target = targetRows[0];
|
|
64
|
+
|
|
65
|
+
const { rows: parentRows } = await client.query(
|
|
66
|
+
`SELECT id, version_id, parent_task_id FROM tasks WHERE id = $1 FOR UPDATE`,
|
|
67
|
+
[parentId]
|
|
68
|
+
);
|
|
69
|
+
if (parentRows.length === 0) throw { code: 'PARENT_NOT_FOUND' };
|
|
70
|
+
const parent = parentRows[0];
|
|
71
|
+
|
|
72
|
+
if (parent.version_id !== target.version_id) {
|
|
73
|
+
throw { code: 'VERSION_MISMATCH', target_version: target.version_id, parent_version: parent.version_id };
|
|
74
|
+
}
|
|
75
|
+
if (parent.parent_task_id !== null) {
|
|
76
|
+
throw { code: 'PARENT_HAS_PARENT', parent_id: parentId, grandparent_id: Number(parent.parent_task_id) };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const { rows: childRows } = await client.query(
|
|
80
|
+
`SELECT id FROM tasks WHERE parent_task_id = $1 LIMIT 1`,
|
|
81
|
+
[targetId]
|
|
82
|
+
);
|
|
83
|
+
if (childRows.length > 0) {
|
|
84
|
+
throw { code: 'TARGET_HAS_CHILDREN', target_id: targetId };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const { rows: updated } = await client.query(
|
|
88
|
+
`UPDATE tasks SET parent_task_id = $2 WHERE id = $1 RETURNING *`,
|
|
89
|
+
[targetId, parentId]
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
await client.query('COMMIT');
|
|
93
|
+
return updated[0];
|
|
94
|
+
} catch (err) {
|
|
95
|
+
await client.query('ROLLBACK').catch(() => {});
|
|
96
|
+
throw err;
|
|
97
|
+
} finally {
|
|
98
|
+
client.release();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = {
|
|
103
|
+
attachParent,
|
|
104
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// modules/lifecycle/lifecycle.js — the `lifecycle` kernel PORT provider surface
|
|
4
|
+
// (BV1.R86 / ADR 0093 §3). The lifecycle is carved last, so by now every
|
|
5
|
+
// capability it INVOKES (grade, reward, onboarding) is a port it resolves; this
|
|
6
|
+
// is the inverse — the surface CORE and the OTHER modules resolve to reach the
|
|
7
|
+
// build state machine without importing modules/lifecycle/ (the one-way rule).
|
|
8
|
+
//
|
|
9
|
+
// It retires the three ADR-0091 §3 doorway leaks: `createTask`,
|
|
10
|
+
// `VOTABLE_TASK_STATUSES`, and `tallyPeerVotes` now live HERE, behind the port,
|
|
11
|
+
// not on src/module-api.js. Plus the work-tracking READS the staying-core read
|
|
12
|
+
// routes (public/me/builders/analytics) need, and `classifyTaskKind` for the
|
|
13
|
+
// dormant System-3 cascade-dispatch in core.
|
|
14
|
+
//
|
|
15
|
+
// DELEGATES (does not spread) to ./db + ./task-classifier so a test that stubs a
|
|
16
|
+
// method on the live module object bites at call time (the economy `reward`
|
|
17
|
+
// precedent). Constants are read live via getters for the same reason.
|
|
18
|
+
|
|
19
|
+
const db = require('./db');
|
|
20
|
+
const classifier = require('./task-classifier');
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
// --- retired doorway leaks (ADR 0093 §3) ---------------------------------
|
|
24
|
+
// createTask: the lifecycle task INSERT (consumers: the onboarding newcomer-
|
|
25
|
+
// restock + the discord bug-filing module db slices).
|
|
26
|
+
createTask: (...a) => db.createTask(...a),
|
|
27
|
+
// tallyPeerVotes: the peer-vote→karma weekly fold-in (consumer: the autonomy
|
|
28
|
+
// routine-timers poller — the SAME tx POST /tasks/peer-votes/tally runs).
|
|
29
|
+
tallyPeerVotes: (...a) => db.tallyPeerVotes(...a),
|
|
30
|
+
// VOTABLE_TASK_STATUSES: the votable-status set (consumer: discord-reaction —
|
|
31
|
+
// decide applause vs a real vote). classifyTaskKind: the kind heuristic
|
|
32
|
+
// (consumer: core cascade-dispatch.js, the dormant System-3 lib).
|
|
33
|
+
get VOTABLE_TASK_STATUSES() { return classifier.VOTABLE_TASK_STATUSES; },
|
|
34
|
+
classifyTaskKind: (...a) => classifier.classifyTaskKind(...a),
|
|
35
|
+
|
|
36
|
+
// --- work-tracking READS the staying-core read routes resolve --------------
|
|
37
|
+
// public.js (the status surface): version/ship feed + grade trend.
|
|
38
|
+
getTask: (...a) => db.getTask(...a),
|
|
39
|
+
listVersions: (...a) => db.listVersions(...a),
|
|
40
|
+
versionProgress: (...a) => db.versionProgress(...a),
|
|
41
|
+
recentShippedTasks: (...a) => db.recentShippedTasks(...a),
|
|
42
|
+
estimationDriftSummary: (...a) => db.estimationDriftSummary(...a),
|
|
43
|
+
rollingAvgGrade: (...a) => db.rollingAvgGrade(...a),
|
|
44
|
+
gradeTrendByDay: (...a) => db.gradeTrendByDay(...a),
|
|
45
|
+
// me.js (the profile reader): per-builder claims + estimation + grade reads.
|
|
46
|
+
getActiveClaimsForBuilder: (...a) => db.getActiveClaimsForBuilder(...a),
|
|
47
|
+
getEstVsActualRatio: (...a) => db.getEstVsActualRatio(...a),
|
|
48
|
+
recentGradesForBuilder: (...a) => db.recentGradesForBuilder(...a),
|
|
49
|
+
countShippedTasksForBuilder: (...a) => db.countShippedTasksForBuilder(...a),
|
|
50
|
+
recentShippedTasksByBuilder: (...a) => db.recentShippedTasksByBuilder(...a),
|
|
51
|
+
// builders.js (the Archon roster): the roster + stale-claim + per-builder grade.
|
|
52
|
+
getBuildersRoster: (...a) => db.getBuildersRoster(...a),
|
|
53
|
+
getActiveClaimsForBuilderWithStale: (...a) => db.getActiveClaimsForBuilderWithStale(...a),
|
|
54
|
+
gradeByBuilder: (...a) => db.gradeByBuilder(...a),
|
|
55
|
+
// analytics.js (the AI-dev-curve): the builder + ecosystem analytics.
|
|
56
|
+
builderAnalytics: (...a) => db.builderAnalytics(...a),
|
|
57
|
+
ecosystemAnalytics: (...a) => db.ecosystemAnalytics(...a),
|
|
58
|
+
};
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
// Shared advisory mutex for the SINGLE shared `main` worktree.
|
|
2
|
+
// (task 1146 / ADR 0058: this comment is a needs_trust gate-surface change used to
|
|
3
|
+
// verify the automatic gatekeeper auto-merges a trusted author's PR with no owner click.)
|
|
4
|
+
//
|
|
5
|
+
// Both ship.js's autoMerge() and the /merge-mode skill mutate the same main
|
|
6
|
+
// worktree (REPO_ROOT). #462 (criterion C4) added a lockfile so two concurrent
|
|
7
|
+
// SHIPS could no longer collide — but the lock lived inside ship.js, so
|
|
8
|
+
// /merge-mode (which mutates the same tree by hand) never participated. This
|
|
9
|
+
// module extracts the lock so BOTH surfaces share ONE mutex: ship-vs-ship,
|
|
10
|
+
// ship-vs-merge-mode, and merge-mode-vs-merge-mode are all serialized.
|
|
11
|
+
// (V3.R50 / #269, criterion C6.)
|
|
12
|
+
//
|
|
13
|
+
// The lock is a plain file at <repoRoot>/.git/otb-automerge.lock. We don't use
|
|
14
|
+
// flock(2): ships and merge runs happen on macOS, where flock over an
|
|
15
|
+
// iCloud-synced filesystem is unreliable, and the holder may be a short-lived
|
|
16
|
+
// CLI process (the manual /merge-mode case has no long-lived owner). The file
|
|
17
|
+
// records three lines:
|
|
18
|
+
// line 1: holder pid (0 for a manual/CLI hold with no long-lived process)
|
|
19
|
+
// line 2: epoch-ms timestamp when acquired
|
|
20
|
+
// line 3: mode ('auto' | 'manual')
|
|
21
|
+
//
|
|
22
|
+
// Staleness / liveness — a held lock is reclaimable when:
|
|
23
|
+
// - auto : the holder pid is dead OR the stamp is older than AUTO_STALE_MS
|
|
24
|
+
// (a crashed automated ship that never released).
|
|
25
|
+
// - manual: only by time (MANUAL_STALE_MS). A manual hold has no stable pid
|
|
26
|
+
// (the CLI process that wrote it has already exited), so we trust
|
|
27
|
+
// the operator to release() and fall back to a generous timeout if
|
|
28
|
+
// they walk away mid-merge.
|
|
29
|
+
//
|
|
30
|
+
// Back-compat: a two-line lockfile written by the pre-#269 ship.js (pid\nts) is
|
|
31
|
+
// read as mode='auto', so a ship mid-flight during the deploy of this change is
|
|
32
|
+
// not disrupted.
|
|
33
|
+
//
|
|
34
|
+
// ⚠️ SYNCHRONOUS / CLI-ONLY. acquire() busy-waits (up to waitMs) and the
|
|
35
|
+
// internal sleepSync() blocks the thread via Atomics.wait — by design, because
|
|
36
|
+
// the only callers are execSync-style CLI scripts (ship.js auto-merge, the
|
|
37
|
+
// merge-lock.js CLI) that have no event loop to yield to. **Do NOT import this
|
|
38
|
+
// module from an Express route handler or any code on the request path** — a
|
|
39
|
+
// blocking acquire would stall the Node event loop for the whole process. If a
|
|
40
|
+
// route ever needs to inspect the lock, add a non-blocking readLock()-only
|
|
41
|
+
// helper rather than calling acquire(). sleepSync is intentionally NOT exported
|
|
42
|
+
// for this reason.
|
|
43
|
+
|
|
44
|
+
const fs = require('node:fs');
|
|
45
|
+
const path = require('node:path');
|
|
46
|
+
const { execSync } = require('node:child_process');
|
|
47
|
+
|
|
48
|
+
const AUTO_STALE_MS = 10 * 60 * 1000; // crashed automated ship
|
|
49
|
+
const MANUAL_STALE_MS = 30 * 60 * 1000; // operator walked away mid-merge-mode
|
|
50
|
+
const INDEX_LOCK_GRACE_MS = 60 * 1000; // a git index.lock younger than this may be a LIVE op
|
|
51
|
+
|
|
52
|
+
function lockPath(repoRoot) {
|
|
53
|
+
return path.join(repoRoot, '.git', 'otb-automerge.lock');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Synchronous sleep without spawning a process (ship.js is execSync-style and
|
|
57
|
+
// has no event loop to yield to while it holds the merge critical section).
|
|
58
|
+
function sleepSync(ms) {
|
|
59
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function pidAlive(pid) {
|
|
63
|
+
// pid <= 1 is never one of OUR holders: auto holds write process.pid (always
|
|
64
|
+
// > 1) and manual holds write 0 (and are reclaimed by time, not liveness).
|
|
65
|
+
// Rejecting pid 1 here also closes the theoretical case where a hand-crafted
|
|
66
|
+
// lockfile names pid 1 (init/launchd, always alive → EPERM) to look
|
|
67
|
+
// perpetually held; such a lock is now reclaimed immediately rather than
|
|
68
|
+
// lingering until AUTO_STALE_MS.
|
|
69
|
+
if (!Number.isInteger(pid) || pid <= 1) return false;
|
|
70
|
+
try {
|
|
71
|
+
process.kill(pid, 0);
|
|
72
|
+
return true;
|
|
73
|
+
} catch (e) {
|
|
74
|
+
return e.code === 'EPERM'; // EPERM: exists, not ours. ESRCH: dead.
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Parse the lockfile into { pid, ts, mode } or null if absent/unreadable.
|
|
79
|
+
function readLock(repoRoot) {
|
|
80
|
+
try {
|
|
81
|
+
const [p, t, m] = fs.readFileSync(lockPath(repoRoot), 'utf8').split('\n');
|
|
82
|
+
const pid = parseInt(p, 10);
|
|
83
|
+
const ts = parseInt(t, 10) || 0;
|
|
84
|
+
const mode = m && m.trim() === 'manual' ? 'manual' : 'auto';
|
|
85
|
+
return { pid: Number.isFinite(pid) ? pid : NaN, ts, mode };
|
|
86
|
+
} catch (_) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Repair the shared main worktree after reclaiming a STALE lock. The prior
|
|
92
|
+
// holder is, by definition of stale, dead or abandoned — and a holder that
|
|
93
|
+
// crashed mid-merge leaves wreckage the NEXT holder would otherwise inherit:
|
|
94
|
+
// - an orphaned git `.git/index.lock` (every git write then fails with
|
|
95
|
+
// "Another git process seems to be running"), and/or
|
|
96
|
+
// - a half-applied merge (MERGE_HEAD + a dirty index full of staged changes)
|
|
97
|
+
// that wedges `mainWorktreeBusy()` and `git merge --ff-only` for everyone.
|
|
98
|
+
// (Real incident 2026-06-01: a crashed /merge-mode run left 830 staged
|
|
99
|
+
// deletions + an orphaned index.lock, wedging the queue for 30 min.)
|
|
100
|
+
//
|
|
101
|
+
// This ONLY runs on the stale-reclaim path, so it never touches a live holder's
|
|
102
|
+
// tree. It is best-effort: every step is guarded so a repair hiccup can't block
|
|
103
|
+
// the reclaim. `runner` (execSync) and `now` are injectable for tests.
|
|
104
|
+
//
|
|
105
|
+
// Safety of `reset --hard origin/main`: REPO_ROOT is the throwaway shared main
|
|
106
|
+
// worktree that only ever holds `main` (all feature work lives in per-builder
|
|
107
|
+
// worktrees), and the dead holder's local merge was never pushed — so resetting
|
|
108
|
+
// to the fetched origin/main loses no committed, reachable work. Gated on being
|
|
109
|
+
// mid-merge or dirty to avoid gratuitous churn on a clean reclaim.
|
|
110
|
+
function recoverWorktree(repoRoot, { now = Date.now, runner = execSync } = {}) {
|
|
111
|
+
const run = (cmd) =>
|
|
112
|
+
runner(cmd, { cwd: repoRoot, stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf8' });
|
|
113
|
+
const tryRun = (cmd) => {
|
|
114
|
+
try { run(cmd); return true; } catch (_) { return false; }
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// 1. Clear an ORPHANED git index.lock — but only if it's old enough that no
|
|
118
|
+
// live git process could still own it. A fresh lock means a live op
|
|
119
|
+
// (possibly a holder that just acquired after us); never yank that.
|
|
120
|
+
try {
|
|
121
|
+
const lk = path.join(repoRoot, '.git', 'index.lock');
|
|
122
|
+
const st = fs.statSync(lk); // throws ENOENT when absent → nothing to clear
|
|
123
|
+
if (now() - st.mtimeMs > INDEX_LOCK_GRACE_MS) fs.unlinkSync(lk);
|
|
124
|
+
} catch (_) {
|
|
125
|
+
/* absent, racing a live op, or unreadable — leave it */
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 2. Abort a half-applied merge and drop the dead holder's staged changes so
|
|
129
|
+
// the next holder starts from a clean origin/main.
|
|
130
|
+
let midMerge = false;
|
|
131
|
+
try { run('git rev-parse -q --verify MERGE_HEAD'); midMerge = true; } catch (_) { /* not mid-merge */ }
|
|
132
|
+
let dirty = false;
|
|
133
|
+
try { dirty = run('git status --porcelain').trim().length > 0; } catch (_) { /* unknown — treat as clean */ }
|
|
134
|
+
if (midMerge) tryRun('git merge --abort');
|
|
135
|
+
if (midMerge || dirty) {
|
|
136
|
+
tryRun('git fetch origin main');
|
|
137
|
+
tryRun('git reset --hard origin/main');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Is a held lock reclaimable right now? `now` is injectable for tests.
|
|
142
|
+
function isStale(rec, now = Date.now()) {
|
|
143
|
+
if (!rec) return true;
|
|
144
|
+
const window = rec.mode === 'manual' ? MANUAL_STALE_MS : AUTO_STALE_MS;
|
|
145
|
+
if (now - rec.ts > window) return true;
|
|
146
|
+
if (rec.mode === 'manual') return false; // time-based only — no stable pid
|
|
147
|
+
return !pidAlive(rec.pid);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Acquire the exclusive merge lock. Returns true (caller MUST release() on
|
|
151
|
+
// every exit path) or false if a live holder keeps it past the wait window
|
|
152
|
+
// (caller bails to /merge-mode). Reclaims a stale lock automatically.
|
|
153
|
+
//
|
|
154
|
+
// opts:
|
|
155
|
+
// waitMs : how long to wait for a live holder before giving up (default 30s)
|
|
156
|
+
// mode : 'auto' (a process-backed ship) | 'manual' (a CLI/operator hold)
|
|
157
|
+
// pid : holder pid to record (default process.pid; pass 0 for manual)
|
|
158
|
+
// sleep : injectable sleeper (tests)
|
|
159
|
+
// now : injectable clock (tests)
|
|
160
|
+
function acquire(repoRoot, opts = {}) {
|
|
161
|
+
const {
|
|
162
|
+
waitMs = 30000,
|
|
163
|
+
mode = 'auto',
|
|
164
|
+
pid = process.pid,
|
|
165
|
+
sleep = sleepSync,
|
|
166
|
+
now = Date.now,
|
|
167
|
+
recover = recoverWorktree,
|
|
168
|
+
} = opts;
|
|
169
|
+
const p = lockPath(repoRoot);
|
|
170
|
+
const deadline = now() + waitMs;
|
|
171
|
+
for (;;) {
|
|
172
|
+
try {
|
|
173
|
+
const fd = fs.openSync(p, 'wx'); // create-exclusive; EEXIST if held
|
|
174
|
+
fs.writeSync(fd, `${pid}\n${now()}\n${mode}\n`);
|
|
175
|
+
fs.closeSync(fd);
|
|
176
|
+
return true;
|
|
177
|
+
} catch (e) {
|
|
178
|
+
if (e.code !== 'EEXIST') throw e;
|
|
179
|
+
const rec = readLock(repoRoot);
|
|
180
|
+
if (isStale(rec, now())) {
|
|
181
|
+
let reclaimed = false;
|
|
182
|
+
try {
|
|
183
|
+
fs.unlinkSync(p);
|
|
184
|
+
reclaimed = true;
|
|
185
|
+
} catch (_) {
|
|
186
|
+
/* someone else reclaimed it first — retry */
|
|
187
|
+
}
|
|
188
|
+
// Only repair the worktree if WE won the unlink — otherwise a freshly
|
|
189
|
+
// arrived live holder now owns it and its (clean) tree must be left be.
|
|
190
|
+
if (reclaimed) {
|
|
191
|
+
try { recover(repoRoot, { now }); } catch (_) { /* best-effort */ }
|
|
192
|
+
}
|
|
193
|
+
continue; // reclaimed — retry the create immediately
|
|
194
|
+
}
|
|
195
|
+
if (now() >= deadline) return false; // live holder; gave up waiting
|
|
196
|
+
sleep(2000);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Release the lock. By default only the recording process (auto holds) or any
|
|
202
|
+
// caller of a manual hold may remove it — defensive against a stolen-stale
|
|
203
|
+
// race where we reclaimed someone else's lock and they later try to release.
|
|
204
|
+
// pid : the releasing process (default process.pid)
|
|
205
|
+
// force : remove regardless of owner (emergency operator escape hatch)
|
|
206
|
+
function release(repoRoot, opts = {}) {
|
|
207
|
+
const { pid = process.pid, force = false } = opts;
|
|
208
|
+
try {
|
|
209
|
+
const rec = readLock(repoRoot);
|
|
210
|
+
if (!rec) return;
|
|
211
|
+
if (force || rec.mode === 'manual' || rec.pid === pid) {
|
|
212
|
+
fs.unlinkSync(lockPath(repoRoot));
|
|
213
|
+
}
|
|
214
|
+
} catch (_) {
|
|
215
|
+
/* already gone */
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ---------- the cross-machine tier: server-side merge lease (task 585 / idea 124) ----------
|
|
220
|
+
//
|
|
221
|
+
// Everything above is machine-LOCAL: a filesystem mutex on ONE checkout of main. When builders
|
|
222
|
+
// ship from DIFFERENT physical machines (each with its own checkout), that lock can't serialize
|
|
223
|
+
// them. The cross-machine tier is a TTL'd DB lease (src/bongos/db.js acquireMergeLease /
|
|
224
|
+
// releaseMergeLease / mergeLeaseStatus), handed out by the GDS API at merge time. This helper is
|
|
225
|
+
// the composition point: a multi-machine ship takes the server lease FIRST (one machine merges at
|
|
226
|
+
// a time), then the local file lock above.
|
|
227
|
+
//
|
|
228
|
+
// async + DEPENDENCY-INJECTED `lease` backend, deliberately: this module must stay require-able by
|
|
229
|
+
// the SYNC CLI path (ship.js, the merge-lock CLI) WITHOUT pulling in db.js + a pg pool, and the
|
|
230
|
+
// server lease only matters for server-mediated / multi-machine ships. The caller injects
|
|
231
|
+
// lease = { acquire({key,holder,ttlSeconds}) -> {acquired,holder,expires_at}, release({key,holder}) }
|
|
232
|
+
// (src/bongos/db.js satisfies this shape). With no backend, runs the fn directly — the file lock still
|
|
233
|
+
// serializes the single-machine case. Throws MERGE_LEASE_HELD if another machine holds the lease.
|
|
234
|
+
async function withServerMergeLease(holder, fn, { lease, key = 'main', ttlSeconds = 600 } = {}) {
|
|
235
|
+
if (!lease || typeof lease.acquire !== 'function') return fn();
|
|
236
|
+
const res = await lease.acquire({ key, holder, ttlSeconds });
|
|
237
|
+
if (!res || !res.acquired) {
|
|
238
|
+
const err = new Error(`merge lease for '${key}' held by ${res?.holder ?? 'another machine'} until ${res?.expires_at ?? '?'}`);
|
|
239
|
+
err.code = 'MERGE_LEASE_HELD';
|
|
240
|
+
throw err;
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
return await fn();
|
|
244
|
+
} finally {
|
|
245
|
+
try { await lease.release({ key, holder }); } catch (_) { /* TTL reclaims it — best-effort */ }
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
module.exports = {
|
|
250
|
+
AUTO_STALE_MS,
|
|
251
|
+
MANUAL_STALE_MS,
|
|
252
|
+
INDEX_LOCK_GRACE_MS,
|
|
253
|
+
lockPath,
|
|
254
|
+
pidAlive,
|
|
255
|
+
readLock,
|
|
256
|
+
isStale,
|
|
257
|
+
recoverWorktree,
|
|
258
|
+
acquire,
|
|
259
|
+
release,
|
|
260
|
+
withServerMergeLease,
|
|
261
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-- lifecycle_001_goal_first_leads.sql — backfill goal OWNERS into the member list
|
|
2
|
+
-- (task 1735). The goal authority model: the OWNER is goals.created_by (fixed at
|
|
3
|
+
-- create, moved only by POST /goals/:id/transfer); goal_members.role 'lead' is
|
|
4
|
+
-- the MANAGER tier the hall renders. From now on db.createGoal inserts the
|
|
5
|
+
-- creator's lead row atomically; this brings the goals created before that rule
|
|
6
|
+
-- up to the same shape so owners appear in their own member lists.
|
|
7
|
+
--
|
|
8
|
+
-- Goals with created_by NULL (the migration-160 default "<version> — general"
|
|
9
|
+
-- goals) have NO owner by design — Archons act as one via the gates' archon arm.
|
|
10
|
+
-- Deliberately NO earliest-member fallback: promoting a member to manager on an
|
|
11
|
+
-- ownerless goal would grant authority nobody asked for (fail-closed).
|
|
12
|
+
--
|
|
13
|
+
-- Data-only (no schema change), idempotent (the upsert converges), and
|
|
14
|
+
-- replay-safe on a fresh DB (zero goals → zero rows; no builder id is
|
|
15
|
+
-- hard-coded — learning 1238).
|
|
16
|
+
|
|
17
|
+
BEGIN;
|
|
18
|
+
|
|
19
|
+
INSERT INTO goal_members (goal_id, builder_id, role)
|
|
20
|
+
SELECT g.id, g.created_by, 'lead'
|
|
21
|
+
FROM goals g
|
|
22
|
+
WHERE g.created_by IS NOT NULL
|
|
23
|
+
ON CONFLICT (goal_id, builder_id) DO UPDATE SET role = 'lead';
|
|
24
|
+
|
|
25
|
+
INSERT INTO schema_migrations (version) VALUES ('lifecycle_001_goal_first_leads')
|
|
26
|
+
ON CONFLICT (version) DO NOTHING;
|
|
27
|
+
|
|
28
|
+
COMMIT;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
-- lifecycle_002_backfill_orphan_task_goals.sql — task 1763.
|
|
2
|
+
--
|
|
3
|
+
-- The goal-clean-up invariant: every task belongs to a goal. Going forward,
|
|
4
|
+
-- db.createTask defaults a goal-less new task into its version's catch-all
|
|
5
|
+
-- "<version> — general" goal (created by migration 160), so no NEW orphan is
|
|
6
|
+
-- minted by any create-vector. This one-time, idempotent backfill sweeps the
|
|
7
|
+
-- PRE-EXISTING orphan tasks into that same per-version general goal — the exact
|
|
8
|
+
-- mirror of migration 160's criterion backfill (same title match: the spaced
|
|
9
|
+
-- em-dash `<version_id> — general`; keep in sync with db.generalGoalIdForVersion).
|
|
10
|
+
--
|
|
11
|
+
-- PORTABLE + replay-safe: no instance data is hard-coded. On a fresh/vanilla DB
|
|
12
|
+
-- there are no orphan tasks (createTask assigns a goal from the first task), so
|
|
13
|
+
-- the UPDATE simply touches zero rows. A version with no general goal (should not
|
|
14
|
+
-- happen post-160, but defensively) leaves its tasks unlinked rather than erroring.
|
|
15
|
+
--
|
|
16
|
+
-- Instance-specific re-homing (e.g. OTB's hall-UI program tasks into a NAMED goal
|
|
17
|
+
-- like #25 rather than the catch-all) is deliberately NOT done here — that is
|
|
18
|
+
-- owning-instance data, applied under a claim via the PATCH /tasks/:id goal_id
|
|
19
|
+
-- endpoint this task adds, not shipped to every instance.
|
|
20
|
+
|
|
21
|
+
BEGIN;
|
|
22
|
+
|
|
23
|
+
-- Deliberately does NOT bump updated_at (mirrors migration 160's criterion
|
|
24
|
+
-- backfill): this is a one-time invariant cleanup, not a meaningful edit, so it
|
|
25
|
+
-- must not churn "recently updated" sort orders across every backfilled row.
|
|
26
|
+
UPDATE tasks t
|
|
27
|
+
SET goal_id = g.id
|
|
28
|
+
FROM goals g
|
|
29
|
+
WHERE g.version_id = t.version_id
|
|
30
|
+
AND g.title = t.version_id || ' — general'
|
|
31
|
+
AND t.goal_id IS NULL;
|
|
32
|
+
|
|
33
|
+
INSERT INTO schema_migrations (version) VALUES ('lifecycle_002_backfill_orphan_task_goals')
|
|
34
|
+
ON CONFLICT (version) DO NOTHING;
|
|
35
|
+
|
|
36
|
+
COMMIT;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"key": "lifecycle",
|
|
3
|
+
"title": "Lifecycle (the build state machine)",
|
|
4
|
+
"description": "The build state machine — tasks · claims · versions · done-when criteria · goals · dependencies · the claim→ship→grade→credit lifecycle · override requests · the ship/confirm/promote orchestration · github-push + merge-lease + conflict-resolve + the publish reconciler. The LAST and most-coupled core domain carved out of the GDS core in BV1.R86 (ADR 0093 §1,§3, 02-module-map §4 — kept whole, never split). default-on; every instance runs the lifecycle. Registers the `lifecycle` kernel PORT (createTask · VOTABLE_TASK_STATUSES · classifyTaskKind · tallyPeerVotes + the work-tracking reads) that core read routes + the ideas/discord/autonomy modules resolve. As a transaction-participant it RESOLVES the `reward` + `onboarding` ports inside its claim/ship/confirm txns — but via resolveOptional (graceful, like sessions→reward), so consumes is empty: a vanilla instance without those modules degrades the credit/onboarding writes to best-effort no-ops, it does not fail.",
|
|
5
|
+
"coreVersion": "^1.12.0",
|
|
6
|
+
"default": true,
|
|
7
|
+
"contributes": {
|
|
8
|
+
"routes": ["tasks", "claims", "versions", "done-when", "goals", "dependencies", "gate-approvals", "analytics", "lifecycle"],
|
|
9
|
+
"pollers": ["publish-reconciler"]
|
|
10
|
+
},
|
|
11
|
+
"provides": ["lifecycle"],
|
|
12
|
+
"consumes": []
|
|
13
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// modules/lifecycle/pollers/publish-reconciler.js — the loader poller entry for
|
|
4
|
+
// the confirmed→shipped auto-heal sweep (BV1.R86 / ADR 0093 §1).
|
|
5
|
+
//
|
|
6
|
+
// Was `publishReconciler.start()` / `.stop()` hardcoded in server.js; now a
|
|
7
|
+
// loader-started POLLER (contributes.pollers:["publish-reconciler"]), exactly the
|
|
8
|
+
// inversion the autonomy carve (routine-timers) made for its weekly timer. The
|
|
9
|
+
// loader's startModulePollers requires THIS file and calls start(deps) at boot /
|
|
10
|
+
// stop() at shutdown — failure-isolated, non-blocking. server.js no longer reaches
|
|
11
|
+
// into the lifecycle module to start it. The reconciler resolves the economy
|
|
12
|
+
// `reward` port for the cost sweep and its github-push/conflict-resolve siblings
|
|
13
|
+
// for the merge land — all module-internal.
|
|
14
|
+
|
|
15
|
+
const reconciler = require('../publish-reconciler');
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
start: (deps = {}) => reconciler.start(deps),
|
|
19
|
+
stop: () => reconciler.stop(),
|
|
20
|
+
};
|