@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,167 @@
|
|
|
1
|
+
// tests/goal_scope_check.mjs
|
|
2
|
+
//
|
|
3
|
+
// Unit suite for src/bongos/goal-scope-check.js — the pure scope wall the goal
|
|
4
|
+
// task-author gate (BV1.R60 / POST /goals/:id/tasks) calls (BV1.R59, ADR 0086 §3).
|
|
5
|
+
//
|
|
6
|
+
// Pure module: no DB, no network. We verify both walls independently and the
|
|
7
|
+
// combined gate: scope-subset (directional containment), the protected-path
|
|
8
|
+
// delegate (sub-Metic block, Metic+ pass), the fail-closed edges (empty scope,
|
|
9
|
+
// empty touches, unknown modules), and — critically — that the subset uses
|
|
10
|
+
// directional `matchOne` semantics, NOT the looser symmetric `touchesOverlap`
|
|
11
|
+
// (which would leak a task touching a path broader than the goal owns).
|
|
12
|
+
//
|
|
13
|
+
// Run: node tests/goal_scope_check.mjs
|
|
14
|
+
|
|
15
|
+
import { strict as assert } from 'node:assert';
|
|
16
|
+
import { createRequire } from 'node:module';
|
|
17
|
+
|
|
18
|
+
const require = createRequire(import.meta.url);
|
|
19
|
+
const gsc = require('../src/bongos/goal-scope-check.js');
|
|
20
|
+
const { touchesOverlap } = require('../src/bongos/path-match.js');
|
|
21
|
+
const { globsForModules, isModuleKey, protectedModules } = require('../src/bongos/module-scope-map.js');
|
|
22
|
+
|
|
23
|
+
let passed = 0;
|
|
24
|
+
let failed = 0;
|
|
25
|
+
function t(name, fn) {
|
|
26
|
+
try { fn(); passed++; console.log(` PASS ${name}`); }
|
|
27
|
+
catch (e) { failed++; console.log(` FAIL ${name}\n ${e.message}`); }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ---------- fixtures: anchor the suite to real module-map facts ----------
|
|
31
|
+
|
|
32
|
+
t('fixtures: art-pipeline + game are real, UNprotected modules; lifecycle is protected', () => {
|
|
33
|
+
assert.ok(isModuleKey('art-pipeline') && isModuleKey('game') && isModuleKey('lifecycle'));
|
|
34
|
+
const prot = protectedModules();
|
|
35
|
+
assert.ok(!prot.includes('art-pipeline'), 'art-pipeline must be unprotected for the maneuverability tests');
|
|
36
|
+
assert.ok(!prot.includes('game'), 'game must be unprotected');
|
|
37
|
+
assert.ok(prot.includes('lifecycle'), 'lifecycle owns migrations/ + routes/ so it must be protected');
|
|
38
|
+
// game owns a single specific file — needed for the directional-containment test.
|
|
39
|
+
assert.ok(globsForModules(['game']).includes('src/preview-server.js'));
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// ---------- the four required cases (done-when) ----------
|
|
43
|
+
|
|
44
|
+
t('in-scope pass: a touch inside a scoped module is allowed (Metic)', () => {
|
|
45
|
+
const r = gsc.check(['art-pipeline'], ['modules/art-pipeline/generated/tiles/olive.png'], 'metic');
|
|
46
|
+
assert.equal(r.ok, true, r.reason);
|
|
47
|
+
assert.equal(r.code, 'ok');
|
|
48
|
+
assert.equal(r.reason, null);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
t('out-of-scope reject: a touch in a different module is rejected', () => {
|
|
52
|
+
const r = gsc.check(['art-pipeline'], ['modules/game/rooms/world.js'], 'metic');
|
|
53
|
+
assert.equal(r.ok, false);
|
|
54
|
+
assert.equal(r.code, 'out_of_scope');
|
|
55
|
+
assert.deepEqual(r.details.out_of_scope, ['modules/game/rooms/world.js']);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
t('protected-path reject: a sub-Metic touching the protected core is rejected even in-scope', () => {
|
|
59
|
+
// 'lifecycle' owns migrations/ (in scope) AND migrations/ is protected.
|
|
60
|
+
const r = gsc.check(['lifecycle'], ['migrations/172_add_thing.sql'], 'thetes');
|
|
61
|
+
assert.equal(r.ok, false);
|
|
62
|
+
assert.equal(r.code, 'protected_path');
|
|
63
|
+
assert.equal(r.details.protected_hits[0].file, 'migrations/172_add_thing.sql');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
t('empty-scope reject: a goal with no scope_modules authorizes nothing', () => {
|
|
67
|
+
const r = gsc.check([], ['art/x.png'], 'metic');
|
|
68
|
+
assert.equal(r.ok, false);
|
|
69
|
+
assert.equal(r.code, 'empty_scope');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// ---------- the maneuverability grant: lower ranks CAN author in unprotected scope ----------
|
|
73
|
+
|
|
74
|
+
t('sub-Metic CAN author within an unprotected scoped module (the whole point of ADR 0086)', () => {
|
|
75
|
+
const r = gsc.check(['art-pipeline'], ['modules/art-pipeline/template/style_guide.md'], 'thetes');
|
|
76
|
+
assert.equal(r.ok, true, r.reason);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
t('Metic+ is NOT blocked by the protected-path wall, even on a protected path in scope', () => {
|
|
80
|
+
const r = gsc.check(['lifecycle'], ['migrations/172_add_thing.sql'], 'metic');
|
|
81
|
+
assert.equal(r.ok, true, r.reason);
|
|
82
|
+
const ra = gsc.check(['lifecycle'], ['migrations/172_add_thing.sql'], 'archon');
|
|
83
|
+
assert.equal(ra.ok, true, ra.reason);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// ---------- directional containment: matchOne, NOT touchesOverlap ----------
|
|
87
|
+
|
|
88
|
+
t('directional: an exact-file glob covers the exact touch, but NOT a broader parent dir', () => {
|
|
89
|
+
// game owns the single file src/preview-server.js.
|
|
90
|
+
assert.equal(gsc.check(['game'], ['src/preview-server.js'], 'metic').ok, true);
|
|
91
|
+
const broad = gsc.check(['game'], ['src/'], 'metic'); // touches the whole src/ tree
|
|
92
|
+
assert.equal(broad.ok, false);
|
|
93
|
+
assert.equal(broad.code, 'out_of_scope');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
t('the subset does NOT use symmetric touchesOverlap (which would leak the broad touch)', () => {
|
|
97
|
+
// Prove the looser matcher WOULD have passed it, so our reject is a deliberate
|
|
98
|
+
// tightening, not an accident.
|
|
99
|
+
assert.equal(touchesOverlap(['src/'], ['src/preview-server.js']), true,
|
|
100
|
+
'symmetric overlap is loose here — exactly why goal-scope-check uses matchOne');
|
|
101
|
+
assert.equal(gsc.check(['game'], ['src/'], 'metic').ok, false,
|
|
102
|
+
'goal-scope-check must REJECT the broad touch despite the symmetric overlap');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// ---------- fail-closed edges ----------
|
|
106
|
+
|
|
107
|
+
t('empty-touches reject: a task with no touches[] cannot be scope-checked', () => {
|
|
108
|
+
const r = gsc.check(['art-pipeline'], [], 'metic');
|
|
109
|
+
assert.equal(r.ok, false);
|
|
110
|
+
assert.equal(r.code, 'empty_touches');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
t('unknown-scope reject: modules that resolve to zero territory fail closed', () => {
|
|
114
|
+
const r = gsc.check(['not-a-real-module'], ['art/x.png'], 'metic');
|
|
115
|
+
assert.equal(r.ok, false);
|
|
116
|
+
assert.equal(r.code, 'unknown_scope');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
t('mixed in/out: one out-of-scope path among in-scope ones still rejects, naming the offender', () => {
|
|
120
|
+
const r = gsc.check(['art-pipeline'], ['modules/art-pipeline/a.png', 'modules/game/b.js', 'modules/art-pipeline/c.png'], 'metic');
|
|
121
|
+
assert.equal(r.ok, false);
|
|
122
|
+
assert.equal(r.code, 'out_of_scope');
|
|
123
|
+
assert.deepEqual(r.details.out_of_scope, ['modules/game/b.js']);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
t('multi-module scope: a touch covered by ANY scoped module passes', () => {
|
|
127
|
+
const r = gsc.check(['art-pipeline', 'game'], ['modules/game/seats.js'], 'metic');
|
|
128
|
+
assert.equal(r.ok, true, r.reason);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
t('ordering is fail-closed: out-of-scope is reported before the protected-path wall', () => {
|
|
132
|
+
// thetes, touch is BOTH out of an art-only scope AND protected — scope wins first.
|
|
133
|
+
const r = gsc.check(['art-pipeline'], ['migrations/9_x.sql'], 'thetes');
|
|
134
|
+
assert.equal(r.ok, false);
|
|
135
|
+
assert.equal(r.code, 'out_of_scope');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
t('null/garbage inputs fail closed, never throw', () => {
|
|
139
|
+
assert.equal(gsc.check(null, null, null).ok, false);
|
|
140
|
+
assert.equal(gsc.check(undefined, ['art/x'], 'metic').code, 'empty_scope');
|
|
141
|
+
assert.equal(gsc.check(['art-pipeline'], [null, '', false], 'metic').code, 'empty_touches');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// ---------- the exposed delegates work standalone (the route may call them directly) ----------
|
|
145
|
+
|
|
146
|
+
t('scopeSubset() delegate: reports ok + the offending paths + resolved globs', () => {
|
|
147
|
+
const s = gsc.scopeSubset(['art-pipeline'], ['modules/art-pipeline/x.png', 'modules/game/y.js']);
|
|
148
|
+
assert.equal(s.ok, false);
|
|
149
|
+
assert.deepEqual(s.out_of_scope, ['modules/game/y.js']);
|
|
150
|
+
assert.ok(s.goal_globs.includes('modules/art-pipeline/'));
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
t('protectedPathBlock() delegate: blocks sub-Metic, passes Metic, on the same path', () => {
|
|
154
|
+
assert.equal(gsc.protectedPathBlock(['migrations/1.sql'], 'thetes').ok, false);
|
|
155
|
+
assert.equal(gsc.protectedPathBlock(['migrations/1.sql'], 'metic').ok, true);
|
|
156
|
+
assert.equal(gsc.protectedPathBlock(['art/ok.png'], 'thetes').ok, true);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
t('isCovered() helper: exact + subtree-prefix containment', () => {
|
|
160
|
+
const globs = globsForModules(['art-pipeline']); // ['modules/art-pipeline/']
|
|
161
|
+
assert.equal(gsc.isCovered('modules/art-pipeline/deep/nested.png', globs), true);
|
|
162
|
+
assert.equal(gsc.isCovered('modules/art-pipeline-extra/x.js', globs), false); // sibling dir sharing the name-prefix is NOT inside 'modules/art-pipeline/'
|
|
163
|
+
assert.equal(gsc.isCovered('modules/art-pipeline/loader.js', globs), true);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
console.log(`\n${passed} passed, ${failed} failed`);
|
|
167
|
+
process.exit(failed ? 1 : 0);
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
// tests/goal_tier.mjs
|
|
2
|
+
//
|
|
3
|
+
// Unit guard for the Goal-tier db helpers (ADR 0086 §2, BV1.R56 / task 1510):
|
|
4
|
+
// createGoal / getGoal / listGoals / setGoalStatus / addGoalMember /
|
|
5
|
+
// removeGoalMember / listGoalMembers. These are the SQL plumbing for the one new
|
|
6
|
+
// tier in the goal-scoped work hierarchy; NO route references them yet (R57 adds
|
|
7
|
+
// routes/goals.js, R58 the /status rollup), so this is the only coverage they get
|
|
8
|
+
// until then.
|
|
9
|
+
//
|
|
10
|
+
// DB-free, same posture as abandon_task.mjs / confirm_attribution.mjs: each
|
|
11
|
+
// helper honours the #538 deps.pool injection seam (ONLY when NODE_ENV==='test'),
|
|
12
|
+
// so a SQL-aware fake client drives it with no live Postgres. We assert the
|
|
13
|
+
// statement shape + bound params + returned row, since the wall (R57/R60) and the
|
|
14
|
+
// /status rollup (R58) will build directly on these contracts.
|
|
15
|
+
//
|
|
16
|
+
// Run: node tests/goal_tier.mjs
|
|
17
|
+
|
|
18
|
+
import { strict as assert } from 'node:assert';
|
|
19
|
+
import { createRequire } from 'node:module';
|
|
20
|
+
import { makeRunner, makeSqlAwareClient } from './helpers.mjs';
|
|
21
|
+
|
|
22
|
+
process.env.NODE_ENV = 'test';
|
|
23
|
+
|
|
24
|
+
const require = createRequire(import.meta.url);
|
|
25
|
+
const db = require('../modules/lifecycle/db.js');
|
|
26
|
+
const {
|
|
27
|
+
createGoal, getGoal, listGoals, reorderGoals, setGoalStatus,
|
|
28
|
+
addGoalMember, removeGoalMember, listGoalMembers,
|
|
29
|
+
isGoalMember, addGoalScopeModules, setGoalSuccessor,
|
|
30
|
+
} = db;
|
|
31
|
+
|
|
32
|
+
const { test, summary } = makeRunner();
|
|
33
|
+
|
|
34
|
+
// These helpers are single-statement (activePool.query directly, like getVersion
|
|
35
|
+
// / createOverrideRequest), not pool.connect() transactions — so the fake pool
|
|
36
|
+
// needs a top-level .query. makeSqlAwareClient's _client already records every
|
|
37
|
+
// call into .queries; we expose its query as the pool's query (the same
|
|
38
|
+
// per-caller fakePool shape abandon_task.mjs / override_attribution.mjs use, just
|
|
39
|
+
// query-style instead of connect-style).
|
|
40
|
+
function fakePool(handler) {
|
|
41
|
+
const c = makeSqlAwareClient(handler);
|
|
42
|
+
return { query: (sql, params) => c._client.query(sql, params), connect: c.connect, queries: c._client.queries };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const find = (queries, re) => queries.find((q) => re.test(String(q.sql).replace(/\s+/g, ' ')));
|
|
46
|
+
|
|
47
|
+
const GOAL_ROW = {
|
|
48
|
+
id: 7, version_id: 'BONGOS-V1', title: 'Goal hierarchy', description: 'desc',
|
|
49
|
+
scope_modules: ['gds-core'], status: 'open', created_by: 42,
|
|
50
|
+
succeeded_by_goal_id: null, sort_order: 0, created_at: 'T0', updated_at: 'T0',
|
|
51
|
+
};
|
|
52
|
+
const MEMBER_ROW = { goal_id: 7, builder_id: 42, role: 'member', joined_at: 'T0' };
|
|
53
|
+
|
|
54
|
+
// =========================================================================
|
|
55
|
+
// createGoal
|
|
56
|
+
// =========================================================================
|
|
57
|
+
await test('createGoal: INSERT binds all six fields in order and returns the row', async () => {
|
|
58
|
+
const pool = fakePool((s) => {
|
|
59
|
+
if (/INSERT INTO goals/.test(s)) return { rows: [GOAL_ROW] };
|
|
60
|
+
return null;
|
|
61
|
+
});
|
|
62
|
+
const out = await createGoal(
|
|
63
|
+
{ versionId: 'BONGOS-V1', title: 'Goal hierarchy', description: 'desc', scopeModules: ['gds-core'], status: 'open', createdBy: 42 },
|
|
64
|
+
{ pool }
|
|
65
|
+
);
|
|
66
|
+
assert.deepEqual(out, GOAL_ROW, 'returns the inserted row');
|
|
67
|
+
const ins = find(pool.queries, /INSERT INTO goals/);
|
|
68
|
+
assert.deepEqual(ins.params, ['BONGOS-V1', 'Goal hierarchy', 'desc', ['gds-core'], 'open', 42],
|
|
69
|
+
'version_id, title, description, scope_modules, status, created_by — in that order');
|
|
70
|
+
assert.match(ins.sql, /RETURNING/, 'returns the row, not just inserts');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// task 1735: goal + first lead land in ONE statement — the creator's lead
|
|
74
|
+
// membership rides as a CTE, guarded so a NULL creator inserts no member.
|
|
75
|
+
await test('createGoal: the creator becomes the first lead in the same statement', async () => {
|
|
76
|
+
const pool = fakePool((s) => (/INSERT INTO goals/.test(s) ? { rows: [GOAL_ROW] } : null));
|
|
77
|
+
await createGoal({ versionId: 'V1', title: 'g', createdBy: 42 }, { pool });
|
|
78
|
+
const ins = find(pool.queries, /INSERT INTO goals/);
|
|
79
|
+
assert.match(ins.sql, /INSERT INTO goal_members \(goal_id, builder_id, role\)/,
|
|
80
|
+
'the member insert is part of the createGoal statement');
|
|
81
|
+
assert.match(ins.sql, /'lead'/, 'the creator is inserted as lead, not member');
|
|
82
|
+
assert.match(ins.sql, /WHERE \$6::bigint IS NOT NULL/,
|
|
83
|
+
'a NULL creator (system goal) inserts no member row');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
await test('createGoal: defaults — null description/createdBy, empty scope, open status', async () => {
|
|
87
|
+
const pool = fakePool((s) => (/INSERT INTO goals/.test(s) ? { rows: [GOAL_ROW] } : null));
|
|
88
|
+
await createGoal({ versionId: 'V1', title: 'general' }, { pool });
|
|
89
|
+
const ins = find(pool.queries, /INSERT INTO goals/);
|
|
90
|
+
assert.deepEqual(ins.params, ['V1', 'general', null, [], 'open', null],
|
|
91
|
+
'unspecified fields fall back to null / [] / open');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// =========================================================================
|
|
95
|
+
// getGoal
|
|
96
|
+
// =========================================================================
|
|
97
|
+
await test('getGoal: SELECT by id returns the row', async () => {
|
|
98
|
+
const pool = fakePool((s) => (/^SELECT .* FROM goals WHERE id = \$1/.test(s) ? { rows: [GOAL_ROW] } : null));
|
|
99
|
+
const out = await getGoal(7, { pool });
|
|
100
|
+
assert.deepEqual(out, GOAL_ROW);
|
|
101
|
+
assert.equal(find(pool.queries, /FROM goals WHERE id = \$1/).params[0], 7);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
await test('getGoal: unknown id returns null (not undefined)', async () => {
|
|
105
|
+
const pool = fakePool(() => ({ rows: [] }));
|
|
106
|
+
const out = await getGoal(999, { pool });
|
|
107
|
+
assert.equal(out, null);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// =========================================================================
|
|
111
|
+
// listGoals
|
|
112
|
+
// =========================================================================
|
|
113
|
+
await test('listGoals: no args binds [null, null] (both filters off)', async () => {
|
|
114
|
+
const pool = fakePool((s) => (/FROM goals/.test(s) ? { rows: [GOAL_ROW] } : null));
|
|
115
|
+
const out = await listGoals(undefined, { pool });
|
|
116
|
+
assert.deepEqual(out, [GOAL_ROW]);
|
|
117
|
+
const sel = find(pool.queries, /FROM goals/);
|
|
118
|
+
assert.deepEqual(sel.params, [null, null]);
|
|
119
|
+
assert.match(sel.sql, /ORDER BY version_id, sort_order, created_at, id/, 'priority-first, then stable ordering');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
await test('listGoals: versionId + status flow through to the bound params', async () => {
|
|
123
|
+
const pool = fakePool((s) => (/FROM goals/.test(s) ? { rows: [] } : null));
|
|
124
|
+
await listGoals({ versionId: 'BONGOS-V1', status: 'open' }, { pool });
|
|
125
|
+
assert.deepEqual(find(pool.queries, /FROM goals/).params, ['BONGOS-V1', 'open']);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// =========================================================================
|
|
129
|
+
// setGoalStatus
|
|
130
|
+
// =========================================================================
|
|
131
|
+
await test('setGoalStatus: UPDATE sets status + bumps updated_at, returns the row', async () => {
|
|
132
|
+
const pool = fakePool((s) => (/^UPDATE goals/.test(s) ? { rows: [{ ...GOAL_ROW, status: 'achieved' }] } : null));
|
|
133
|
+
const out = await setGoalStatus({ goalId: 7, status: 'achieved' }, { pool });
|
|
134
|
+
assert.equal(out.status, 'achieved');
|
|
135
|
+
const upd = find(pool.queries, /^UPDATE goals/);
|
|
136
|
+
assert.deepEqual(upd.params, [7, 'achieved']);
|
|
137
|
+
assert.match(upd.sql, /updated_at = now\(\)/, 'must bump updated_at');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
await test('setGoalStatus: unknown goal returns null', async () => {
|
|
141
|
+
const pool = fakePool(() => ({ rows: [] }));
|
|
142
|
+
assert.equal(await setGoalStatus({ goalId: 404, status: 'archived' }, { pool }), null);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// =========================================================================
|
|
146
|
+
// addGoalMember
|
|
147
|
+
// =========================================================================
|
|
148
|
+
await test('addGoalMember: upserts on the PK (re-join changes role, no dup-key)', async () => {
|
|
149
|
+
const pool = fakePool((s) => (/^INSERT INTO goal_members/.test(s) ? { rows: [{ ...MEMBER_ROW, role: 'lead' }] } : null));
|
|
150
|
+
const out = await addGoalMember({ goalId: 7, builderId: 42, role: 'lead' }, { pool });
|
|
151
|
+
assert.equal(out.role, 'lead');
|
|
152
|
+
const ins = find(pool.queries, /^INSERT INTO goal_members/);
|
|
153
|
+
assert.deepEqual(ins.params, [7, 42, 'lead']);
|
|
154
|
+
assert.match(ins.sql, /ON CONFLICT \(goal_id, builder_id\) DO UPDATE SET role = EXCLUDED.role/, 'upsert, not plain insert');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
await test('addGoalMember: role defaults to member', async () => {
|
|
158
|
+
const pool = fakePool((s) => (/^INSERT INTO goal_members/.test(s) ? { rows: [MEMBER_ROW] } : null));
|
|
159
|
+
await addGoalMember({ goalId: 7, builderId: 42 }, { pool });
|
|
160
|
+
assert.equal(find(pool.queries, /^INSERT INTO goal_members/).params[2], 'member');
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// =========================================================================
|
|
164
|
+
// removeGoalMember
|
|
165
|
+
// =========================================================================
|
|
166
|
+
await test('removeGoalMember: a deleted row reports removed:true', async () => {
|
|
167
|
+
const pool = fakePool((s) => (/^DELETE FROM goal_members/.test(s) ? { rowCount: 1, rows: [] } : null));
|
|
168
|
+
const out = await removeGoalMember({ goalId: 7, builderId: 42 }, { pool });
|
|
169
|
+
assert.deepEqual(out, { removed: true });
|
|
170
|
+
assert.deepEqual(find(pool.queries, /^DELETE FROM goal_members/).params, [7, 42]);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
await test('removeGoalMember: a non-member leave reports removed:false', async () => {
|
|
174
|
+
const pool = fakePool((s) => (/^DELETE FROM goal_members/.test(s) ? { rowCount: 0, rows: [] } : null));
|
|
175
|
+
assert.deepEqual(await removeGoalMember({ goalId: 7, builderId: 99 }, { pool }), { removed: false });
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// =========================================================================
|
|
179
|
+
// listGoalMembers
|
|
180
|
+
// =========================================================================
|
|
181
|
+
await test('listGoalMembers: SELECT by goal_id with builder identity, stable order', async () => {
|
|
182
|
+
// task 1734: builder identity rides along (LEFT JOIN builders) so the hall
|
|
183
|
+
// Goals page can render names + lead badges — additive columns only.
|
|
184
|
+
const pool = fakePool((s) => (/FROM goal_members gm\s+LEFT JOIN builders b ON b\.id = gm\.builder_id\s+WHERE gm\.goal_id = \$1/.test(s) ? { rows: [MEMBER_ROW] } : null));
|
|
185
|
+
const out = await listGoalMembers(7, { pool });
|
|
186
|
+
assert.deepEqual(out, [MEMBER_ROW]);
|
|
187
|
+
const sel = find(pool.queries, /FROM goal_members gm/);
|
|
188
|
+
assert.equal(sel.params[0], 7);
|
|
189
|
+
assert.match(sel.sql, /ORDER BY gm\.joined_at, gm\.builder_id/);
|
|
190
|
+
assert.match(sel.sql, /b\.github_login, b\.display_name, b\.avatar_url, b\.rank/);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// =========================================================================
|
|
194
|
+
// isGoalMember (BV1.R64 — the membership predicate behind the widen/lifecycle gate)
|
|
195
|
+
// =========================================================================
|
|
196
|
+
await test('isGoalMember: a matching row → true; binds (goalId, builderId)', async () => {
|
|
197
|
+
const pool = fakePool((s) => (/SELECT 1 FROM goal_members WHERE goal_id = \$1 AND builder_id = \$2/.test(s) ? { rows: [{ '?column?': 1 }] } : null));
|
|
198
|
+
const out = await isGoalMember({ goalId: 7, builderId: 42 }, { pool });
|
|
199
|
+
assert.equal(out, true);
|
|
200
|
+
assert.deepEqual(find(pool.queries, /FROM goal_members/).params, [7, 42]);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
await test('isGoalMember: no row → false (a non-member)', async () => {
|
|
204
|
+
const pool = fakePool(() => ({ rows: [] }));
|
|
205
|
+
assert.equal(await isGoalMember({ goalId: 7, builderId: 99 }, { pool }), false);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// =========================================================================
|
|
209
|
+
// addGoalScopeModules (BV1.R64 — "ask to widen": set-union append)
|
|
210
|
+
// =========================================================================
|
|
211
|
+
await test('addGoalScopeModules: UPDATE set-unions the new keys, binds (goalId, modules)', async () => {
|
|
212
|
+
const pool = fakePool((s) => (/^UPDATE goals/.test(s) ? { rows: [{ ...GOAL_ROW, scope_modules: ['art-pipeline', 'gds-core'] }] } : null));
|
|
213
|
+
const out = await addGoalScopeModules({ goalId: 7, modules: ['art-pipeline'] }, { pool });
|
|
214
|
+
assert.deepEqual(out.scope_modules, ['art-pipeline', 'gds-core']);
|
|
215
|
+
const upd = find(pool.queries, /^UPDATE goals/);
|
|
216
|
+
assert.deepEqual(upd.params, [7, ['art-pipeline']]);
|
|
217
|
+
assert.match(upd.sql, /array_agg\(DISTINCT m ORDER BY m\)/, 'dedupes existing + new keys');
|
|
218
|
+
assert.match(upd.sql, /unnest\(scope_modules \|\| \$2::text\[\]\)/, 'unions the requested keys onto the existing scope');
|
|
219
|
+
assert.match(upd.sql, /updated_at = now\(\)/);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
await test('addGoalScopeModules: unknown goal returns null', async () => {
|
|
223
|
+
const pool = fakePool(() => ({ rows: [] }));
|
|
224
|
+
assert.equal(await addGoalScopeModules({ goalId: 404, modules: ['x'] }, { pool }), null);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// =========================================================================
|
|
228
|
+
// setGoalSuccessor (BV1.R64 — rescope carry-forward lineage)
|
|
229
|
+
// =========================================================================
|
|
230
|
+
await test('setGoalSuccessor: UPDATE stamps succeeded_by_goal_id, binds (goalId, successorId)', async () => {
|
|
231
|
+
const pool = fakePool((s) => (/^UPDATE goals/.test(s) ? { rows: [{ ...GOAL_ROW, succeeded_by_goal_id: 12 }] } : null));
|
|
232
|
+
const out = await setGoalSuccessor({ goalId: 7, successorId: 12 }, { pool });
|
|
233
|
+
assert.equal(out.succeeded_by_goal_id, 12);
|
|
234
|
+
const upd = find(pool.queries, /^UPDATE goals/);
|
|
235
|
+
assert.deepEqual(upd.params, [7, 12]);
|
|
236
|
+
assert.match(upd.sql, /succeeded_by_goal_id = \$2/);
|
|
237
|
+
assert.match(upd.sql, /updated_at = now\(\)/);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
await test('setGoalSuccessor: unknown goal returns null', async () => {
|
|
241
|
+
const pool = fakePool(() => ({ rows: [] }));
|
|
242
|
+
assert.equal(await setGoalSuccessor({ goalId: 404, successorId: 12 }, { pool }), null);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// =========================================================================
|
|
246
|
+
// reorderGoals (task 1760 — Archon drag-to-reorder)
|
|
247
|
+
// =========================================================================
|
|
248
|
+
await test('reorderGoals: full-set list SELECTs the version set, then UPDATEs sort_order by position', async () => {
|
|
249
|
+
const pool = fakePool((s) => {
|
|
250
|
+
if (/SELECT id FROM goals WHERE version_id/.test(s)) return { rows: [{ id: 7 }, { id: 8 }, { id: 9 }] };
|
|
251
|
+
if (/UPDATE goals g/.test(s)) return { rows: [
|
|
252
|
+
{ ...GOAL_ROW, id: 9, sort_order: 0 },
|
|
253
|
+
{ ...GOAL_ROW, id: 7, sort_order: 1 },
|
|
254
|
+
{ ...GOAL_ROW, id: 8, sort_order: 2 },
|
|
255
|
+
] };
|
|
256
|
+
return null;
|
|
257
|
+
});
|
|
258
|
+
const out = await reorderGoals({ versionId: 'BONGOS-V1', orderedIds: [9, 7, 8] }, { pool });
|
|
259
|
+
assert.deepEqual(out.map((g) => g.id), [9, 7, 8], 'returns rows in the requested order');
|
|
260
|
+
const upd = find(pool.queries, /UPDATE goals g/);
|
|
261
|
+
assert.deepEqual(upd.params, [[9, 7, 8], [0, 1, 2]], 'binds orderedIds + their 0-based positions');
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// The UI only ever renders a status-filtered SLICE of a version's goals
|
|
265
|
+
// (roadmap excludes archived; the Goals page defaults to open-only) — so a
|
|
266
|
+
// scoped reorder of a subset must succeed, not fail-closed (this was the
|
|
267
|
+
// task-1760 launch bug: any version with one archived goal could never be
|
|
268
|
+
// reordered at all, since the client could never round-trip an id it never
|
|
269
|
+
// rendered). The goal(s) not named keep their relative order, appended after.
|
|
270
|
+
await test('reorderGoals: a partial list (a hidden/unrendered goal) succeeds, remainder appended after', async () => {
|
|
271
|
+
const pool = fakePool((s) => {
|
|
272
|
+
if (/SELECT id FROM goals WHERE version_id/.test(s)) return { rows: [{ id: 7 }, { id: 8 }, { id: 9 }] };
|
|
273
|
+
if (/UPDATE goals g/.test(s)) return { rows: [
|
|
274
|
+
{ ...GOAL_ROW, id: 9, sort_order: 0 },
|
|
275
|
+
{ ...GOAL_ROW, id: 7, sort_order: 1 },
|
|
276
|
+
{ ...GOAL_ROW, id: 8, sort_order: 2 },
|
|
277
|
+
] };
|
|
278
|
+
return null;
|
|
279
|
+
});
|
|
280
|
+
// Client only rendered/reordered [9, 7]; goal 8 (e.g. archived) was never shown.
|
|
281
|
+
const out = await reorderGoals({ versionId: 'BONGOS-V1', orderedIds: [9, 7] }, { pool });
|
|
282
|
+
assert.deepEqual(out.map((g) => g.id), [9, 7], 'returns only the touched subset, in the requested order');
|
|
283
|
+
const upd = find(pool.queries, /UPDATE goals g/);
|
|
284
|
+
assert.deepEqual(upd.params, [[9, 7, 8], [0, 1, 2]], 'the unrendered goal (8) is appended after the reordered slice');
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
await test('reorderGoals: an id from another version fails closed', async () => {
|
|
288
|
+
const pool = fakePool((s) => (/SELECT id FROM goals WHERE version_id/.test(s) ? { rows: [{ id: 7 }, { id: 8 }] } : null));
|
|
289
|
+
await assert.rejects(
|
|
290
|
+
() => reorderGoals({ versionId: 'BONGOS-V1', orderedIds: [7, 8, 999] }, { pool }),
|
|
291
|
+
(err) => err.code === 'SET_MISMATCH'
|
|
292
|
+
);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
await test('reorderGoals: an empty list fails closed', async () => {
|
|
296
|
+
const pool = fakePool((s) => (/SELECT id FROM goals WHERE version_id/.test(s) ? { rows: [{ id: 7 }] } : null));
|
|
297
|
+
await assert.rejects(
|
|
298
|
+
() => reorderGoals({ versionId: 'BONGOS-V1', orderedIds: [] }, { pool }),
|
|
299
|
+
(err) => err.code === 'SET_MISMATCH'
|
|
300
|
+
);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
await test('reorderGoals: a duplicated id in the list fails closed', async () => {
|
|
304
|
+
const pool = fakePool((s) => (/SELECT id FROM goals WHERE version_id/.test(s) ? { rows: [{ id: 7 }, { id: 8 }] } : null));
|
|
305
|
+
await assert.rejects(
|
|
306
|
+
() => reorderGoals({ versionId: 'BONGOS-V1', orderedIds: [7, 7] }, { pool }),
|
|
307
|
+
(err) => err.code === 'SET_MISMATCH'
|
|
308
|
+
);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// -------------------------------------------------------------------------
|
|
312
|
+
summary();
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// tests/goal_wall_proof.mjs — the BONGOS-V1 C6 acceptance proof (BV1.R66, ADR 0086 §7).
|
|
2
|
+
//
|
|
3
|
+
// C6 done-when item 5: a sub-Metic builder demonstrably AUTHORS + CLAIMS + SHIPS a
|
|
4
|
+
// task inside an assigned goal, while being BLOCKED server-side from authoring one
|
|
5
|
+
// that touches a protected path OR a module outside scope — the proof the goal wall
|
|
6
|
+
// holds END-TO-END. The LIVE deployed-gate transcript (a real goal + a real 403 on
|
|
7
|
+
// prod) is in docs/reviews/bongos-v1-c6-goal-wall-proof.md; this file is the
|
|
8
|
+
// permanent, re-runnable assertion of the same story, using the SAME pure code the
|
|
9
|
+
// deployed server runs.
|
|
10
|
+
//
|
|
11
|
+
// The wall is TWO independent layers (ADR 0086 §7), and this proves BOTH + the linkage:
|
|
12
|
+
// CREATE-TIME (first filter, ADVISORY — sees only DECLARED touches):
|
|
13
|
+
// authorizeGoalTaskCreate + goal-scope-check — bounds the author to the goal's
|
|
14
|
+
// modules and blocks a sub-Metic from the protected core.
|
|
15
|
+
// SHIP-TIME (authoritative — runs on the REAL committed diff):
|
|
16
|
+
// checkPermissionPaths (the grader permissionPathPrePass + the post-push
|
|
17
|
+
// main-audit, SEC #863) — catches a MIS-DECLARED task whose real diff reaches
|
|
18
|
+
// protected paths even if it slipped the create gate.
|
|
19
|
+
//
|
|
20
|
+
// The EXHAUSTIVE create-time vector table lives in tests/goal_abuse_matrix.mjs (R61);
|
|
21
|
+
// this file proves the END-TO-END story the matrix doesn't: the ship-time backstop
|
|
22
|
+
// and the create->ship linkage.
|
|
23
|
+
//
|
|
24
|
+
// Run: node tests/goal_wall_proof.mjs
|
|
25
|
+
|
|
26
|
+
import { strict as assert } from 'node:assert';
|
|
27
|
+
import { createRequire } from 'node:module';
|
|
28
|
+
import { makeRunner } from './helpers.mjs';
|
|
29
|
+
|
|
30
|
+
process.env.NODE_ENV = 'test';
|
|
31
|
+
const require = createRequire(import.meta.url);
|
|
32
|
+
const { authorizeGoalTaskCreate } = require('../modules/lifecycle/routes/goals.js');
|
|
33
|
+
const { deriveRequiredRank } = require('../modules/lifecycle/db.js');
|
|
34
|
+
const { checkPermissionPaths } = require('../src/bongos/permission-path-check.js');
|
|
35
|
+
const { checkRouteRanks, MODULE_EXPECTED_RANKS } = require('../src/bongos/route-rank-check.js');
|
|
36
|
+
const { test, summary } = makeRunner();
|
|
37
|
+
|
|
38
|
+
// A sub-Metic member working an `ideas`-scoped (non-protected) goal — the exact shape
|
|
39
|
+
// of the live proof goal on prod (see the doc for the real transcript).
|
|
40
|
+
const SUBMETIC = 'xenos';
|
|
41
|
+
const GOAL = { id: 42, version_id: 'BONGOS-V1', status: 'open', scope_modules: ['ideas'] };
|
|
42
|
+
const GOAL_PROTECTED = { id: 43, version_id: 'BONGOS-V1', status: 'open', scope_modules: ['lifecycle'] };
|
|
43
|
+
const VERSION = { id: 'BONGOS-V1', status: 'planning' };
|
|
44
|
+
const IN_SCOPE = ['modules/ideas/routes/inbox.js'];
|
|
45
|
+
const OUTSIDE_MODULE = ['modules/game/rooms/world.js'];
|
|
46
|
+
const PROTECTED = ['migrations/999_goal_authored.sql'];
|
|
47
|
+
|
|
48
|
+
// ---- 1. CREATE-TIME: the maneuverability grant + the two blocks ----
|
|
49
|
+
await test('create-time: a sub-Metic member CAN author an in-scope task (the grant)', () => {
|
|
50
|
+
const d = authorizeGoalTaskCreate({ goal: GOAL, version: VERSION, isMember: true, builderRank: SUBMETIC, touches: IN_SCOPE });
|
|
51
|
+
assert.equal(d.ok, true, JSON.stringify(d));
|
|
52
|
+
});
|
|
53
|
+
await test('create-time: a sub-Metic is BLOCKED authoring OUTSIDE the goal modules -> 403 out_of_scope', () => {
|
|
54
|
+
const d = authorizeGoalTaskCreate({ goal: GOAL, version: VERSION, isMember: true, builderRank: SUBMETIC, touches: OUTSIDE_MODULE });
|
|
55
|
+
assert.equal(d.status, 403); assert.equal(d.body.error, 'out_of_scope');
|
|
56
|
+
});
|
|
57
|
+
await test('create-time: a sub-Metic is BLOCKED authoring into the PROTECTED core -> 403 protected_path', () => {
|
|
58
|
+
// Even inside a protected-scope goal: scope-subset passes, the rank floor blocks.
|
|
59
|
+
const d = authorizeGoalTaskCreate({ goal: GOAL_PROTECTED, version: VERSION, isMember: true, builderRank: SUBMETIC, touches: PROTECTED });
|
|
60
|
+
assert.equal(d.status, 403); assert.equal(d.body.error, 'protected_path');
|
|
61
|
+
});
|
|
62
|
+
await test('create-time: a NON-member is BLOCKED -> 403 not_a_member (membership before scope)', () => {
|
|
63
|
+
const d = authorizeGoalTaskCreate({ goal: GOAL, version: VERSION, isMember: false, builderRank: SUBMETIC, touches: IN_SCOPE });
|
|
64
|
+
assert.equal(d.status, 403); assert.equal(d.body.error, 'not_a_member');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// ---- 2. NO SELF-ESCALATION: the auto-derived rank floor (ADR 0084) ----
|
|
68
|
+
await test('no self-escalation: an in-scope task derives to xenos — the author can claim their OWN work', () => {
|
|
69
|
+
assert.equal(deriveRequiredRank(IN_SCOPE, false), 'xenos');
|
|
70
|
+
});
|
|
71
|
+
await test('no self-escalation: a protected task auto-floors to metic — the sub-Metic author CANNOT claim it', () => {
|
|
72
|
+
assert.equal(deriveRequiredRank(PROTECTED, false), 'metic');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// ---- 3. SHIP-TIME: the authoritative defense on the REAL committed diff ----
|
|
76
|
+
// Even if a task's DECLARED touches slip the create gate, the ship-time gates (grader
|
|
77
|
+
// permissionPathPrePass + post-push main-audit) run checkPermissionPaths on the REAL
|
|
78
|
+
// diff. A sub-Metic diff hitting a protected path fails closed; a Metic+ clears it.
|
|
79
|
+
await test('ship-time: a sub-Metic REAL diff touching a protected path fails closed (hardFail)', () => {
|
|
80
|
+
const r = checkPermissionPaths({ changedFiles: PROTECTED, builderRank: SUBMETIC });
|
|
81
|
+
assert.equal(r.hardFail, true);
|
|
82
|
+
assert.deepEqual(r.protectedHits.map((h) => h.file), PROTECTED);
|
|
83
|
+
});
|
|
84
|
+
await test('ship-time: the same protected diff by a Metic+ clears the floor', () => {
|
|
85
|
+
assert.equal(checkPermissionPaths({ changedFiles: PROTECTED, builderRank: 'metic' }).hardFail, false);
|
|
86
|
+
});
|
|
87
|
+
await test('ship-time: a sub-Metic in-scope real diff is clean (the happy path ships)', () => {
|
|
88
|
+
assert.equal(checkPermissionPaths({ changedFiles: IN_SCOPE, builderRank: SUBMETIC }).hardFail, false);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// ---- 4. THE GATE CANNOT SILENTLY DRIFT: the route-rank pins (BV1.R61) ----
|
|
92
|
+
await test('drift-proof: the bounded-authoring keystone is pinned + classifies to its pin (live)', () => {
|
|
93
|
+
assert.equal((MODULE_EXPECTED_RANKS.lifecycle || {})['POST /goals/:id/tasks'], 'any-builder');
|
|
94
|
+
const res = checkRouteRanks();
|
|
95
|
+
const r = res.routes.find((x) => x.key === 'POST /goals/:id/tasks');
|
|
96
|
+
assert.ok(r, 'the keystone route must exist live');
|
|
97
|
+
assert.equal(r.rank, 'any-builder', 'a drift here would red the build (R61 pin)');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// ---- 5. THE LINKAGE: create-time is advisory, ship-time is authoritative ----
|
|
101
|
+
// The two layers are INDEPENDENT and COMPLEMENTARY: the create gate sees only the
|
|
102
|
+
// DECLARED touches (a mis-declaration can slip it), but the ship gate re-checks the
|
|
103
|
+
// REAL diff and fails closed. A mis-declared protected task therefore passes create
|
|
104
|
+
// yet dies at ship — the wall holds even when the first filter is fooled.
|
|
105
|
+
await test('linkage: a MIS-DECLARED task (declares in-scope, real diff protected) passes create but DIES at ship', () => {
|
|
106
|
+
const create = authorizeGoalTaskCreate({ goal: GOAL, version: VERSION, isMember: true, builderRank: SUBMETIC, touches: IN_SCOPE });
|
|
107
|
+
assert.equal(create.ok, true, 'the advisory create gate is fooled by a mis-declaration (sees only declared touches)');
|
|
108
|
+
const ship = checkPermissionPaths({ changedFiles: PROTECTED, builderRank: SUBMETIC });
|
|
109
|
+
assert.equal(ship.hardFail, true, 'the authoritative ship gate catches the real protected diff');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
summary();
|