@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,235 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Pure-helper tests for the deterministic newcomer floor replenisher
|
|
3
|
+
// (task 1158; multi-chore-per-discipline since task 1488).
|
|
4
|
+
//
|
|
5
|
+
// Co-located with the script rather than in tests/*.mjs. The repo's
|
|
6
|
+
// run-unit-tests.js gate only scans tests/, so tests/newcomer_floor.mjs is a thin
|
|
7
|
+
// shim that require()s THIS file so it runs in the gate. Covers the pure logic
|
|
8
|
+
// (per-chore deficit math, per-template floor resolution, monotonic per-instance
|
|
9
|
+
// source_ref seq, ref decomposition, template->copy building + scope-clamp,
|
|
10
|
+
// description assembly) and the integrity of the real templates.json. Runnable:
|
|
11
|
+
//
|
|
12
|
+
// node scripts/gds/newcomer-floor.test.js
|
|
13
|
+
//
|
|
14
|
+
// Exits non-zero on first failure.
|
|
15
|
+
|
|
16
|
+
const assert = require('node:assert');
|
|
17
|
+
const path = require('node:path');
|
|
18
|
+
const nf = require('./newcomer-floor');
|
|
19
|
+
|
|
20
|
+
let passed = 0;
|
|
21
|
+
function test(name, fn) {
|
|
22
|
+
try { fn(); passed += 1; }
|
|
23
|
+
catch (err) { console.error(`✗ ${name}\n ${err.message}`); process.exit(1); }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// per-discipline DEFAULT floors (the fallback when a template omits its own).
|
|
27
|
+
const FLOOR_DEFAULTS = { engineer: 2, artist: 3, ideator: 2 };
|
|
28
|
+
|
|
29
|
+
// templates-by-discipline fixture (each discipline -> LIST of chores).
|
|
30
|
+
const TEMPLATES = {
|
|
31
|
+
engineer: [
|
|
32
|
+
{ template_id: 'unit-test-pass', version_id: 'GDS-V4', discipline: 'engineer', floor: 2, title: 'Add a unit test', done_when: ['a', 'b'], est_minutes: 45 },
|
|
33
|
+
{ template_id: 'docs-hygiene-pass', version_id: 'GDS-V4', discipline: 'engineer', floor: 1, title: 'Docs sweep', done_when: ['a', 'b'], est_minutes: 40 },
|
|
34
|
+
],
|
|
35
|
+
artist: [
|
|
36
|
+
{ template_id: 'asset-generate-pass', version_id: 'V2', discipline: 'artist', title: 'Asset', done_when: ['a', 'b'], est_minutes: 55 }, // no own floor -> default
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// ---- templateFloor ----
|
|
41
|
+
|
|
42
|
+
test('templateFloor: own floor wins over the discipline default', () => {
|
|
43
|
+
assert.strictEqual(nf.templateFloor({ floor: 5 }, 'engineer', FLOOR_DEFAULTS), 5);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('templateFloor: falls back to the discipline default when omitted', () => {
|
|
47
|
+
assert.strictEqual(nf.templateFloor({}, 'artist', FLOOR_DEFAULTS), 3);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('templateFloor: 0 is a valid explicit floor (not treated as missing)', () => {
|
|
51
|
+
assert.strictEqual(nf.templateFloor({ floor: 0 }, 'engineer', FLOOR_DEFAULTS), 0);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('templateFloor: unknown discipline with no default -> 0', () => {
|
|
55
|
+
assert.strictEqual(nf.templateFloor({}, 'nope', FLOOR_DEFAULTS), 0);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// ---- computeTemplateDeficits ----
|
|
59
|
+
|
|
60
|
+
function deficitFor(rows, templateId) {
|
|
61
|
+
return rows.find((r) => r.template_id === templateId);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
test('computeTemplateDeficits: empty supply -> each chore needs its full floor', () => {
|
|
65
|
+
const rows = nf.computeTemplateDeficits({}, TEMPLATES, FLOOR_DEFAULTS);
|
|
66
|
+
assert.strictEqual(deficitFor(rows, 'unit-test-pass').needed, 2);
|
|
67
|
+
assert.strictEqual(deficitFor(rows, 'docs-hygiene-pass').needed, 1);
|
|
68
|
+
assert.strictEqual(deficitFor(rows, 'asset-generate-pass').needed, 3, 'artist uses the default floor');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('computeTemplateDeficits: ready + backlog both count as supply (idempotency)', () => {
|
|
72
|
+
const supply = { 'engineer:unit-test-pass': { ready: 1, backlog: 1 } }; // fills floor 2
|
|
73
|
+
const rows = nf.computeTemplateDeficits(supply, TEMPLATES, FLOOR_DEFAULTS);
|
|
74
|
+
assert.strictEqual(deficitFor(rows, 'unit-test-pass').needed, 0);
|
|
75
|
+
assert.strictEqual(deficitFor(rows, 'docs-hygiene-pass').needed, 1, 'sibling chore is independent');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('computeTemplateDeficits: supply is per-template, not shared across a discipline', () => {
|
|
79
|
+
// over-supplying one engineer chore must NOT satisfy the other.
|
|
80
|
+
const supply = { 'engineer:unit-test-pass': { ready: 9, backlog: 0 } };
|
|
81
|
+
const rows = nf.computeTemplateDeficits(supply, TEMPLATES, FLOOR_DEFAULTS);
|
|
82
|
+
assert.strictEqual(deficitFor(rows, 'unit-test-pass').needed, 0);
|
|
83
|
+
assert.strictEqual(deficitFor(rows, 'docs-hygiene-pass').needed, 1);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('computeTemplateDeficits: over-supply never goes negative', () => {
|
|
87
|
+
const supply = { 'artist:asset-generate-pass': { ready: 10, backlog: 0 } };
|
|
88
|
+
const rows = nf.computeTemplateDeficits(supply, TEMPLATES, FLOOR_DEFAULTS);
|
|
89
|
+
assert.strictEqual(deficitFor(rows, 'asset-generate-pass').needed, 0);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('computeTemplateDeficits: only-filter narrows to one discipline', () => {
|
|
93
|
+
const rows = nf.computeTemplateDeficits({}, TEMPLATES, FLOOR_DEFAULTS, { only: 'artist' });
|
|
94
|
+
assert.deepStrictEqual([...new Set(rows.map((r) => r.discipline))], ['artist']);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('computeTemplateDeficits: ignores non-floor disciplines', () => {
|
|
98
|
+
const rows = nf.computeTemplateDeficits({}, { unclassified: [{ template_id: 'x', floor: 9 }] }, { unclassified: 9 });
|
|
99
|
+
assert.deepStrictEqual(rows, []);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// ---- instanceSourceRef + parseSeq + parseRef ----
|
|
103
|
+
|
|
104
|
+
test('instanceSourceRef: tmpl:<disc>:<template_id>:<seq>', () => {
|
|
105
|
+
assert.strictEqual(nf.instanceSourceRef('engineer', 'unit-test-pass', 7), 'tmpl:engineer:unit-test-pass:7');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test('parseSeq: returns seq only for the matching discipline+template', () => {
|
|
109
|
+
assert.strictEqual(nf.parseSeq('tmpl:engineer:unit-test-pass:4', 'engineer', 'unit-test-pass'), 4);
|
|
110
|
+
assert.strictEqual(nf.parseSeq('tmpl:engineer:unit-test-pass:4', 'artist', 'unit-test-pass'), null, 'wrong discipline');
|
|
111
|
+
assert.strictEqual(nf.parseSeq('tmpl:engineer:other:4', 'engineer', 'unit-test-pass'), null, 'wrong template');
|
|
112
|
+
assert.strictEqual(nf.parseSeq('manual:engineer:some-title', 'engineer', 'unit-test-pass'), null, 'foreign ref');
|
|
113
|
+
assert.strictEqual(nf.parseSeq('tmpl:engineer:unit-test-pass:abc', 'engineer', 'unit-test-pass'), null, 'malformed seq');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('parseRef: decomposes a chore ref into discipline/template/seq', () => {
|
|
117
|
+
assert.deepStrictEqual(nf.parseRef('tmpl:engineer:unit-test-pass:7'), { discipline: 'engineer', templateId: 'unit-test-pass', seq: 7 });
|
|
118
|
+
assert.strictEqual(nf.parseRef('manual:engineer:x'), null, 'not a chore ref');
|
|
119
|
+
assert.strictEqual(nf.parseRef('tmpl:engineer:unit-test-pass:0'), null, 'seq must be positive');
|
|
120
|
+
assert.strictEqual(nf.parseRef('tmpl:engineer:unit-test-pass'), null, 'too few parts');
|
|
121
|
+
assert.strictEqual(nf.parseRef('tmpl:a:b:c:d'), null, 'too many parts');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// ---- nextSeq (monotonic across all refs) ----
|
|
125
|
+
|
|
126
|
+
test('nextSeq: empty set -> 1', () => {
|
|
127
|
+
assert.strictEqual(nf.nextSeq(new Set(), 'engineer', 'unit-test-pass'), 1);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test('nextSeq: 1 + max matching seq, ignoring other templates/disciplines', () => {
|
|
131
|
+
const refs = new Set([
|
|
132
|
+
'tmpl:engineer:unit-test-pass:1',
|
|
133
|
+
'tmpl:engineer:unit-test-pass:3', // gap is fine; max is 3
|
|
134
|
+
'tmpl:engineer:unit-test-pass:2',
|
|
135
|
+
'tmpl:engineer:docs-hygiene-pass:9', // sibling chore — ignored
|
|
136
|
+
'tmpl:artist:asset-generate-pass:5', // different discipline — ignored
|
|
137
|
+
'manual:engineer:something', // foreign — ignored
|
|
138
|
+
]);
|
|
139
|
+
assert.strictEqual(nf.nextSeq(refs, 'engineer', 'unit-test-pass'), 4);
|
|
140
|
+
assert.strictEqual(nf.nextSeq(refs, 'engineer', 'docs-hygiene-pass'), 10, 'sibling seq is independent');
|
|
141
|
+
assert.strictEqual(nf.nextSeq(refs, 'ideator', 'idea-seed-pass'), 1);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('nextSeq: never recycles a shipped/abandoned seq (max over ALL statuses)', () => {
|
|
145
|
+
const refs = new Set(['tmpl:ideator:idea-seed-pass:1', 'tmpl:ideator:idea-seed-pass:2']);
|
|
146
|
+
assert.strictEqual(nf.nextSeq(refs, 'ideator', 'idea-seed-pass'), 3);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// ---- buildProposalFromTemplate ----
|
|
150
|
+
|
|
151
|
+
const SAMPLE_TEMPLATE = {
|
|
152
|
+
template_id: 'docs-hygiene-pass',
|
|
153
|
+
version_id: 'GDS-V4',
|
|
154
|
+
discipline: 'engineer',
|
|
155
|
+
kind: 'cleanup',
|
|
156
|
+
est_minutes: 40,
|
|
157
|
+
credits_reward: 15,
|
|
158
|
+
floor: 1,
|
|
159
|
+
title: ' Docs-hygiene sweep ',
|
|
160
|
+
description: 'Body.',
|
|
161
|
+
done_when: ['a', 'b'],
|
|
162
|
+
touches: ['docs/', 42, ''],
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
test('buildProposalFromTemplate: carries fields, normalizes touches, sets seq ref', () => {
|
|
166
|
+
const p = nf.buildProposalFromTemplate(SAMPLE_TEMPLATE, 5, { discipline: 'engineer' });
|
|
167
|
+
assert.strictEqual(p.title, 'Docs-hygiene sweep', 'trimmed');
|
|
168
|
+
assert.strictEqual(p.version_id, 'GDS-V4');
|
|
169
|
+
assert.strictEqual(p.kind, 'cleanup');
|
|
170
|
+
assert.strictEqual(p.credits_reward, 15);
|
|
171
|
+
assert.strictEqual(p.est_minutes, 40);
|
|
172
|
+
assert.deepStrictEqual(p.touches, ['docs/', '42'], 'empties dropped, coerced to strings');
|
|
173
|
+
assert.strictEqual(p.source_ref, 'tmpl:engineer:docs-hygiene-pass:5');
|
|
174
|
+
assert.deepStrictEqual(p.done_when, ['a', 'b']);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test('buildProposalFromTemplate: clamps est_minutes to the 60-min hard cap', () => {
|
|
178
|
+
const over = nf.buildProposalFromTemplate({ ...SAMPLE_TEMPLATE, est_minutes: 120 }, 1);
|
|
179
|
+
assert.strictEqual(over.est_minutes, nf.HARD_MAX_MINUTES, '120 clamps to 60');
|
|
180
|
+
const bad = nf.buildProposalFromTemplate({ ...SAMPLE_TEMPLATE, est_minutes: -3 }, 1);
|
|
181
|
+
assert.strictEqual(bad.est_minutes, nf.HARD_MAX_MINUTES, 'non-positive -> ceiling');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test('buildProposalFromTemplate: null on a titleless template', () => {
|
|
185
|
+
assert.strictEqual(nf.buildProposalFromTemplate({ ...SAMPLE_TEMPLATE, title: ' ' }, 1), null);
|
|
186
|
+
assert.strictEqual(nf.buildProposalFromTemplate(null, 1), null);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// ---- buildDescription ----
|
|
190
|
+
|
|
191
|
+
test('buildDescription: folds done-when + evergreen footer', () => {
|
|
192
|
+
const desc = nf.buildDescription(
|
|
193
|
+
{ title: 't', description: 'Body text.', done_when: ['x', 'y'], est_minutes: 30 },
|
|
194
|
+
'engineer'
|
|
195
|
+
);
|
|
196
|
+
assert.ok(desc.includes('Body text.'));
|
|
197
|
+
assert.ok(desc.includes('**Done when:**'));
|
|
198
|
+
assert.ok(desc.includes('- x') && desc.includes('- y'));
|
|
199
|
+
assert.ok(desc.includes('Evergreen newcomer chore'), 'footer present');
|
|
200
|
+
assert.ok(desc.includes('engineer'), 'discipline in footer');
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// ---- loadTemplates: the REAL templates.json is well-formed (multi-chore shape) ----
|
|
204
|
+
|
|
205
|
+
test('loadTemplates: real templates.json is a valid per-discipline list', () => {
|
|
206
|
+
const templates = nf.loadTemplates(path.join(__dirname, 'newcomer-floor.templates.json'));
|
|
207
|
+
for (const disc of ['engineer', 'artist', 'ideator']) {
|
|
208
|
+
const list = templates[disc];
|
|
209
|
+
assert.ok(Array.isArray(list) && list.length >= 1, `${disc} is a non-empty list`);
|
|
210
|
+
for (const t of list) {
|
|
211
|
+
assert.strictEqual(t.discipline, disc, `${disc} chore discipline matches its key`);
|
|
212
|
+
assert.ok(t.template_id && t.title && t.version_id, `${disc} chore has template_id/title/version_id`);
|
|
213
|
+
assert.ok(Array.isArray(t.done_when) && t.done_when.length >= 2, `${disc}/${t.template_id} has done-when bullets`);
|
|
214
|
+
assert.ok(t.est_minutes <= nf.HARD_MAX_MINUTES, `${disc}/${t.template_id} within the 60-min cap`);
|
|
215
|
+
assert.ok(Number.isFinite(Number(t.floor)) && t.floor >= 0, `${disc}/${t.template_id} has a numeric floor`);
|
|
216
|
+
const p = nf.buildProposalFromTemplate(t, 1, { discipline: disc });
|
|
217
|
+
assert.ok(p && p.source_ref === `tmpl:${disc}:${t.template_id}:1`, `${disc}/${t.template_id} stamps a clean copy`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test('loadTemplates: engineer now offers BOTH the unit-test chore and the docs sweep', () => {
|
|
223
|
+
const templates = nf.loadTemplates(path.join(__dirname, 'newcomer-floor.templates.json'));
|
|
224
|
+
const ids = templates.engineer.map((t) => t.template_id);
|
|
225
|
+
assert.ok(ids.includes('unit-test-pass'), 'the safe coding chore is present');
|
|
226
|
+
assert.ok(ids.includes('docs-hygiene-pass'), 'the docs sweep is retained');
|
|
227
|
+
// every engineer chore touches only safe (non-protected) surfaces by design:
|
|
228
|
+
// touches[] is empty (git-merge is the collision detector), so this asserts the
|
|
229
|
+
// contract that engineer chores carry no protected-path touches.
|
|
230
|
+
for (const t of templates.engineer) {
|
|
231
|
+
assert.deepStrictEqual(t.touches || [], [], `${t.template_id} declares no touches[]`);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
console.log(`✓ all ${passed} newcomer-floor pure-helper tests passed`);
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// next-number.js — deterministic next-free ADR + migration numbers (V4.R26 / #964).
|
|
3
|
+
//
|
|
4
|
+
// WHY: ADR + migration numbers collided across parallel sessions. ADRs collided
|
|
5
|
+
// because each session scanned its OWN (possibly stale) local tree and picked the
|
|
6
|
+
// same "next" — the triple ADR-0044 collision (sessions 1660/1629) and the
|
|
7
|
+
// ADR-0024 collision (idea 122). Migrations collided/drifted because the
|
|
8
|
+
// claim-time DB counter is not reconciled against reality — it once handed out
|
|
9
|
+
// 079 when 079 was already applied on prod, and today it sits ahead of the
|
|
10
|
+
// committed files (counter ~099 while migrations/ tops out at 093), so the
|
|
11
|
+
// "reserved" number is neither the next free one nor collision-proof.
|
|
12
|
+
//
|
|
13
|
+
// This helper computes the next free number from the AUTHORITATIVE union of:
|
|
14
|
+
// - files committed on origin/main (git — the real "taken" set, shared by all
|
|
15
|
+
// parallel sessions, so everyone agrees on the baseline)
|
|
16
|
+
// - the local working tree (so a file you added THIS session counts,
|
|
17
|
+
// even before it is committed)
|
|
18
|
+
// next = max(union) + 1.
|
|
19
|
+
//
|
|
20
|
+
// FAIL-OPEN (V4 ethos: sessions stop fighting the machine room): if origin/main
|
|
21
|
+
// is unreachable (offline, fresh clone, credential-less box) it falls back to the
|
|
22
|
+
// local HEAD tree + working tree and flags the result `degraded` — it never throws
|
|
23
|
+
// and never blocks a claim.
|
|
24
|
+
//
|
|
25
|
+
// Usage:
|
|
26
|
+
// node scripts/gds/next-number.js # human-readable
|
|
27
|
+
// node scripts/gds/next-number.js --json # {"adr":58,"migration":94,...}
|
|
28
|
+
//
|
|
29
|
+
// Pure helpers (parseNumbers, nextFree, computeNextNumbers) + the sync facade
|
|
30
|
+
// (nextNumbers) are exported for unit tests (tests/next_number.mjs).
|
|
31
|
+
|
|
32
|
+
const fs = require('node:fs');
|
|
33
|
+
const path = require('node:path');
|
|
34
|
+
const { execFileSync } = require('node:child_process');
|
|
35
|
+
|
|
36
|
+
const { migrationNumberOf, CORE_NS } = require('./migration-namespace');
|
|
37
|
+
|
|
38
|
+
const REPO_ROOT = path.resolve(__dirname, '..', '..');
|
|
39
|
+
const ADR_DIR = 'docs/adr';
|
|
40
|
+
const MIGRATIONS_DIR = 'migrations';
|
|
41
|
+
|
|
42
|
+
// ADRs are NNNN-slug.md (4-digit). Migration numbers are parsed via migration-namespace's
|
|
43
|
+
// migrationNumberOf so BOTH the legacy bare form (NNN_slug.sql) AND the namespaced form
|
|
44
|
+
// (core_NNN_slug.sql / <key>_NNN_slug.sql, ADR 0108 §5) count toward the next-free number —
|
|
45
|
+
// otherwise the first core_-prefixed file would be undercounted and its number reused.
|
|
46
|
+
const ADR_RE = /^(\d{4})-.*\.md$/;
|
|
47
|
+
|
|
48
|
+
// Extract the numeric prefixes matching `re` from a list of basenames → Set<int>.
|
|
49
|
+
function parseNumbers(basenames, re) {
|
|
50
|
+
const out = new Set();
|
|
51
|
+
for (const name of basenames || []) {
|
|
52
|
+
const m = re.exec(name);
|
|
53
|
+
if (m) out.add(parseInt(m[1], 10));
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// next free = max + 1; an empty set starts the sequence at `start`.
|
|
59
|
+
function nextFree(numberSet, start = 1) {
|
|
60
|
+
let max = -Infinity;
|
|
61
|
+
for (const n of numberSet) if (n > max) max = n;
|
|
62
|
+
return max === -Infinity ? start : max + 1;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// PURE core: given two lists of repo-relative paths (committed + local), compute
|
|
66
|
+
// the next free ADR + migration number. `start*` let callers pin the sequence
|
|
67
|
+
// floor; defaults match the real repo (ADRs from 1, migrations from 1).
|
|
68
|
+
function computeNextNumbers({ committedPaths = [], localPaths = [], startAdr = 1, startMigration = 1 } = {}) {
|
|
69
|
+
const baseName = (p) => p.split('/').pop();
|
|
70
|
+
const inDir = (p, dir) => p.startsWith(dir + '/');
|
|
71
|
+
const allPaths = [...committedPaths, ...localPaths];
|
|
72
|
+
|
|
73
|
+
const adrNames = allPaths.filter((p) => inDir(p, ADR_DIR)).map(baseName);
|
|
74
|
+
const migNames = allPaths.filter((p) => inDir(p, MIGRATIONS_DIR)).map(baseName);
|
|
75
|
+
|
|
76
|
+
const adrSet = parseNumbers(adrNames, ADR_RE);
|
|
77
|
+
// Count bare AND namespaced migration files (ADR 0108 §5): migrationNumberOf(...) parses
|
|
78
|
+
// both `NNN_x.sql` and `core_NNN_x.sql`/`<key>_NNN_x.sql`, so a prefixed file is never
|
|
79
|
+
// undercounted (which would hand its number out again).
|
|
80
|
+
const migSet = new Set(migNames.map(migrationNumberOf).filter((n) => n != null));
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
adr: nextFree(adrSet, startAdr),
|
|
84
|
+
migration: nextFree(migSet, startMigration),
|
|
85
|
+
highestAdr: adrSet.size ? Math.max(...adrSet) : null,
|
|
86
|
+
highestMigration: migSet.size ? Math.max(...migSet) : null,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ---- I/O facade (injectable for tests) -------------------------------------
|
|
91
|
+
|
|
92
|
+
// List repo-relative paths under `dirs` committed on `ref`, via git. Returns []
|
|
93
|
+
// (not throw) if the ref/repo is unavailable — the caller decides degraded-ness.
|
|
94
|
+
function gitTreePaths(ref, dirs, runGit) {
|
|
95
|
+
try {
|
|
96
|
+
const out = runGit(['ls-tree', '-r', '--name-only', ref, '--', ...dirs]);
|
|
97
|
+
return out.split('\n').map((s) => s.trim()).filter(Boolean);
|
|
98
|
+
} catch {
|
|
99
|
+
return null; // signal: ref unreachable
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// List repo-relative paths under `dir` in the local working tree.
|
|
104
|
+
function localDirPaths(dir, readDir) {
|
|
105
|
+
try {
|
|
106
|
+
return readDir(path.join(REPO_ROOT, dir)).map((name) => `${dir}/${name}`);
|
|
107
|
+
} catch {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const defaultRunGit = (args) =>
|
|
113
|
+
execFileSync('git', args, { cwd: REPO_ROOT, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
114
|
+
const defaultReadDir = (p) => fs.readdirSync(p);
|
|
115
|
+
|
|
116
|
+
// SYNC facade used by claim.js + the CLI. Pulls the committed set from
|
|
117
|
+
// origin/main (fail-open to HEAD, then to local-only) and unions the working
|
|
118
|
+
// tree. Returns the numbers plus which source answered (for an honest print).
|
|
119
|
+
function nextNumbers({ runGit = defaultRunGit, readDir = defaultReadDir } = {}) {
|
|
120
|
+
const dirs = [ADR_DIR, MIGRATIONS_DIR];
|
|
121
|
+
let committedPaths = gitTreePaths('origin/main', dirs, runGit);
|
|
122
|
+
let source = 'origin/main';
|
|
123
|
+
let degraded = false;
|
|
124
|
+
if (committedPaths === null) {
|
|
125
|
+
committedPaths = gitTreePaths('HEAD', dirs, runGit);
|
|
126
|
+
source = 'HEAD';
|
|
127
|
+
degraded = true;
|
|
128
|
+
}
|
|
129
|
+
if (committedPaths === null) {
|
|
130
|
+
committedPaths = [];
|
|
131
|
+
source = 'local-only';
|
|
132
|
+
degraded = true;
|
|
133
|
+
}
|
|
134
|
+
const localPaths = [...localDirPaths(ADR_DIR, readDir), ...localDirPaths(MIGRATIONS_DIR, readDir)];
|
|
135
|
+
const nums = computeNextNumbers({ committedPaths, localPaths });
|
|
136
|
+
return { ...nums, source, degraded };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const padAdr = (n) => String(n).padStart(4, '0');
|
|
140
|
+
const padMig = (n) => String(n).padStart(3, '0');
|
|
141
|
+
|
|
142
|
+
function main() {
|
|
143
|
+
const json = process.argv.includes('--json');
|
|
144
|
+
const r = nextNumbers();
|
|
145
|
+
if (json) {
|
|
146
|
+
process.stdout.write(JSON.stringify({
|
|
147
|
+
adr: r.adr, migration: r.migration,
|
|
148
|
+
adr_padded: padAdr(r.adr), migration_padded: padMig(r.migration),
|
|
149
|
+
source: r.source, degraded: r.degraded,
|
|
150
|
+
}) + '\n');
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
console.log(`Next free ADR: ${padAdr(r.adr)} → docs/adr/${padAdr(r.adr)}-<slug>.md`);
|
|
154
|
+
// New CORE migrations are namespaced ${CORE_NS}_ (ADR 0108 §5) so their stem can't collide
|
|
155
|
+
// with an instance/module migration across repos. Instance seeds stay bare in
|
|
156
|
+
// migrations/instance/; a module migration is <key>_${padMig(r.migration)}_… in its own dir.
|
|
157
|
+
console.log(`Next free migration: ${padMig(r.migration)} → migrations/${CORE_NS}_${padMig(r.migration)}_<slug>.sql (core; instance seeds stay bare → migrations/instance/${padMig(r.migration)}_<slug>.sql)`);
|
|
158
|
+
console.log(`(from ${r.source} ∪ local working tree)${r.degraded ? ' ⚠ origin/main unreachable — verify before committing' : ''}`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (require.main === module) main();
|
|
162
|
+
|
|
163
|
+
module.exports = { parseNumbers, nextFree, computeNextNumbers, nextNumbers, gitTreePaths, padAdr, padMig };
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
//
|
|
4
|
+
// scripts/gds/oauth-secret.js — SHELL-INDEPENDENT, VERIFIED placement of a
|
|
5
|
+
// provisioned instance's GitHub OAuth App credentials (BONGOS-V1 goal 35, task 1979).
|
|
6
|
+
//
|
|
7
|
+
// WHY. During the Emersonian standup the manual hidden-input shell command used to
|
|
8
|
+
// place the GitHub OAuth client secret failed SILENTLY on the server shell, leaving a
|
|
9
|
+
// 26-char truncated value in web.env that broke sign-in with no obvious cause. The
|
|
10
|
+
// onboarding flow needs a secret-placement step that is:
|
|
11
|
+
// (1) SHELL-INDEPENDENT — a Node rewrite of the specific env line, never a fragile
|
|
12
|
+
// `read -s`/`sed -i` that can truncate or silently no-op;
|
|
13
|
+
// (2) VALIDATED before it is written — length + charset checks that CATCH the 26-char
|
|
14
|
+
// truncation the runtime auth_configured probe MISSES (authConfigured() only
|
|
15
|
+
// checks PRESENCE, not validity — a truncated-but-present secret passes it);
|
|
16
|
+
// (3) VERIFIED after the service restarts — probe GET /healthz and assert
|
|
17
|
+
// auth_configured:true, so onboarding never "proceeds" past broken auth.
|
|
18
|
+
// It APPLIES TO EVERY FORM of the flow — the /new-project skill (task 1981), the
|
|
19
|
+
// `bongos onboard` CLI (task 1982), and the hall wizard (task 1983) drive it.
|
|
20
|
+
//
|
|
21
|
+
// Control-plane tool (like provision.js): it rewrites /etc/<slug>/web.env (chmod 600)
|
|
22
|
+
// and restarts the instance's systemd unit, so it runs on the box, never the web tier.
|
|
23
|
+
// DRY-RUN by DEFAULT: without --apply it validates + prints the plan and mutates nothing.
|
|
24
|
+
|
|
25
|
+
const fs = require('node:fs');
|
|
26
|
+
const path = require('node:path');
|
|
27
|
+
const cp = require('node:child_process');
|
|
28
|
+
|
|
29
|
+
const REPO_ROOT = path.resolve(__dirname, '..', '..');
|
|
30
|
+
// Mirrors provision.js conventions (kept in lockstep — ADR 0111 / provision.js).
|
|
31
|
+
const ETC_BASE = process.env.PROVISION_ETC_BASE || '/etc';
|
|
32
|
+
const PROVISIONED_BRANDING_FILE = 'config/branding.neutral.json';
|
|
33
|
+
|
|
34
|
+
// A GitHub OAuth App client SECRET is a 40-char hex string (classic); GitHub may issue
|
|
35
|
+
// longer. Require a sane MINIMUM (catches the 26-char truncation) + a charset no real
|
|
36
|
+
// secret violates; do NOT hard-cap length.
|
|
37
|
+
const SECRET_MIN_LEN = 40;
|
|
38
|
+
// A client ID: classic 20 hex chars, or an 'Iv1.'/'Iv23'/'Ov23' App prefix.
|
|
39
|
+
const CLIENT_ID_MIN_LEN = 20;
|
|
40
|
+
const PLACEHOLDER_RE = /^(x{3,}|placeholder|change[-_]?me|todo|your[-_]?(client[-_]?)?(id|secret))$/i;
|
|
41
|
+
|
|
42
|
+
function validateClientSecret(secret) {
|
|
43
|
+
const s = String(secret == null ? '' : secret).trim();
|
|
44
|
+
if (!s) return { ok: false, reason: 'empty — no client secret provided' };
|
|
45
|
+
if (PLACEHOLDER_RE.test(s)) return { ok: false, reason: `looks like a placeholder ("${s.slice(0, 16)}")` };
|
|
46
|
+
if (s.length < SECRET_MIN_LEN) return { ok: false, reason: `too short (${s.length} chars; a GitHub OAuth client secret is ≥ ${SECRET_MIN_LEN}) — likely truncated by a silent shell failure (the task-1979 bug)` };
|
|
47
|
+
if (!/^[A-Za-z0-9._-]+$/.test(s)) return { ok: false, reason: 'contains characters no GitHub client secret uses (whitespace/quotes?) — likely a bad paste' };
|
|
48
|
+
return { ok: true };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function validateClientId(id) {
|
|
52
|
+
const s = String(id == null ? '' : id).trim();
|
|
53
|
+
if (!s) return { ok: false, reason: 'empty — no client id provided' };
|
|
54
|
+
if (PLACEHOLDER_RE.test(s)) return { ok: false, reason: `looks like a placeholder ("${s.slice(0, 16)}")` };
|
|
55
|
+
if (s.length < CLIENT_ID_MIN_LEN) return { ok: false, reason: `too short (${s.length} chars; a GitHub OAuth client id is ≥ ${CLIENT_ID_MIN_LEN})` };
|
|
56
|
+
if (!/^[A-Za-z0-9._]+$/.test(s)) return { ok: false, reason: 'contains unexpected characters — likely a bad paste' };
|
|
57
|
+
return { ok: true };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// The env-var prefix the provisioned instance resolves (the neutral pack's envPrefix,
|
|
61
|
+
// mirroring provision.js provisionedEnvPrefix — the creds MUST be written under this
|
|
62
|
+
// prefix or src/branding + auth never read them, task 1972). Fail-soft to CLOUDBONGOS.
|
|
63
|
+
function provisionedEnvPrefix() {
|
|
64
|
+
try {
|
|
65
|
+
const pack = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, PROVISIONED_BRANDING_FILE), 'utf8'));
|
|
66
|
+
return pack.envPrefix || 'CLOUDBONGOS';
|
|
67
|
+
} catch { return 'CLOUDBONGOS'; }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function webEnvPath(slug, { etcBase = ETC_BASE } = {}) {
|
|
71
|
+
return path.posix.join(etcBase, slug, 'web.env');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Rewrite the CLIENT_ID / CLIENT_SECRET lines of a web.env body IN PLACE, matching the
|
|
75
|
+
// pack's env prefix. PURE string transform — this IS the shell-independent placement
|
|
76
|
+
// (no `read -s`, no `sed -i`). THROWS if a target key line is absent, so a
|
|
77
|
+
// mismatched-prefix web.env can never silently no-op (the failure mode task 1979 hits).
|
|
78
|
+
function fillOAuthEnv(body, { prefix, clientId, clientSecret }) {
|
|
79
|
+
const esc = (k) => k.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
80
|
+
const setKey = (text, key, value) => {
|
|
81
|
+
const re = new RegExp(`^(${esc(key)})=.*$`, 'm');
|
|
82
|
+
if (!re.test(text)) throw new Error(`web.env has no "${key}=" line to fill (env-prefix mismatch?)`);
|
|
83
|
+
return text.replace(re, `$1=${value}`);
|
|
84
|
+
};
|
|
85
|
+
let out = body;
|
|
86
|
+
if (clientId != null) out = setKey(out, `${prefix}_GITHUB_CLIENT_ID`, clientId);
|
|
87
|
+
if (clientSecret != null) out = setKey(out, `${prefix}_GITHUB_CLIENT_SECRET`, clientSecret);
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// The PORT= line a web.env carries (provision.js writes it) — the healthz probe target.
|
|
92
|
+
function portFromEnv(body) {
|
|
93
|
+
const m = /^PORT=(\d+)$/m.exec(String(body || ''));
|
|
94
|
+
return m ? Number(m[1]) : null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Parse the /healthz JSON the post-restart probe returns → { ok, authConfigured }.
|
|
98
|
+
function parseHealthzAuth(stdout) {
|
|
99
|
+
try {
|
|
100
|
+
const j = JSON.parse(String(stdout || '').trim());
|
|
101
|
+
return { ok: j.ok !== false, authConfigured: j.auth_configured === true };
|
|
102
|
+
} catch { return { ok: false, authConfigured: false, parseError: true }; }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
// CLI: place <slug> --client-id ID --client-secret SECRET [--apply] [--port N]
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
function argVal(args, name) { const i = args.indexOf(name); return i >= 0 && i + 1 < args.length ? args[i + 1] : null; }
|
|
109
|
+
|
|
110
|
+
function usage() {
|
|
111
|
+
console.log(`oauth-secret.js — verified, shell-independent OAuth-secret placement (ADR 0111, task 1979)
|
|
112
|
+
|
|
113
|
+
Usage:
|
|
114
|
+
node scripts/gds/oauth-secret.js place <slug> --client-id <id> --client-secret <secret> [--apply] [--port <n>]
|
|
115
|
+
|
|
116
|
+
Validates the creds (length/format — CATCHES the silent-truncation bug), rewrites the
|
|
117
|
+
CLIENT_ID/CLIENT_SECRET lines of /etc/<slug>/web.env via Node (no fragile shell input),
|
|
118
|
+
restarts the instance's systemd unit, then PROBES /healthz to confirm auth_configured.
|
|
119
|
+
DRY-RUN by default; --apply performs the write + restart + probe on the control plane.`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function main() {
|
|
123
|
+
const args = process.argv.slice(2);
|
|
124
|
+
const cmd = args[0];
|
|
125
|
+
if (!cmd || cmd === '--help' || cmd === '-h' || cmd === 'help') { usage(); process.exit(0); }
|
|
126
|
+
if (cmd !== 'place') { console.error(`unknown command: ${cmd}\n`); usage(); process.exit(2); }
|
|
127
|
+
const slug = args[1] && !args[1].startsWith('--') ? args[1] : null;
|
|
128
|
+
if (!slug) { console.error('place needs a <slug>'); process.exit(2); }
|
|
129
|
+
const apply = args.includes('--apply');
|
|
130
|
+
const clientId = argVal(args, '--client-id');
|
|
131
|
+
const clientSecret = argVal(args, '--client-secret');
|
|
132
|
+
|
|
133
|
+
// (1) VALIDATE before touching anything — the truncation guard.
|
|
134
|
+
const idV = validateClientId(clientId);
|
|
135
|
+
const secV = validateClientSecret(clientSecret);
|
|
136
|
+
const problems = [];
|
|
137
|
+
if (!idV.ok) problems.push(`client id: ${idV.reason}`);
|
|
138
|
+
if (!secV.ok) problems.push(`client secret: ${secV.reason}`);
|
|
139
|
+
if (problems.length) {
|
|
140
|
+
console.error('✖ OAuth creds rejected before placement (nothing written):');
|
|
141
|
+
for (const p of problems) console.error(` - ${p}`);
|
|
142
|
+
process.exit(2);
|
|
143
|
+
}
|
|
144
|
+
console.log('✓ creds validated (length + charset)');
|
|
145
|
+
|
|
146
|
+
const prefix = provisionedEnvPrefix();
|
|
147
|
+
const envPath = webEnvPath(slug);
|
|
148
|
+
let body;
|
|
149
|
+
try { body = fs.readFileSync(envPath, 'utf8'); }
|
|
150
|
+
catch (e) { console.error(`cannot read ${envPath}: ${e.message} — is ${slug} provisioned on this control plane?`); process.exit(1); }
|
|
151
|
+
|
|
152
|
+
// (2) SHELL-INDEPENDENT placement — rewrite the specific env lines via Node.
|
|
153
|
+
let next;
|
|
154
|
+
try { next = fillOAuthEnv(body, { prefix, clientId, clientSecret }); }
|
|
155
|
+
catch (e) { console.error(`✖ ${e.message}`); process.exit(1); }
|
|
156
|
+
|
|
157
|
+
const port = argVal(args, '--port') ? Number(argVal(args, '--port')) : portFromEnv(next);
|
|
158
|
+
|
|
159
|
+
if (!apply) {
|
|
160
|
+
console.log(`[dry-run] would rewrite ${envPath} (${prefix}_GITHUB_CLIENT_ID/_SECRET), chmod 600`);
|
|
161
|
+
console.log(`[dry-run] would restart systemd unit ${slug}, then probe http://127.0.0.1:${port || '<port>'}/healthz for auth_configured`);
|
|
162
|
+
console.log('re-run with --apply to place + verify.');
|
|
163
|
+
process.exit(0);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
fs.writeFileSync(envPath, next, { mode: 0o600 });
|
|
167
|
+
fs.chmodSync(envPath, 0o600);
|
|
168
|
+
console.log(`✓ wrote ${envPath} (chmod 600)`);
|
|
169
|
+
cp.execSync(`systemctl restart ${slug}`, { stdio: 'inherit' });
|
|
170
|
+
console.log(`✓ restarted ${slug}`);
|
|
171
|
+
|
|
172
|
+
// (3) VERIFY — probe /healthz for auth_configured (retry briefly for restart).
|
|
173
|
+
if (!port) { console.error('✖ no PORT in web.env and no --port given — cannot probe /healthz'); process.exit(1); }
|
|
174
|
+
let probe = { authConfigured: false };
|
|
175
|
+
for (let i = 0; i < 10; i++) {
|
|
176
|
+
try {
|
|
177
|
+
const out = cp.execSync(`curl -sS --max-time 5 http://127.0.0.1:${port}/healthz`, { stdio: ['ignore', 'pipe', 'pipe'] }).toString();
|
|
178
|
+
probe = parseHealthzAuth(out);
|
|
179
|
+
if (probe.ok || probe.authConfigured) break;
|
|
180
|
+
} catch { /* not up yet */ }
|
|
181
|
+
cp.execSync('sleep 1');
|
|
182
|
+
}
|
|
183
|
+
if (!probe.authConfigured) {
|
|
184
|
+
console.error(`✖ post-restart probe: /healthz reports auth_configured=false — the instance still cannot authenticate. Do NOT proceed; recheck the OAuth app creds.`);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
console.log('✓ verified: /healthz reports auth_configured=true — sign-in is live');
|
|
188
|
+
process.exit(0);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (require.main === module) main();
|
|
192
|
+
|
|
193
|
+
module.exports = {
|
|
194
|
+
SECRET_MIN_LEN, CLIENT_ID_MIN_LEN,
|
|
195
|
+
validateClientSecret, validateClientId,
|
|
196
|
+
provisionedEnvPrefix, webEnvPath, fillOAuthEnv, portFromEnv, parseHealthzAuth,
|
|
197
|
+
};
|