@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,284 @@
|
|
|
1
|
+
// tests/reward_gate.mjs
|
|
2
|
+
//
|
|
3
|
+
// Unit coverage for task 1670 / ADR 0096 + the task 1673 amendment — the reward
|
|
4
|
+
// gate AUTO-ASSIGNS a capped credits_reward at the workable transitions
|
|
5
|
+
// (promote-to-ready + claim) instead of BLOCKING. A task can never become
|
|
6
|
+
// workable paying 0 drachmae, and a promote/claim is never refused for a missing
|
|
7
|
+
// reward — the gate fills in a fair, capped value and proceeds.
|
|
8
|
+
//
|
|
9
|
+
// The decision is one shared pure helper (db.rewardGateAssignment) consumed by
|
|
10
|
+
// the promote route and the claim path (same pattern as deriveRequiredRank). We
|
|
11
|
+
// test the helpers directly (no DB), then read the route + claim + migration
|
|
12
|
+
// sources to pin the enforcement points and the auto-promote revert.
|
|
13
|
+
//
|
|
14
|
+
// Run: node tests/reward_gate.mjs
|
|
15
|
+
|
|
16
|
+
import { strict as assert } from 'node:assert';
|
|
17
|
+
import { createRequire } from 'node:module';
|
|
18
|
+
import { readFileSync } from 'node:fs';
|
|
19
|
+
import { fileURLToPath } from 'node:url';
|
|
20
|
+
import { dirname, join } from 'node:path';
|
|
21
|
+
|
|
22
|
+
const require = createRequire(import.meta.url);
|
|
23
|
+
const db = require('../modules/lifecycle/db.js');
|
|
24
|
+
// createTask reads the shared pool destructured from the module-api doorway. That is
|
|
25
|
+
// the SAME singleton object db.js captured, so mutating its .query stubs the INSERT
|
|
26
|
+
// createTask runs — no database needed.
|
|
27
|
+
const sharedPool = require('../src/module-api.js').pool;
|
|
28
|
+
|
|
29
|
+
const __dir = dirname(fileURLToPath(import.meta.url));
|
|
30
|
+
const root = join(__dir, '..');
|
|
31
|
+
|
|
32
|
+
let passed = 0;
|
|
33
|
+
let failed = 0;
|
|
34
|
+
// `fn` may be sync or async. We register each as a thunk and run them sequentially
|
|
35
|
+
// at the end (preserving the interleaved console.log section headers' positions is
|
|
36
|
+
// not required — the count is what gates the exit code), so the async createTask
|
|
37
|
+
// tests below surface their assertions properly.
|
|
38
|
+
const _queue = [];
|
|
39
|
+
function t(name, fn) {
|
|
40
|
+
_queue.push(async () => {
|
|
41
|
+
try { await fn(); passed++; console.log(` PASS ${name}`); }
|
|
42
|
+
catch (e) { failed++; console.log(` FAIL ${name}\n ${e.message}`); }
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log('rewardMissing (0/NULL detection):');
|
|
47
|
+
|
|
48
|
+
t('NULL / undefined / 0 / negative are "missing"', () => {
|
|
49
|
+
assert.equal(db.rewardMissing(null), true);
|
|
50
|
+
assert.equal(db.rewardMissing(undefined), true);
|
|
51
|
+
assert.equal(db.rewardMissing(0), true);
|
|
52
|
+
assert.equal(db.rewardMissing(-5), true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
t('any positive reward is present', () => {
|
|
56
|
+
assert.equal(db.rewardMissing(1), false);
|
|
57
|
+
assert.equal(db.rewardMissing(40), false);
|
|
58
|
+
assert.equal(db.rewardMissing('40'), false); // string ints coerce
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
console.log('\nsuggestCreditsReward (capped — now PERSISTED at the gate):');
|
|
62
|
+
|
|
63
|
+
t('scales ~1 drachma/min, floored at 5, weighted by kind', () => {
|
|
64
|
+
assert.equal(db.suggestCreditsReward({ est_minutes: 40, kind: 'feature' }), 40);
|
|
65
|
+
// bug weight 1.25 -> 40 * 1.25 = 50
|
|
66
|
+
assert.equal(db.suggestCreditsReward({ est_minutes: 40, kind: 'bug' }), 50);
|
|
67
|
+
// tiny task still names a non-zero number (floor 5)
|
|
68
|
+
assert.equal(db.suggestCreditsReward({ est_minutes: 1, kind: 'cleanup' }), 5);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
t('missing/garbage est falls back to a ~30-min default, still positive', () => {
|
|
72
|
+
assert.ok(db.suggestCreditsReward({ kind: 'feature' }) >= 5);
|
|
73
|
+
assert.ok(db.suggestCreditsReward({ est_minutes: 0 }) >= 5);
|
|
74
|
+
assert.ok(db.suggestCreditsReward({}) >= 5);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
t('CAPPED at 60 (anti-gaming: est-inflation cannot balloon the auto-assigned pay)', () => {
|
|
78
|
+
assert.equal(db.REWARD_SUGGESTION_CAP, 60);
|
|
79
|
+
// a 1000-min estimate would be 1000 drachmae uncapped — clamped to the cap.
|
|
80
|
+
assert.equal(db.suggestCreditsReward({ est_minutes: 1000, kind: 'feature' }), 60);
|
|
81
|
+
// bug weight 1.25 on a big est is also clamped, not 1250.
|
|
82
|
+
assert.equal(db.suggestCreditsReward({ est_minutes: 1000, kind: 'bug' }), 60);
|
|
83
|
+
// every output is <= the cap.
|
|
84
|
+
for (const m of [5, 30, 60, 120, 600, 5000]) {
|
|
85
|
+
assert.ok(db.suggestCreditsReward({ est_minutes: m, kind: 'feature' }) <= 60);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
console.log('\nrewardGateAssignment (the shared AUTO-ASSIGN decision):');
|
|
90
|
+
|
|
91
|
+
t('an unrewarded task yields an assignment (capped suggestion), never a refusal', () => {
|
|
92
|
+
const a = db.rewardGateAssignment({ id: 99, credits_reward: 0, kind: 'feature', est_minutes: 40 });
|
|
93
|
+
assert.ok(a, 'should produce an assignment');
|
|
94
|
+
assert.equal(a.assign, 40);
|
|
95
|
+
// no error shape — the gate proceeds.
|
|
96
|
+
assert.equal(a.code, undefined);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
t('a NULL reward also yields an assignment', () => {
|
|
100
|
+
const a = db.rewardGateAssignment({ id: 1, credits_reward: null, kind: 'feature', est_minutes: 30 });
|
|
101
|
+
assert.ok(a);
|
|
102
|
+
assert.equal(a.assign, 30);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
t('a positive reward needs no assignment (returns null)', () => {
|
|
106
|
+
assert.equal(db.rewardGateAssignment({ id: 1, credits_reward: 40 }), null);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
t('GRANDFATHERED rows still get a value — reward_gate_exempt is now inert', () => {
|
|
110
|
+
// The amendment WANTS to value the grandfathered zero-reward tasks, so the
|
|
111
|
+
// exempt flag no longer suppresses the assignment.
|
|
112
|
+
const a = db.rewardGateAssignment({ id: 1, credits_reward: 0, reward_gate_exempt: true, kind: 'feature', est_minutes: 20 });
|
|
113
|
+
assert.ok(a, 'exempt zero-reward task should still be valued');
|
|
114
|
+
assert.equal(a.assign, 20);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
t('the assigned value never exceeds the cap', () => {
|
|
118
|
+
const a = db.rewardGateAssignment({ id: 1, credits_reward: 0, kind: 'feature', est_minutes: 9999 });
|
|
119
|
+
assert.ok(a.assign <= db.REWARD_SUGGESTION_CAP);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
t('null task is a no-op (no throw, no assignment)', () => {
|
|
123
|
+
assert.equal(db.rewardGateAssignment(null), null);
|
|
124
|
+
assert.equal(db.rewardGateAssignment(undefined), null);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
// Source-wiring assertions: the two enforcement points AUTO-ASSIGN (no longer
|
|
129
|
+
// refuse), and the migration reverts the 177 auto-promote reward clause. These
|
|
130
|
+
// fail closed if a future edit drops a wiring.
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
console.log('\nenforcement points (source-wiring — AUTO-ASSIGN):');
|
|
133
|
+
|
|
134
|
+
const tasksRouteSrc = readFileSync(join(root, 'modules/lifecycle/routes/tasks.js'), 'utf8');
|
|
135
|
+
const dbSrc = readFileSync(join(root, 'modules/lifecycle/db.js'), 'utf8');
|
|
136
|
+
const migration178 = readFileSync(join(root, 'migrations/178_reward_gate_auto_assign_revert_autopromote.sql'), 'utf8');
|
|
137
|
+
|
|
138
|
+
t('promote route AUTO-ASSIGNS then proceeds (no 409 refusal for missing reward)', () => {
|
|
139
|
+
const start = tasksRouteSrc.indexOf("router.post('/tasks/:id/promote'");
|
|
140
|
+
assert.ok(start >= 0, 'promote route not found');
|
|
141
|
+
const body = tasksRouteSrc.slice(start, start + 1600);
|
|
142
|
+
assert.match(body, /rewardGateAssignment/, 'promote route must consult the auto-assign decision');
|
|
143
|
+
assert.match(body, /setCreditsReward/, 'promote route must persist the assigned reward');
|
|
144
|
+
// it must assign BEFORE flipping to ready, and still flip to ready.
|
|
145
|
+
assert.ok(
|
|
146
|
+
body.indexOf('rewardGateAssignment') < body.indexOf("updateTaskStatus(id, 'ready')"),
|
|
147
|
+
'auto-assign must precede the ready flip'
|
|
148
|
+
);
|
|
149
|
+
assert.match(body, /updateTaskStatus\(id, 'ready'\)/, 'promote must still flip to ready');
|
|
150
|
+
// the old hard refusal must be gone — no REWARD_REQUIRED 409 in the promote body.
|
|
151
|
+
assert.ok(!/REWARD_REQUIRED/.test(body), 'promote must no longer return a REWARD_REQUIRED refusal');
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
t('claim path AUTO-ASSIGNS inside the FOR UPDATE transaction (never refuses)', () => {
|
|
155
|
+
const start = dbSrc.indexOf('async function claimTask');
|
|
156
|
+
assert.ok(start >= 0, 'claimTask not found');
|
|
157
|
+
const body = dbSrc.slice(start, start + 5000);
|
|
158
|
+
assert.match(body, /rewardGateAssignment\(task\)/, 'claimTask must consult the auto-assign decision');
|
|
159
|
+
assert.match(body, /UPDATE tasks SET credits_reward/, 'claimTask must persist the assigned reward in-tx');
|
|
160
|
+
// it must SELECT the columns the gate needs.
|
|
161
|
+
assert.match(body, /credits_reward/, 'claimTask FOR UPDATE select must include credits_reward');
|
|
162
|
+
// no hard throw of the old refusal from the reward gate inside claimTask.
|
|
163
|
+
assert.ok(!/throw rewardErr/.test(body), 'claimTask must no longer throw a reward refusal');
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
t('an AUDIT line is logged on each auto-assignment (route + claim)', () => {
|
|
167
|
+
assert.match(dbSrc, /\[reward-gate\] AUTO-ASSIGN/, 'db.js must log an audit line on auto-assign');
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
// task 1677 / ADR 0096 (2026-06-28): creation is now the PRIMARY assignment point.
|
|
172
|
+
// db.createTask auto-assigns a capped credits_reward at the LOWEST create layer when
|
|
173
|
+
// the caller supplies no positive value, so EVERY create-vector inherits a born-with
|
|
174
|
+
// drachmae value. promote/claim stays the backstop. We pin the behavior with a real
|
|
175
|
+
// invocation of createTask against a stub pool (no DB), then source-wire the route.
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
console.log('\ncreation-time auto-assign (db.createTask — the PRIMARY point):');
|
|
178
|
+
|
|
179
|
+
// createTask reads the module-level `pool`; stub its .query so we can capture the
|
|
180
|
+
// credits_reward bound into the INSERT without a database.
|
|
181
|
+
async function withStubbedCreatePool(run) {
|
|
182
|
+
const captured = {};
|
|
183
|
+
const realQuery = sharedPool.query;
|
|
184
|
+
sharedPool.query = async (sql, params) => {
|
|
185
|
+
if (/INSERT INTO tasks/.test(sql)) {
|
|
186
|
+
// credits_reward is the 11th bind ($11) — see the createTask INSERT column order.
|
|
187
|
+
captured.creditsReward = params[10];
|
|
188
|
+
return { rows: [{ id: 4242, credits_reward: params[10] }] };
|
|
189
|
+
}
|
|
190
|
+
return { rows: [] };
|
|
191
|
+
};
|
|
192
|
+
try { return await run(captured); }
|
|
193
|
+
finally { sharedPool.query = realQuery; }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
t('a task CREATED with NO reward is born with a positive, capped value', async () => {
|
|
197
|
+
await withStubbedCreatePool(async (captured) => {
|
|
198
|
+
const row = await db.createTask({ versionId: 1, title: 't', kind: 'feature', estMinutes: 40 });
|
|
199
|
+
assert.ok(captured.creditsReward > 0, 'INSERT must bind a positive credits_reward');
|
|
200
|
+
assert.equal(captured.creditsReward, 40, 'feature @40min -> 40 drachmae');
|
|
201
|
+
assert.ok(captured.creditsReward <= db.REWARD_SUGGESTION_CAP, 'must respect the cap');
|
|
202
|
+
assert.equal(row.credits_reward, 40, 'returned row carries the assigned value');
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
t('a task CREATED with credits_reward 0 (the route default) is auto-assigned', async () => {
|
|
207
|
+
await withStubbedCreatePool(async (captured) => {
|
|
208
|
+
await db.createTask({ versionId: 1, title: 't', creditsReward: 0, kind: 'bug', estMinutes: 40 });
|
|
209
|
+
// bug weight 1.25 -> 50; 0 is treated as "unset" so the default kicks in.
|
|
210
|
+
assert.equal(captured.creditsReward, 50);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
t('a huge-est new task is CAPPED at creation, not ballooned', async () => {
|
|
215
|
+
await withStubbedCreatePool(async (captured) => {
|
|
216
|
+
await db.createTask({ versionId: 1, title: 't', kind: 'feature', estMinutes: 9999 });
|
|
217
|
+
assert.equal(captured.creditsReward, db.REWARD_SUGGESTION_CAP);
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
t('an EXPLICIT positive credits_reward is PRESERVED (never overridden)', async () => {
|
|
222
|
+
await withStubbedCreatePool(async (captured) => {
|
|
223
|
+
await db.createTask({ versionId: 1, title: 't', creditsReward: 17, kind: 'feature', estMinutes: 40 });
|
|
224
|
+
assert.equal(captured.creditsReward, 17, 'author-set positive value must survive untouched');
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
t('createTask logs a [creation] audit line on auto-assign', () => {
|
|
229
|
+
const start = dbSrc.indexOf('async function createTask');
|
|
230
|
+
// Scan the REAL createTask body — from its declaration to the next top-level
|
|
231
|
+
// function (findTaskBySourceRef) — so the assertions hold as createTask grows
|
|
232
|
+
// rather than depending on a magic window size. A fixed 4800-char window
|
|
233
|
+
// silently broke when task 1763 added the goal_id fallback before the INSERT,
|
|
234
|
+
// sliding the [creation] audit line past its end.
|
|
235
|
+
const end = dbSrc.indexOf('async function findTaskBySourceRef', start);
|
|
236
|
+
const body = dbSrc.slice(start, end > start ? end : start + 6000);
|
|
237
|
+
assert.match(body, /suggestCreditsReward/, 'createTask must reuse the capped helper');
|
|
238
|
+
assert.match(body, /\[reward-gate\] AUTO-ASSIGN.*\[creation\]/s, 'createTask must log a [creation] audit line');
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
t('POST /tasks surfaces the assigned credits_reward in the 201 response', () => {
|
|
242
|
+
const start = tasksRouteSrc.indexOf("router.post('/tasks'");
|
|
243
|
+
assert.ok(start >= 0, 'POST /tasks route not found');
|
|
244
|
+
// Scan the REAL POST /tasks handler — from its declaration to the NEXT route
|
|
245
|
+
// registration — so the assertion holds as the handler grows rather than
|
|
246
|
+
// depending on a magic window size (same fix as the createTask sibling above).
|
|
247
|
+
// A fixed 11000-char window silently broke when the handler grew and slid the
|
|
248
|
+
// `credits_reward: task.credits_reward` response line to offset 11027, 27 chars
|
|
249
|
+
// past the window — failing on main and reddening every PR's `unit` check
|
|
250
|
+
// (task 2026; supersedes the never-pushed task 1967, same brittleness).
|
|
251
|
+
const end = tasksRouteSrc.indexOf('router.', start + 'router.post'.length);
|
|
252
|
+
const body = tasksRouteSrc.slice(start, end > start ? end : start + 13000);
|
|
253
|
+
assert.match(body, /credits_reward: task\.credits_reward/, 'response must surface the born-with reward');
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
t('the promote/claim backstop is KEPT (not removed by the creation-time change)', () => {
|
|
257
|
+
// The backstop fires rarely now but still covers any legacy/edge 0-reward path.
|
|
258
|
+
assert.match(dbSrc, /\[promote\]/, 'promote backstop audit line must remain');
|
|
259
|
+
assert.match(dbSrc, /\[claim by builder/, 'claim backstop audit line must remain');
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
console.log('\nmigration 178 (revert the 177 auto-promote reward clause):');
|
|
263
|
+
|
|
264
|
+
t('reverts task_is_fully_unblocked to the deps-doneness predicate', () => {
|
|
265
|
+
assert.match(migration178, /CREATE OR REPLACE FUNCTION task_is_fully_unblocked/);
|
|
266
|
+
// the dependency gate survives intact.
|
|
267
|
+
assert.match(migration178, /WITH gating AS/);
|
|
268
|
+
assert.match(migration178, /SELECT NOT EXISTS/);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
t('the 177 reward-gate clause is GONE from the reverted predicate', () => {
|
|
272
|
+
assert.ok(
|
|
273
|
+
!/reward_gate_exempt = true OR COALESCE\(t\.credits_reward, 0\) > 0/.test(migration178),
|
|
274
|
+
'migration 178 must NOT carry the 177 reward clause'
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
t('says the reward_gate_exempt column is now inert', () => {
|
|
279
|
+
assert.match(migration178, /inert|INERT/);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
for (const run of _queue) { await run(); }
|
|
283
|
+
console.log(`\n${passed} passed, ${failed} failed`);
|
|
284
|
+
process.exit(failed === 0 ? 0 : 1);
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
// tests/route_rank_check.mjs
|
|
2
|
+
//
|
|
3
|
+
// Deterministic route-rank check (#475 / C7). Covers the pure classifier
|
|
4
|
+
// (classifyText), the invariant (checkRouteRanks → findings/hardFail), the
|
|
5
|
+
// pseudo-worker shaping (toWorkerResult), and a LIVE assertion that every
|
|
6
|
+
// route currently declared under src/bongos/routes/ classifies to a known rank
|
|
7
|
+
// (the GET /public/repo-info multi-line-comment parse, fixed here).
|
|
8
|
+
//
|
|
9
|
+
// Run: node tests/route_rank_check.mjs
|
|
10
|
+
|
|
11
|
+
import { strict as assert } from 'node:assert';
|
|
12
|
+
import { createRequire } from 'node:module';
|
|
13
|
+
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
const rrc = require('../src/bongos/route-rank-check.js');
|
|
16
|
+
|
|
17
|
+
let passed = 0;
|
|
18
|
+
let failed = 0;
|
|
19
|
+
function test(name, fn) {
|
|
20
|
+
try {
|
|
21
|
+
fn();
|
|
22
|
+
console.log(` ok ${name}`);
|
|
23
|
+
passed++;
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.error(` FAIL ${name}`);
|
|
26
|
+
console.error(` ${err.message}`);
|
|
27
|
+
failed++;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ---------- classifyText: middleware-chain classification ----------
|
|
32
|
+
|
|
33
|
+
test('requireRank(archon) → archon', () => {
|
|
34
|
+
const r = rrc.classifyText(`router.post('/x', auth.requireBuilder, auth.requireRank('archon'), h);`);
|
|
35
|
+
assert.equal(r[0].rank, 'archon');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('requireRank(metic, archon) → metic+archon', () => {
|
|
39
|
+
const r = rrc.classifyText(`router.post('/x', auth.requireRank('metic', 'archon'), h);`);
|
|
40
|
+
assert.equal(r[0].rank, 'metic+archon');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('requireRank(xenos,...) → any-builder', () => {
|
|
44
|
+
const r = rrc.classifyText(`router.post('/x', auth.requireRank('xenos', 'metic', 'archon'), h);`);
|
|
45
|
+
assert.equal(r[0].rank, 'any-builder');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('requireBuilder only → any-builder', () => {
|
|
49
|
+
const r = rrc.classifyText(`router.get('/x', auth.requireBuilder, h);`);
|
|
50
|
+
assert.equal(r[0].rank, 'any-builder');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('requireBfgPrincipal → bfg-principal (identity gate wins over the requireBuilder beside it)', () => {
|
|
54
|
+
const r = rrc.classifyText(`router.post('/x', auth.requireBuilder, auth.requireBfgPrincipal, h);`);
|
|
55
|
+
assert.equal(r[0].rank, 'bfg-principal', 'the BFG cross-builder write route must classify as the principal gate, not any-builder');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('multi-line declaration: middleware on the next line still classifies', () => {
|
|
59
|
+
const r = rrc.classifyText(`router.post('/x',\n auth.requireRank('archon'),\n handler);`);
|
|
60
|
+
assert.equal(r[0].rank, 'archon');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('a nested requireRank in the HANDLER BODY does not downgrade the route [regression]', () => {
|
|
64
|
+
// Only the route's own middleware list decides its rank; a requireRank call
|
|
65
|
+
// inside the handler body (within the 20-line scan window) must be ignored.
|
|
66
|
+
const src = `router.post('/admin', auth.requireRank('archon'), async (req, res) => {\n` +
|
|
67
|
+
` if (foo) bar(auth.requireRank('xenos'));\n` +
|
|
68
|
+
` res.end();\n});`;
|
|
69
|
+
assert.equal(rrc.classifyText(src)[0].rank, 'archon');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('a route declared with NO middleware does not borrow the NEXT route\'s rank [regression]', () => {
|
|
73
|
+
// A short GET handler must not bleed into the following route's requireRank.
|
|
74
|
+
const src = `router.get('/list', async (req, res) => {\n` +
|
|
75
|
+
` res.json([]);\n});\n` +
|
|
76
|
+
`router.post('/list', auth.requireRank('archon'), async (req, res) => {\n` +
|
|
77
|
+
` res.end();\n});`;
|
|
78
|
+
const rows = rrc.classifyText(src);
|
|
79
|
+
assert.equal(rows.find((x) => x.method === 'GET').rank, 'unknown'); // no middleware, no annotation
|
|
80
|
+
assert.equal(rows.find((x) => x.method === 'POST').rank, 'archon');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// ---------- classifyText: `rank:` annotation fallback ----------
|
|
84
|
+
|
|
85
|
+
test('rank: annotation directly above → classifies', () => {
|
|
86
|
+
const r = rrc.classifyText(` // rank: public\n router.get('/x', h);`);
|
|
87
|
+
assert.equal(r[0].rank, 'public');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('rank: annotation atop a 6-line comment block (the repo-info case) → classifies', () => {
|
|
91
|
+
const src = [
|
|
92
|
+
' // rank: public — GitHub URL bases for the deployed checkout',
|
|
93
|
+
' // line 2 of the block',
|
|
94
|
+
' // line 3',
|
|
95
|
+
' // line 4',
|
|
96
|
+
' // line 5',
|
|
97
|
+
' // line 6',
|
|
98
|
+
" router.get('/public/repo-info', h);",
|
|
99
|
+
].join('\n');
|
|
100
|
+
const r = rrc.classifyText(src);
|
|
101
|
+
assert.equal(r[0].rank, 'public', 'whole contiguous comment block must be scanned, not a 5-line window');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('annotation does not leak across a prior route body (stops at code)', () => {
|
|
105
|
+
const src = [
|
|
106
|
+
" // rank: archon",
|
|
107
|
+
" router.post('/a', h);", // /a → archon, from the annotation directly above it
|
|
108
|
+
' });',
|
|
109
|
+
" router.get('/b', h);", // /b → unknown: no annotation, no middleware, prior line is code (the }); above)
|
|
110
|
+
].join('\n');
|
|
111
|
+
const r = rrc.classifyText(src);
|
|
112
|
+
assert.equal(r[0].rank, 'archon');
|
|
113
|
+
assert.equal(r[1].rank, 'unknown', 'the /a annotation must not bleed down to /b past the }); code line');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('typo annotation (not a known rank) → unknown', () => {
|
|
117
|
+
const r = rrc.classifyText(` // rank: any-builders\n router.get('/x', h);`);
|
|
118
|
+
assert.equal(r[0].rank, 'unknown', 'a misspelled rank surfaces rather than being trusted');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// ---------- checkRouteRanks invariant (via a fixture-free routesDir shim) ----------
|
|
122
|
+
// checkRouteRanks reads files; we exercise the finding logic through the pure
|
|
123
|
+
// path by constructing routes through classifyText + the documented severity
|
|
124
|
+
// rule. (The live filesystem assertion below covers the fs path end-to-end.)
|
|
125
|
+
|
|
126
|
+
test('toWorkerResult: clean → pass, no issues', () => {
|
|
127
|
+
const w = rrc.toWorkerResult({ ok: true, hardFail: false, routeCount: 40, routes: [], findings: [] });
|
|
128
|
+
assert.equal(w.verdict, 'pass');
|
|
129
|
+
assert.equal(w.kind, 'route-rank');
|
|
130
|
+
assert.equal(w.issues.length, 0);
|
|
131
|
+
assert.equal(w.confidence, 1);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('toWorkerResult: write-unknown → fail with a blocker issue', () => {
|
|
135
|
+
const findings = [{ severity: 'blocker', file: 'src/bongos/routes/x.js', route: 'POST /x', method: 'POST', rank: 'unknown', summary: 'no gate' }];
|
|
136
|
+
const w = rrc.toWorkerResult({ ok: false, hardFail: true, routeCount: 40, routes: [], findings });
|
|
137
|
+
assert.equal(w.verdict, 'fail');
|
|
138
|
+
assert.equal(w.issues.length, 1);
|
|
139
|
+
assert.equal(w.issues[0].severity, 'blocker');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test('toWorkerResult: read-unknown only → concerns (not fail)', () => {
|
|
143
|
+
const findings = [{ severity: 'major', file: 'src/bongos/routes/x.js', route: 'GET /x', method: 'GET', rank: 'unknown', summary: 'confirm public' }];
|
|
144
|
+
const w = rrc.toWorkerResult({ ok: false, hardFail: false, routeCount: 40, routes: [], findings });
|
|
145
|
+
assert.equal(w.verdict, 'concerns');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// ---------- EXPECTED_RANKS: exact-rank pin on privileged routes (#999) ----------
|
|
149
|
+
|
|
150
|
+
test('EXPECTED_RANKS: pins are non-empty and all to known ranks', () => {
|
|
151
|
+
const keys = Object.keys(rrc.EXPECTED_RANKS);
|
|
152
|
+
assert.ok(keys.length > 0, 'should pin at least one privileged route');
|
|
153
|
+
for (const [k, v] of Object.entries(rrc.EXPECTED_RANKS)) {
|
|
154
|
+
assert.ok(rrc.KNOWN_RANKS.has(v), `pinned expected rank '${v}' for ${k} must be a known rank`);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test('EXPECTED_RANKS: a DOWNGRADE on a pinned route trips a blocker via a routesDir shim', () => {
|
|
159
|
+
// Build a synthetic routes dir whose every pinned route is present, but one
|
|
160
|
+
// archon-pinned route (PATCH /builders/:id/rank) has been silently downgraded
|
|
161
|
+
// to requireBuilder. The base "must classify" loop would wave this through
|
|
162
|
+
// (it classifies to a KNOWN rank, 'any-builder') — the pin is what catches it.
|
|
163
|
+
const os = require('node:os');
|
|
164
|
+
const fs = require('node:fs');
|
|
165
|
+
const path = require('node:path');
|
|
166
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'rrc-'));
|
|
167
|
+
const lines = [];
|
|
168
|
+
const emit = (key, expected) => {
|
|
169
|
+
const [method, route] = key.split(' ');
|
|
170
|
+
const m = method.toLowerCase();
|
|
171
|
+
if (key === 'PATCH /builders/:id/rank') {
|
|
172
|
+
// DOWNGRADE: requireBuilder only → classifies any-builder, not archon.
|
|
173
|
+
lines.push(` router.${m}('${route}', auth.requireBuilder, h);`);
|
|
174
|
+
} else if (expected === 'archon') {
|
|
175
|
+
lines.push(` router.${m}('${route}', auth.requireBuilder, auth.requireRank('archon'), h);`);
|
|
176
|
+
} else if (expected === 'metic+archon') {
|
|
177
|
+
lines.push(` router.${m}('${route}', auth.requireRank('metic', 'archon'), h);`);
|
|
178
|
+
} else {
|
|
179
|
+
lines.push(` // rank: ${expected}`);
|
|
180
|
+
lines.push(` router.${m}('${route}', h);`);
|
|
181
|
+
}
|
|
182
|
+
// A blank gap matching a real handler body — keeps classifyRank's 20-line
|
|
183
|
+
// middleware lookahead on the downgraded route from "borrowing" a NEIGHBOUR
|
|
184
|
+
// route's requireRank('archon') line.
|
|
185
|
+
lines.push(' });', '', '', '', '', '', '');
|
|
186
|
+
};
|
|
187
|
+
// Emit every pinned route EXCEPT the downgraded one first, then the downgraded
|
|
188
|
+
// one LAST (so nothing with requireRank('archon') sits within its lookahead).
|
|
189
|
+
for (const [key, expected] of Object.entries(rrc.EXPECTED_RANKS)) {
|
|
190
|
+
if (key !== 'PATCH /builders/:id/rank') emit(key, expected);
|
|
191
|
+
}
|
|
192
|
+
emit('PATCH /builders/:id/rank', rrc.EXPECTED_RANKS['PATCH /builders/:id/rank']);
|
|
193
|
+
fs.writeFileSync(path.join(dir, 'shim.js'), lines.join('\n'));
|
|
194
|
+
const res = rrc.checkRouteRanks({ routesDir: dir });
|
|
195
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
196
|
+
|
|
197
|
+
const downgrade = res.findings.find((f) => f.route === 'PATCH /builders/:id/rank');
|
|
198
|
+
assert.ok(downgrade, 'a downgraded pinned route must surface a finding');
|
|
199
|
+
assert.equal(downgrade.severity, 'blocker', 'a rank downgrade on a privileged route is a hard fail');
|
|
200
|
+
assert.equal(res.hardFail, true);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test('EXPECTED_RANKS: a MISSING pinned route trips a blocker (a protected route vanished)', () => {
|
|
204
|
+
const os = require('node:os');
|
|
205
|
+
const fs = require('node:fs');
|
|
206
|
+
const path = require('node:path');
|
|
207
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'rrc-'));
|
|
208
|
+
// Empty routes dir → every pinned route is "missing".
|
|
209
|
+
fs.writeFileSync(path.join(dir, 'empty.js'), '// no routes here\n');
|
|
210
|
+
const res = rrc.checkRouteRanks({ routesDir: dir });
|
|
211
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
212
|
+
const missing = res.findings.find((f) => f.rank === '(missing)');
|
|
213
|
+
assert.ok(missing, 'a pinned route absent from the route set must surface a finding');
|
|
214
|
+
assert.equal(missing.severity, 'blocker');
|
|
215
|
+
assert.equal(res.hardFail, true);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// ---------- LIVE: every real route classifies to a known rank ----------
|
|
219
|
+
|
|
220
|
+
test('LIVE: checkRouteRanks() on src/bongos/routes/ has zero unknowns', () => {
|
|
221
|
+
const res = rrc.checkRouteRanks();
|
|
222
|
+
assert.ok(res.routeCount > 0, 'should discover routes');
|
|
223
|
+
const unknowns = res.findings.map((f) => f.route);
|
|
224
|
+
assert.equal(res.findings.length, 0,
|
|
225
|
+
`every route must classify to a known rank; unclassified: ${unknowns.join(', ')}`);
|
|
226
|
+
assert.equal(res.ok, true);
|
|
227
|
+
assert.equal(res.hardFail, false);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
test('LIVE: every pinned privileged route still classifies to its EXPECTED rank', () => {
|
|
231
|
+
const res = rrc.checkRouteRanks();
|
|
232
|
+
const byKey = new Map();
|
|
233
|
+
for (const r of res.routes) if (!byKey.has(r.key)) byKey.set(r.key, r);
|
|
234
|
+
for (const [key, expected] of Object.entries(rrc.EXPECTED_RANKS)) {
|
|
235
|
+
const r = byKey.get(key);
|
|
236
|
+
assert.ok(r, `pinned route ${key} must exist in the live route set`);
|
|
237
|
+
assert.equal(r.rank, expected, `pinned route ${key} must classify as '${expected}', got '${r.rank}'`);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
console.log('');
|
|
242
|
+
console.log(`Route-rank-check tests: ${passed} passed, ${failed} failed`);
|
|
243
|
+
if (failed > 0) process.exit(1);
|