@bongos/core 1.23.22 → 1.24.2
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 +933 -413
- package/.claude/skills/blocker-review/SKILL.md +9 -1
- package/.claude/skills/blocker-solve/SKILL.md +1 -1
- package/.claude/skills/builder-claim/SKILL.md +1 -1
- package/.claude/skills/builder-reauth/SKILL.md +1 -1
- package/.claude/skills/builder-redteam/SKILL.md +1 -1
- package/.claude/skills/builder-sequence/SKILL.md +1 -1
- package/.claude/skills/builder-setup/SKILL.md +1 -1
- package/.claude/skills/builder-ship/SKILL.md +1 -1
- package/.claude/skills/collab-review/SKILL.md +5 -2
- package/.claude/skills/design/SKILL.md +1 -1
- package/.claude/skills/goal-create/SKILL.md +2 -2
- package/.claude/skills/grade-recover/SKILL.md +1 -1
- package/.claude/skills/merge-mode/SKILL.md +1 -1
- package/.claude/skills/owner-review/SKILL.md +1 -1
- package/.claude/skills/planning-session/SKILL.md +11 -11
- package/.claude/skills/read-session-export/SKILL.md +1 -1
- package/.claude/skills/recall/SKILL.md +1 -1
- package/.claude/skills/scan-before-install/SKILL.md +1 -1
- package/.claude/skills/session-handoff/SKILL.md +1 -1
- package/.claude/skills/strand-fix/SKILL.md +13 -0
- package/.claude/skills/worktree-clean/SKILL.md +1 -1
- package/AGENTS.md +15 -0
- package/GEMINI.md +5 -0
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +96 -0
- package/clients/bongos-client/index.cjs +96 -0
- package/clients/bongos-client/index.d.ts +155 -4
- package/clients/bongos-client/index.mjs +96 -0
- package/docs/adr/0054-session-token-reward-cost-plus.md +3 -1
- package/docs/adr/0055-server-mediated-branch-publish.md +1 -1
- package/docs/adr/0385-money-lives-with-a-processor-credits-stay-a-project-meter.md +12 -1
- package/docs/adr/0393-a-platform-account-is-a-person-and-github-is-one-way-in.md +37 -0
- package/docs/adr/0394-market-watch-searches-through-the-messages-api-on-the-projects-key-and-runs-from-its-own-poller.md +102 -0
- package/docs/adr/0395-a-task-says-what-it-needs-and-lists-show-only-what-you-can-do.md +36 -0
- package/docs/adr/0396-google-sign-in-a-stand-in-login-and-a-browser-approved-cli-sign-in.md +41 -0
- package/docs/adr/README.md +6 -2
- package/docs/api/openapi.json +8651 -5833
- package/docs/api-reference.md +66 -10
- package/docs/architecture.md +37 -1
- package/docs/canonical-permissions.md +1 -1
- package/docs/copy-inventory.md +427 -339
- package/docs/copy-registry.json +1376 -500
- package/docs/file-map.md +1 -0
- package/docs/module-api-changelog.md +7 -0
- package/docs/onboarding/diagrams/03-drachmae-karma.mmd +3 -3
- package/docs/onboarding/diagrams/README.md +1 -1
- package/docs/onboarding/drachmae-and-karma.md +15 -15
- package/docs/onboarding/primer.md +2 -2
- package/docs/page-inventory.json +57 -7
- package/docs/page-readings.json +1210 -1027
- package/docs/recipes/google-sign-in.md +60 -0
- package/docs/recipes/ops-gotchas.md +1 -1
- package/migrations/core_282_builders_lower_login_idx.sql +33 -0
- package/migrations/core_283_claimable_ignores_page_markers.sql +53 -0
- package/migrations/core_283_payout_approvals.sql +183 -0
- package/migrations/core_284_payout_gates.sql +179 -0
- package/migrations/core_285_task_needs.sql +74 -0
- package/modules/ai-studio/billing.js +67 -0
- package/modules/ai-studio/context.js +29 -0
- package/modules/ai-studio/db.js +172 -0
- package/modules/ai-studio/gemini.js +75 -0
- package/modules/ai-studio/generate.js +119 -0
- package/modules/ai-studio/keys.js +73 -0
- package/modules/ai-studio/migrations/ai_studio_001_keys.sql +22 -0
- package/modules/ai-studio/migrations/ai_studio_002_ledger.sql +48 -0
- package/modules/ai-studio/migrations/ai_studio_003_requests.sql +55 -0
- package/modules/ai-studio/openrouter.js +90 -0
- package/modules/ai-studio/payments.js +105 -0
- package/modules/ai-studio/pricing.js +92 -0
- package/modules/ai-studio/routes/ai-studio.js +235 -5
- package/modules/ai-studio/studio.js +121 -0
- package/modules/autonomy/fence.js +64 -1
- package/modules/builder-settings/builder-needs.js +27 -1
- package/modules/copy-desk/routes/copy-desk.js +5 -0
- package/modules/economy/achievements.js +22 -10
- package/modules/economy/cost-classify.js +9 -0
- package/modules/economy/cost-write-guard.js +52 -0
- package/modules/economy/cost.js +2 -1
- package/modules/economy/credits.js +18 -15
- package/modules/economy/goal-reward.js +161 -0
- package/modules/economy/reward.js +4 -0
- package/modules/economy/routes/cost.js +33 -7
- package/modules/government/access-routes.js +70 -0
- package/modules/government/access.js +88 -0
- package/modules/government/asks.js +5 -2
- package/modules/government/catalog.js +6 -0
- package/modules/government/db.js +72 -0
- package/modules/government/docket.js +48 -2
- package/modules/government/migrations/government_035_payout_approve.sql +29 -0
- package/modules/government/migrations/government_036_access_holders.sql +33 -0
- package/modules/government/pollers/board-expiry.js +108 -20
- package/modules/government/protected-surfaces.json +1 -0
- package/modules/government/routes/government.js +31 -0
- package/modules/government/routing.js +49 -7
- package/modules/government/waiting.js +78 -0
- package/modules/hall-ui/public/ai-studio-lib.js +268 -0
- package/modules/hall-ui/public/ai-studio.css +193 -0
- package/modules/hall-ui/public/ai-studio.html +98 -0
- package/modules/hall-ui/public/ai-studio.js +556 -0
- package/modules/hall-ui/public/ai-studio.states.json +94 -0
- package/modules/hall-ui/public/blockers-by-person.js +158 -0
- package/modules/hall-ui/public/blockers-lib.js +15 -1
- package/modules/hall-ui/public/blockers.html +8 -0
- package/modules/hall-ui/public/blockers.js +1 -1
- package/modules/hall-ui/public/claim-action.js +3 -0
- package/modules/hall-ui/public/collab.html +12 -0
- package/modules/hall-ui/public/craft-mode.js +4 -1
- package/modules/hall-ui/public/criterion-uat-ui.js +4 -1
- package/modules/hall-ui/public/drachmae.html +1 -1
- package/modules/hall-ui/public/genesis/r5-life-1-primordial-sea.jpg +0 -0
- package/modules/hall-ui/public/genesis/r5-life-2-first-cells-cut.webp +0 -0
- package/modules/hall-ui/public/genesis/r5-life-2-first-cells.jpg +0 -0
- package/modules/hall-ui/public/genesis/r5-life-3-genome-cut.webp +0 -0
- package/modules/hall-ui/public/genesis/r5-life-3-genome.jpg +0 -0
- package/modules/hall-ui/public/genesis/r5-life-4-membrane-cut.webp +0 -0
- package/modules/hall-ui/public/genesis/r5-life-4-membrane.jpg +0 -0
- package/modules/hall-ui/public/genesis/r5-life-5-nervous-system-cut.webp +0 -0
- package/modules/hall-ui/public/genesis/r5-life-5-nervous-system.jpg +0 -0
- package/modules/hall-ui/public/goal-inbox.js +1 -1
- package/modules/hall-ui/public/goals-render.js +4 -0
- package/modules/hall-ui/public/goals.html +8 -0
- package/modules/hall-ui/public/gov-living.js +6 -2
- package/modules/hall-ui/public/government-access.js +108 -0
- package/modules/hall-ui/public/government.html +21 -0
- package/modules/hall-ui/public/hall-ask.css +5 -0
- package/modules/hall-ui/public/hall-ask.js +39 -3
- package/modules/hall-ui/public/notes-panel.css +20 -0
- package/modules/hall-ui/public/notes-panel.js +146 -0
- package/modules/hall-ui/public/project-settings.html +1 -1
- package/modules/hall-ui/public/project-settings.js +7 -5
- package/modules/hall-ui/public/settings-ai-keys.js +124 -0
- package/modules/hall-ui/public/settings.html +15 -0
- package/modules/hall-ui/public/street-deck.js +12 -3
- package/modules/hall-ui/public/studio.css +90 -8
- package/modules/hall-ui/public/studio.html +39 -10
- package/modules/hall-ui/public/studio.js +148 -18
- package/modules/hall-ui/public/task.html +2 -0
- package/modules/hall-ui/public/task.js +4 -0
- package/modules/hall-ui/public/tweak-editor.js +12 -3
- package/modules/hall-ui/public/welcome-boot.css +42 -6
- package/modules/hall-ui/public/welcome-boot.js +20 -6
- package/modules/hall-ui/public/work.js +20 -0
- package/modules/hall-ui/records/ai-studio.md +36 -0
- package/modules/hall-ui/records/blockers-people.md +38 -0
- package/modules/lifecycle/db-claims.js +32 -4
- package/modules/lifecycle/db-goals.js +18 -5
- package/modules/lifecycle/db-tasks.js +15 -6
- package/modules/lifecycle/done-when.js +23 -1
- package/modules/lifecycle/lifecycle.js +5 -0
- package/modules/lifecycle/migrations/lifecycle_017_notes.sql +46 -0
- package/modules/lifecycle/module.json +2 -1
- package/modules/lifecycle/notes.js +219 -0
- package/modules/lifecycle/page-notice.js +124 -0
- package/modules/lifecycle/page-tweak-artist.js +18 -1
- package/modules/lifecycle/publish-reconciler.js +67 -20
- package/modules/lifecycle/routes/claims.js +5 -2
- package/modules/lifecycle/routes/goals.js +3 -1
- package/modules/lifecycle/routes/notes.js +91 -0
- package/modules/lifecycle/routes/project-settings.js +43 -35
- package/modules/lifecycle/routes/task-route-helpers.js +21 -0
- package/modules/lifecycle/routes/task-write-routes.js +21 -3
- package/modules/lifecycle/routes/tasks.js +12 -12
- package/modules/lifecycle/task-needs-gate.js +70 -0
- package/modules/market-watch/CLAUDE.md +15 -0
- package/modules/market-watch/db.js +340 -0
- package/modules/market-watch/key.js +58 -0
- package/modules/market-watch/migrations/market_watch_001_tables.sql +249 -0
- package/modules/market-watch/migrations/market_watch_002_run.sql +46 -0
- package/modules/market-watch/module.json +26 -0
- package/modules/market-watch/pollers/hub-seed.js +54 -0
- package/modules/market-watch/pollers/weekly-run.js +100 -0
- package/modules/market-watch/research.js +350 -0
- package/modules/market-watch/run.js +245 -0
- package/modules/market-watch/seed/market-data.json +38 -0
- package/modules/market-watch/seed/partners-data.json +497 -0
- package/modules/market-watch/seed.js +252 -0
- package/modules/market-watch/store.js +230 -0
- package/modules/memory/routes/memory.js +14 -2
- package/modules/memory/routes/search.js +8 -2
- package/modules/platform-identity/account-logins.js +192 -0
- package/modules/platform-identity/migrations/platform_identity_034_account_logins.sql +96 -0
- package/modules/platform-identity/platform-identity.js +5 -4
- package/modules/platform-identity/routes/my-projects.js +6 -0
- package/modules/platform-identity/routes/profile.js +18 -0
- package/modules/platform-identity/routes/public-profile.js +10 -1
- package/modules/platform-identity/routes/sso.js +26 -1
- package/modules/platform-identity/tests/platform-identity.mjs +2 -1
- package/modules/provisioning/credential-preflight.js +13 -3
- package/modules/provisioning/pollers/app-liveness.js +25 -5
- package/modules/provisioning/routes/provisioning.js +1 -1
- package/modules/provisioning/starter-bundles.js +6 -2
- package/modules/public-landing/public/account.html +10 -2
- package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.jpg +0 -0
- package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.webp +0 -0
- package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r2-chrome-blob-one-cut.webp +0 -0
- package/modules/public-landing/public/assets/world/r2-chrome-blob-one-cut.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r2-chrome-blob-one.jpg +0 -0
- package/modules/public-landing/public/assets/world/r2-chrome-blob-one.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r2-chrome-blob-one.webp +0 -0
- package/modules/public-landing/public/assets/world/r2-chrome-blob-one.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.jpg +0 -0
- package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.webp +0 -0
- package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r3-frost-bead-cut.webp +0 -0
- package/modules/public-landing/public/assets/world/r3-frost-bead-cut.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r3-frost-pair-cut.webp +0 -0
- package/modules/public-landing/public/assets/world/r3-frost-pair-cut.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r3-gold-blob-cut.webp +0 -0
- package/modules/public-landing/public/assets/world/r3-gold-blob-cut.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r3-gold-pair-cut.webp +0 -0
- package/modules/public-landing/public/assets/world/r3-gold-pair-cut.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r3-obsidian-blob-cut.webp +0 -0
- package/modules/public-landing/public/assets/world/r3-obsidian-blob-cut.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r3-obsidian-pair-cut.webp +0 -0
- package/modules/public-landing/public/assets/world/r3-obsidian-pair-cut.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r3-space-nebula.jpg +0 -0
- package/modules/public-landing/public/assets/world/r3-space-nebula.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r4-card-chrome.jpg +0 -0
- package/modules/public-landing/public/assets/world/r4-card-chrome.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r4-card-nebula.jpg +0 -0
- package/modules/public-landing/public/assets/world/r4-card-nebula.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r5-life-1-primordial-sea.jpg +0 -0
- package/modules/public-landing/public/assets/world/r5-life-1-primordial-sea.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r5-life-2-first-cells-cut.webp +0 -0
- package/modules/public-landing/public/assets/world/r5-life-2-first-cells-cut.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r5-life-2-first-cells.jpg +0 -0
- package/modules/public-landing/public/assets/world/r5-life-2-first-cells.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r5-life-3-genome-cut.webp +0 -0
- package/modules/public-landing/public/assets/world/r5-life-3-genome-cut.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r5-life-3-genome.jpg +0 -0
- package/modules/public-landing/public/assets/world/r5-life-3-genome.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r5-life-4-membrane-cut.webp +0 -0
- package/modules/public-landing/public/assets/world/r5-life-4-membrane-cut.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r5-life-4-membrane.jpg +0 -0
- package/modules/public-landing/public/assets/world/r5-life-4-membrane.jpg.json +1 -1
- package/modules/public-landing/public/assets/world/r5-life-5-nervous-system-cut.webp +0 -0
- package/modules/public-landing/public/assets/world/r5-life-5-nervous-system-cut.webp.json +1 -1
- package/modules/public-landing/public/assets/world/r5-life-5-nervous-system.jpg +0 -0
- package/modules/public-landing/public/assets/world/r5-life-5-nervous-system.jpg.json +1 -1
- package/modules/public-landing/public/community.html +1 -1
- package/modules/public-landing/public/connections.html +2 -2
- package/modules/public-landing/public/guild.html +1 -1
- package/modules/public-landing/public/invitations.html +2 -2
- package/modules/public-landing/public/projects.html +5 -5
- package/modules/raise/views/nda.html +2 -0
- package/modules/specialities/db.js +32 -1
- package/modules/specialities/routes/specialities.js +10 -6
- package/modules/status-ui/public/index.html +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +230 -0
- package/scripts/bongos/autobongos-tweak-lane.js +46 -1
- package/scripts/bongos/backfill-subagent-rewards.js +2 -2
- package/scripts/bongos/claim.js +22 -1
- package/scripts/bongos/db-backup-nightly.sh +29 -0
- package/scripts/bongos/deploy-divergence.js +7 -0
- package/scripts/bongos/doc-cli-guard.js +6 -0
- package/scripts/bongos/fitness.js +3 -2
- package/scripts/bongos/gen-diagrams.js +3 -3
- package/scripts/bongos/government-walk.js +3 -0
- package/scripts/bongos/lib.sh +4 -5
- package/scripts/bongos/migration-namespace.js +13 -1
- package/scripts/bongos/plain-cards.js +4 -0
- package/scripts/bongos/provision-github-setup.js +3 -1
- package/scripts/bongos/provision-units.js +6 -1
- package/scripts/bongos/publish-manifest.js +3 -0
- package/scripts/bongos/release.js +2 -0
- package/scripts/bongos/run-unit-tests.js +268 -82
- package/scripts/bongos/seed-tasks.example.json +56 -0
- package/scripts/bongos/seed-tasks.js +222 -0
- package/scripts/bongos/seed-verify-criteria.js +1 -2
- package/scripts/bongos/ship-finish.js +2 -0
- package/scripts/bongos/ship-resume.js +2 -0
- package/scripts/bongos/strand-lease.js +250 -0
- package/scripts/bongos/strand-watch.js +26 -5
- package/scripts/bongos/version-literal-guard.js +2 -2
- package/scripts/discord/post.js +4 -3
- package/scripts/gds/seed-tasks.js +7 -0
- package/scripts/gds/{build-bongos.js → strand-lease.js} +3 -3
- package/scripts/hall-preview/server.js +21 -0
- package/src/bongos/auth-config.js +29 -1
- package/src/bongos/auth-discord.js +3 -3
- package/src/bongos/auth-github.js +3 -6
- package/src/bongos/auth-google.js +217 -0
- package/src/bongos/device-approval.js +140 -0
- package/src/bongos/llm-pricing.js +17 -1
- package/src/bongos/metrics.js +48 -2
- package/src/bongos/middleware/rate-limit.js +30 -11
- package/src/bongos/module-scope-map.js +12 -1
- package/src/bongos/optimizer.js +15 -1
- package/src/bongos/payout-approvals.js +342 -0
- package/src/bongos/payout-gates.js +364 -0
- package/src/bongos/prelaunch-gate.js +7 -9
- package/src/bongos/prelaunch-switch.js +20 -0
- package/src/bongos/route-rank-check.js +7 -0
- package/src/bongos/routes/auth-google.js +246 -0
- package/src/bongos/routes/auth.js +38 -1
- package/src/bongos/routes/backup.js +33 -9
- package/src/bongos/routes/builders.js +57 -30
- package/src/bongos/routes/github.js +9 -0
- package/src/bongos/routes/me.js +18 -0
- package/src/bongos/routes/my-payouts.js +133 -0
- package/src/bongos/routes/payout-approvals.js +312 -0
- package/src/bongos/routes/payout-gates.js +179 -0
- package/src/bongos/routes.js +15 -1
- package/src/bongos/secret-box.js +18 -3
- package/src/bongos/serve-internal.js +47 -19
- package/src/bongos/sign-in-pages.js +138 -0
- package/src/bongos/task-needs.js +146 -0
- package/src/bongos-downloads.js +18 -1
- package/src/instance-config.js +28 -0
- package/src/module-api.js +14 -1
- package/tests/access_holders.mjs +214 -0
- package/tests/account_logins.mjs +326 -0
- package/tests/account_logins_db.mjs +161 -0
- package/tests/ai_studio_billing.mjs +253 -0
- package/tests/ai_studio_generate.mjs +282 -0
- package/tests/ai_studio_keys.mjs +159 -0
- package/tests/ai_studio_requests.mjs +319 -0
- package/tests/auth_backchannel_logout_route.mjs +201 -0
- package/tests/auto_satisfy_criteria.mjs +10 -1
- package/tests/autobongos_tweak_lane.mjs +144 -0
- package/tests/autobongos_tweak_pin_identity.mjs +137 -0
- package/tests/backfill_subagent_rewards.mjs +17 -1
- package/tests/backup_trigger_lock.mjs +119 -0
- package/tests/blockers_people.mjs +198 -0
- package/tests/bounded_rate_maps.mjs +184 -0
- package/tests/claimable_blocker_status.mjs +1 -1
- package/tests/claims_batch_routes.mjs +421 -0
- package/tests/config_read_cache.mjs +171 -0
- package/tests/copy_desk_page_editor.mjs +12 -0
- package/tests/cost_write_guard.mjs +200 -0
- package/tests/craft_achievements.mjs +33 -10
- package/tests/criterion_goal_attach.mjs +1 -1
- package/tests/db_backup_nightly.mjs +73 -1
- package/tests/deploy_divergence_line.mjs +7 -0
- package/tests/effective_visibility_predicate.mjs +12 -0
- package/tests/fitness.mjs +19 -0
- package/tests/fixtures/seed-tasks/bongos-v1-idea-routing.json +256 -0
- package/tests/fixtures/seed-tasks/bv1-profiles.json +592 -0
- package/tests/fixtures/seed-tasks/bv2-ideator-surface.json +373 -0
- package/tests/fixtures/seed-tasks/fake-api.mjs +80 -0
- package/tests/github_one_trip.mjs +34 -0
- package/tests/github_repo_visibility.mjs +20 -0
- package/tests/goal_achievement.mjs +30 -1
- package/tests/goal_achievement_reward.mjs +205 -0
- package/tests/goal_sort_staleness.mjs +2 -1
- package/tests/goal_tier.mjs +11 -1
- package/tests/google_fonts_nonblocking.mjs +84 -0
- package/tests/google_sign_in.mjs +401 -0
- package/tests/government_board_expiry.mjs +94 -0
- package/tests/government_board_membership.mjs +4 -1
- package/tests/government_protected_surfaces.mjs +1 -1
- package/tests/government_routes.mjs +1 -1
- package/tests/government_seed.mjs +1 -0
- package/tests/hall_ai_studio.mjs +347 -0
- package/tests/hall_page_gate_map.mjs +3 -0
- package/tests/hall_studio_home.mjs +61 -2
- package/tests/home_attention_cards.mjs +1 -1
- package/tests/human_signal.mjs +141 -0
- package/tests/install_script_reader.mjs +51 -0
- package/tests/integration_fixture_ids.mjs +82 -0
- package/tests/invite_expiry_db.mjs +13 -1
- package/tests/lib_sh_resolution.mjs +0 -4
- package/tests/market_watch_data.mjs +244 -0
- package/tests/market_watch_data_db.mjs +308 -0
- package/tests/market_watch_module.mjs +114 -0
- package/tests/market_watch_run.mjs +503 -0
- package/tests/metrics.mjs +124 -0
- package/tests/migration_namespace.mjs +14 -0
- package/tests/module_api.mjs +2 -0
- package/tests/module_loader.mjs +1 -1
- package/tests/notes.mjs +182 -0
- package/tests/own_scope_guard.mjs +5 -0
- package/tests/page_tweak_marker_sql.mjs +76 -0
- package/tests/page_tweak_no_block.mjs +135 -0
- package/tests/page_tweak_notice.mjs +103 -0
- package/tests/payout_approvals.mjs +253 -0
- package/tests/payout_approvals_db.mjs +106 -0
- package/tests/payout_gates.mjs +322 -0
- package/tests/payout_gates_db.mjs +113 -0
- package/tests/planning_session_skill.mjs +13 -3
- package/tests/project_settings_page.mjs +29 -5
- package/tests/project_settings_spend_cap_route.mjs +235 -0
- package/tests/promotion_sweep.mjs +29 -1
- package/tests/provision.mjs +3 -2
- package/tests/provisioning_app_status.mjs +18 -0
- package/tests/provisioning_credential_preflight.mjs +53 -0
- package/tests/provisioning_env_manifest_edit_delete.mjs +223 -0
- package/tests/publish_reconciler_overlap.mjs +60 -0
- package/tests/rank_change_broadcast_port.mjs +151 -0
- package/tests/seed_tasks.mjs +176 -0
- package/tests/seed_verify_criteria.mjs +2 -6
- package/tests/site_classified_once.mjs +142 -0
- package/tests/speciality_db_shape.mjs +23 -0
- package/tests/speciality_session_skills.mjs +48 -2
- package/tests/strand_lease.mjs +249 -0
- package/tests/strand_watch.mjs +10 -0
- package/tests/task_criteria_routes.mjs +275 -0
- package/tests/task_criteria_unlink_db.mjs +123 -0
- package/tests/task_needs.mjs +233 -0
- package/tests/task_needs_db.mjs +110 -0
- package/tests/unit_runner_serial.mjs +266 -43
- package/tests/version_literals.mjs +5 -7
- package/tests/welcome_boot.mjs +16 -5
- package/tests/welcome_boot_browser.mjs +36 -4
- package/docs/recipes/bongos-cli-release.md +0 -66
- package/scripts/bongos/backfill-disciplines.js +0 -144
- package/scripts/bongos/backfill-session-earnings.js +0 -123
- package/scripts/bongos/backfill-session-types.js +0 -87
- package/scripts/bongos/build-bongos.js +0 -94
- package/scripts/bongos/cleanup-orphans.js +0 -74
- package/scripts/bongos/seed-bongos-v1-idea-routing-tasks.js +0 -152
- package/scripts/bongos/seed-bv1-profiles-tasks.js +0 -135
- package/scripts/bongos/seed-bv2-ideator-surface-tasks.js +0 -390
- package/scripts/bongos/smoke-batch-claim.sh +0 -238
- package/scripts/bongos/smoke-batch-release.sh +0 -316
- package/scripts/bongos/smoke-claim-consistency.sh +0 -222
- package/scripts/bongos/smoke-dependencies.sh +0 -143
- package/scripts/gds/backfill-disciplines.js +0 -7
- package/scripts/gds/backfill-session-earnings.js +0 -7
- package/scripts/gds/backfill-session-types.js +0 -7
- package/scripts/gds/cleanup-orphans.js +0 -7
- package/scripts/gds/seed-bongos-v1-idea-routing-tasks.js +0 -6
- package/scripts/gds/seed-bv1-profiles-tasks.js +0 -6
- package/scripts/gds/seed-bv2-ideator-surface-tasks.js +0 -6
- package/scripts/gds/smoke-batch-claim.sh +0 -8
- package/scripts/gds/smoke-batch-release.sh +0 -8
- package/scripts/gds/smoke-claim-consistency.sh +0 -8
- package/scripts/gds/smoke-dependencies.sh +0 -8
- package/tests/smoke_dependencies_witness.mjs +0 -46
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# GDS batch-release + dry-run-validate smoke test (task 1758).
|
|
3
|
-
#
|
|
4
|
-
# Exercises POST /api/bongos/claims/batch/release:
|
|
5
|
-
# Case A: 2 own active claims → 200, both in released[], both tasks 'ready'.
|
|
6
|
-
# Case B: 1 own active claim + 1 bogus claim id → 200 (NOT all-or-nothing —
|
|
7
|
-
# the batch has no cross-claim invariant), the good one released,
|
|
8
|
-
# the bad one enumerated in failures[] with CLAIM_NOT_FOUND.
|
|
9
|
-
#
|
|
10
|
-
# Exercises POST /api/bongos/claims/batch/validate:
|
|
11
|
-
# Case C: 2 ready tasks, disjoint touches → parallel_safe:true, both valid.
|
|
12
|
-
# Case D: 2 ready tasks, OVERLAPPING touches → parallel_safe:false, both
|
|
13
|
-
# marked invalid (BATCH_TOUCHES_CONFLICT) — and, since this is a
|
|
14
|
-
# dry run, neither task actually gets claimed (still 'ready' after).
|
|
15
|
-
# Case E: 1 ready + 1 already-active task → the active one is marked
|
|
16
|
-
# invalid (TASK_NOT_READY), the ready one stays valid.
|
|
17
|
-
#
|
|
18
|
-
# Creates synthetic '__smoke__' tasks that are filtered from the public surfaces.
|
|
19
|
-
# Cleans up by releasing/abandoning every claim it creates and marking tasks
|
|
20
|
-
# 'abandoned' so they don't linger.
|
|
21
|
-
#
|
|
22
|
-
# Usage: bash scripts/bongos/smoke-batch-release.sh
|
|
23
|
-
# Env: GDS_API_BASE / PMS_API_BASE override host (default: this instance's own,
|
|
24
|
-
# resolved from the session + branding pack — see lib.sh)
|
|
25
|
-
|
|
26
|
-
set -euo pipefail
|
|
27
|
-
|
|
28
|
-
# shellcheck source=scripts/bongos/lib.sh
|
|
29
|
-
source "$(dirname "$0")/lib.sh"
|
|
30
|
-
|
|
31
|
-
API="$(gds_api_base)"
|
|
32
|
-
TOKEN="$(gds_resolve_token)" || exit $?
|
|
33
|
-
|
|
34
|
-
# task 1003166 (G02): resolve the version at RUNTIME rather than naming one. A
|
|
35
|
-
# literal works until that version ships, then `version_closed` refuses every
|
|
36
|
-
# create and the smoke fails as if the code broke (idea 1000823).
|
|
37
|
-
VERSION_ID=$(node "$(dirname "$0")/version-select.js") || {
|
|
38
|
-
echo "FAIL: could not resolve a building version — see version-select.js" >&2
|
|
39
|
-
exit 1
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
ts=$(date +%Y%m%d-%H%M%S)
|
|
43
|
-
|
|
44
|
-
# Wrapper: METHOD PATH [BODY] → echoes "PAYLOAD\nHTTP_CODE". Never exits.
|
|
45
|
-
call() {
|
|
46
|
-
local method="$1" path="$2" body="${3:-}"
|
|
47
|
-
local args=(-sS -X "${method}" -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -w "\n%{http_code}")
|
|
48
|
-
if [[ -n "${body}" ]]; then args+=(-d "${body}"); fi
|
|
49
|
-
curl "${args[@]}" "${API}${path}"
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
parse_call() {
|
|
53
|
-
local out="$1"
|
|
54
|
-
CODE="${out##*$'\n'}"
|
|
55
|
-
PAYLOAD="${out%$'\n'*}"
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
mk_task() {
|
|
59
|
-
# mk_task <suffix> <touches-csv> → echoes new task id
|
|
60
|
-
local suffix="$1" touches_csv="$2"
|
|
61
|
-
local body
|
|
62
|
-
body=$(python3 -c "
|
|
63
|
-
import json,sys
|
|
64
|
-
t = '${touches_csv}'.split(',')
|
|
65
|
-
print(json.dumps({
|
|
66
|
-
'version_id': '${VERSION_ID}',
|
|
67
|
-
'title': '__smoke__ batch-release ${ts}-${suffix}',
|
|
68
|
-
'description': 'smoke',
|
|
69
|
-
'status': 'ready',
|
|
70
|
-
'touches': t,
|
|
71
|
-
'est_minutes': 1,
|
|
72
|
-
'manual_degree': 1,
|
|
73
|
-
'priority': 5,
|
|
74
|
-
'automation_tag': 'overnight-safe',
|
|
75
|
-
'credits_reward': 0,
|
|
76
|
-
'source': 'smoke',
|
|
77
|
-
'source_ref': '${ts}-${suffix}'
|
|
78
|
-
}))")
|
|
79
|
-
parse_call "$(call POST /api/bongos/tasks "${body}")"
|
|
80
|
-
python3 -c "import json,sys; print(json.loads('''${PAYLOAD}''')['task']['id'])"
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
claim_task() {
|
|
84
|
-
# claim_task <task_id> → echoes new claim id.
|
|
85
|
-
# Uses /claims/batch with bind_session:false (task 1795) rather than the
|
|
86
|
-
# plain single-claim path — this CLI token IS a real bound session, and the
|
|
87
|
-
# plain single-claim path caps a session to ONE active claim at a time
|
|
88
|
-
# (gateOneActiveClaimPerSession, task 1642). bind_session:false stores
|
|
89
|
-
# creator_session_id NULL instead of the caller's session, so this session
|
|
90
|
-
# can hold as many of these as it needs for fixture setup (NULL sessions are
|
|
91
|
-
# explicitly excluded from the uniq_active_claim_per_session index).
|
|
92
|
-
local tid="$1"
|
|
93
|
-
parse_call "$(call POST /api/bongos/claims/batch "{\"task_ids\":[${tid}],\"bind_session\":false}")"
|
|
94
|
-
python3 -c "import json,sys; print(json.loads('''${PAYLOAD}''')['claims'][0]['id'])"
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
# Track created tasks + claims for cleanup. Claims released in Case A/B are
|
|
98
|
-
# dropped from CREATED_CLAIMS as they resolve so cleanup doesn't double-resolve.
|
|
99
|
-
CREATED_TASKS=()
|
|
100
|
-
CREATED_CLAIMS=()
|
|
101
|
-
cleanup() {
|
|
102
|
-
local leaked=()
|
|
103
|
-
echo
|
|
104
|
-
echo "--- cleanup ---"
|
|
105
|
-
for cid in "${CREATED_CLAIMS[@]:-}"; do
|
|
106
|
-
[[ -z "${cid}" ]] && continue
|
|
107
|
-
call POST "/api/bongos/claims/${cid}/resolve" \
|
|
108
|
-
'{"outcome":"abandoned","notes_md":"smoke cleanup"}' >/dev/null || true
|
|
109
|
-
done
|
|
110
|
-
for tid in "${CREATED_TASKS[@]:-}"; do
|
|
111
|
-
[[ -z "${tid}" ]] && continue
|
|
112
|
-
# task 1002856: same bug as smoke-batch-claim.sh — /tasks/:id/promote is the
|
|
113
|
-
# backlog->ready transition and ignores a status field, so this never
|
|
114
|
-
# abandoned anything and the redirect swallowed the failure.
|
|
115
|
-
if ! call POST "/api/bongos/tasks/${tid}/abandon" \
|
|
116
|
-
'{"reason":"smoke cleanup (scripts/bongos/smoke-batch-release.sh)"}' >/dev/null 2>&1; then
|
|
117
|
-
leaked+=("${tid}")
|
|
118
|
-
fi
|
|
119
|
-
done
|
|
120
|
-
if [[ ${#leaked[@]} -gt 0 ]]; then
|
|
121
|
-
echo "WARN: could not abandon ${#leaked[@]} smoke task(s): ${leaked[*]}"
|
|
122
|
-
echo "WARN: clear them with: node scripts/bongos/api.js POST /tasks/<id>/abandon --body '{\"reason\":\"smoke residue\"}'"
|
|
123
|
-
fi
|
|
124
|
-
echo "cleanup done"
|
|
125
|
-
}
|
|
126
|
-
trap cleanup EXIT
|
|
127
|
-
|
|
128
|
-
fail=0
|
|
129
|
-
ok() { echo "PASS $*"; }
|
|
130
|
-
bad() { echo "FAIL $*"; fail=1; }
|
|
131
|
-
|
|
132
|
-
echo "=== GDS batch-release + validate smoke ==="
|
|
133
|
-
echo "API: ${API}"
|
|
134
|
-
echo
|
|
135
|
-
|
|
136
|
-
# ---- Case A: 2 own active claims → 200, both released ------------------
|
|
137
|
-
# Each id is registered for cleanup IMMEDIATELY after it's created/claimed
|
|
138
|
-
# (not batched after both calls) — so if the second call in a pair fails,
|
|
139
|
-
# the first one's already-registered and still gets cleaned up on exit.
|
|
140
|
-
echo "--- A: release 2 own claims (expect 200, both released) ---"
|
|
141
|
-
TA1=$(mk_task A1 "__smoke__/batch-release/${ts}/a1"); CREATED_TASKS+=("${TA1}")
|
|
142
|
-
TA2=$(mk_task A2 "__smoke__/batch-release/${ts}/a2"); CREATED_TASKS+=("${TA2}")
|
|
143
|
-
CA1=$(claim_task "${TA1}"); CREATED_CLAIMS+=("${CA1}")
|
|
144
|
-
CA2=$(claim_task "${TA2}"); CREATED_CLAIMS+=("${CA2}")
|
|
145
|
-
echo " claimed #${TA1}→claim ${CA1}, #${TA2}→claim ${CA2}"
|
|
146
|
-
|
|
147
|
-
BODY_A=$(python3 -c "import json; print(json.dumps({'claim_ids':[${CA1},${CA2}]}))")
|
|
148
|
-
parse_call "$(call POST /api/bongos/claims/batch/release "${BODY_A}")"
|
|
149
|
-
if [[ "${CODE}" == "200" ]]; then
|
|
150
|
-
N=$(python3 -c "import json,sys; print(len(json.loads('''${PAYLOAD}''')['released']))")
|
|
151
|
-
NF=$(python3 -c "import json,sys; print(len(json.loads('''${PAYLOAD}''')['failures']))")
|
|
152
|
-
if [[ "${N}" == "2" && "${NF}" == "0" ]]; then
|
|
153
|
-
ok "A: 200 with 2 released, 0 failures"
|
|
154
|
-
CREATED_CLAIMS=("${CREATED_CLAIMS[@]/${CA1}/}" ); CREATED_CLAIMS=("${CREATED_CLAIMS[@]/${CA2}/}")
|
|
155
|
-
else
|
|
156
|
-
bad "A: expected 2 released/0 failures, got ${N}/${NF} → ${PAYLOAD}"
|
|
157
|
-
fi
|
|
158
|
-
else
|
|
159
|
-
bad "A: expected 200, got ${CODE} → ${PAYLOAD}"
|
|
160
|
-
fi
|
|
161
|
-
for tid in "${TA1}" "${TA2}"; do
|
|
162
|
-
parse_call "$(call GET "/api/bongos/tasks/${tid}")"
|
|
163
|
-
S=$(python3 -c "import json,sys; print(json.loads('''${PAYLOAD}''')['task']['status'])")
|
|
164
|
-
if [[ "${S}" == "ready" ]]; then
|
|
165
|
-
ok "A: task #${tid} back to 'ready'"
|
|
166
|
-
else
|
|
167
|
-
bad "A: task #${tid} status = ${S} (expected ready)"
|
|
168
|
-
fi
|
|
169
|
-
done
|
|
170
|
-
|
|
171
|
-
# ---- Case B: 1 own claim + 1 bogus id → 200, partial success -----------
|
|
172
|
-
echo
|
|
173
|
-
echo "--- B: 1 own claim + 1 bogus claim id (expect 200, partial) ---"
|
|
174
|
-
TB1=$(mk_task B1 "__smoke__/batch-release/${ts}/b1")
|
|
175
|
-
CREATED_TASKS+=("${TB1}")
|
|
176
|
-
CB1=$(claim_task "${TB1}")
|
|
177
|
-
CREATED_CLAIMS+=("${CB1}")
|
|
178
|
-
BOGUS_CLAIM_ID=999999999
|
|
179
|
-
echo " claimed #${TB1}→claim ${CB1}; bogus id ${BOGUS_CLAIM_ID}"
|
|
180
|
-
|
|
181
|
-
BODY_B=$(python3 -c "import json; print(json.dumps({'claim_ids':[${CB1},${BOGUS_CLAIM_ID}]}))")
|
|
182
|
-
parse_call "$(call POST /api/bongos/claims/batch/release "${BODY_B}")"
|
|
183
|
-
if [[ "${CODE}" == "200" ]]; then
|
|
184
|
-
RELEASED_IDS=$(python3 -c "
|
|
185
|
-
import json,sys
|
|
186
|
-
d = json.loads('''${PAYLOAD}''')
|
|
187
|
-
print(','.join(str(r['claim_id']) for r in d['released']))
|
|
188
|
-
")
|
|
189
|
-
FAIL_REASONS=$(python3 -c "
|
|
190
|
-
import json,sys
|
|
191
|
-
d = json.loads('''${PAYLOAD}''')
|
|
192
|
-
fs = d['failures']
|
|
193
|
-
print(','.join(f\"{f['claim_id']}:{f['reason']}\" for f in fs))
|
|
194
|
-
")
|
|
195
|
-
if [[ "${RELEASED_IDS}" == *"${CB1}"* ]]; then
|
|
196
|
-
ok "B: good claim #${CB1} released (released: ${RELEASED_IDS})"
|
|
197
|
-
CREATED_CLAIMS=("${CREATED_CLAIMS[@]/${CB1}/}")
|
|
198
|
-
else
|
|
199
|
-
bad "B: good claim #${CB1} NOT released (released: ${RELEASED_IDS})"
|
|
200
|
-
fi
|
|
201
|
-
if [[ "${FAIL_REASONS}" == *"${BOGUS_CLAIM_ID}:CLAIM_NOT_FOUND"* ]]; then
|
|
202
|
-
ok "B: bogus id enumerated as CLAIM_NOT_FOUND (failures: ${FAIL_REASONS})"
|
|
203
|
-
else
|
|
204
|
-
bad "B: bogus id not enumerated as CLAIM_NOT_FOUND (failures: ${FAIL_REASONS})"
|
|
205
|
-
fi
|
|
206
|
-
else
|
|
207
|
-
bad "B: expected 200, got ${CODE} → ${PAYLOAD}"
|
|
208
|
-
fi
|
|
209
|
-
|
|
210
|
-
# ---- Case C: validate, disjoint touches → parallel_safe:true -----------
|
|
211
|
-
echo
|
|
212
|
-
echo "--- C: validate 2 ready disjoint-touches tasks (expect parallel_safe:true) ---"
|
|
213
|
-
TC1=$(mk_task C1 "__smoke__/batch-release/${ts}/c1"); CREATED_TASKS+=("${TC1}")
|
|
214
|
-
TC2=$(mk_task C2 "__smoke__/batch-release/${ts}/c2"); CREATED_TASKS+=("${TC2}")
|
|
215
|
-
|
|
216
|
-
BODY_C=$(python3 -c "import json; print(json.dumps({'task_ids':[${TC1},${TC2}]}))")
|
|
217
|
-
parse_call "$(call POST /api/bongos/claims/batch/validate "${BODY_C}")"
|
|
218
|
-
if [[ "${CODE}" == "200" ]]; then
|
|
219
|
-
PS=$(python3 -c "import json,sys; print(json.loads('''${PAYLOAD}''')['parallel_safe'])")
|
|
220
|
-
if [[ "${PS}" == "True" ]]; then
|
|
221
|
-
ok "C: parallel_safe:true for disjoint touches"
|
|
222
|
-
else
|
|
223
|
-
bad "C: expected parallel_safe:true, got ${PS} → ${PAYLOAD}"
|
|
224
|
-
fi
|
|
225
|
-
else
|
|
226
|
-
bad "C: expected 200, got ${CODE} → ${PAYLOAD}"
|
|
227
|
-
fi
|
|
228
|
-
# Dry run — confirm NOTHING got claimed.
|
|
229
|
-
for tid in "${TC1}" "${TC2}"; do
|
|
230
|
-
parse_call "$(call GET "/api/bongos/tasks/${tid}")"
|
|
231
|
-
S=$(python3 -c "import json,sys; print(json.loads('''${PAYLOAD}''')['task']['status'])")
|
|
232
|
-
if [[ "${S}" == "ready" ]]; then
|
|
233
|
-
ok "C: task #${tid} still 'ready' (validate did not claim)"
|
|
234
|
-
else
|
|
235
|
-
bad "C: task #${tid} status = ${S} (validate must never claim)"
|
|
236
|
-
fi
|
|
237
|
-
done
|
|
238
|
-
|
|
239
|
-
# ---- Case D: validate, overlapping touches → parallel_safe:false -------
|
|
240
|
-
echo
|
|
241
|
-
echo "--- D: validate 2 ready overlapping-touches tasks (expect parallel_safe:false) ---"
|
|
242
|
-
TD1=$(mk_task D1 "__smoke__/batch-release/${ts}/shared"); CREATED_TASKS+=("${TD1}")
|
|
243
|
-
TD2=$(mk_task D2 "__smoke__/batch-release/${ts}/shared"); CREATED_TASKS+=("${TD2}")
|
|
244
|
-
echo " created tasks ${TD1}, ${TD2} (both touch __smoke__/batch-release/${ts}/shared)"
|
|
245
|
-
|
|
246
|
-
BODY_D=$(python3 -c "import json; print(json.dumps({'task_ids':[${TD1},${TD2}]}))")
|
|
247
|
-
parse_call "$(call POST /api/bongos/claims/batch/validate "${BODY_D}")"
|
|
248
|
-
if [[ "${CODE}" == "200" ]]; then
|
|
249
|
-
PS=$(python3 -c "import json,sys; print(json.loads('''${PAYLOAD}''')['parallel_safe'])")
|
|
250
|
-
REASONS=$(python3 -c "
|
|
251
|
-
import json,sys
|
|
252
|
-
d = json.loads('''${PAYLOAD}''')
|
|
253
|
-
rs = set()
|
|
254
|
-
for r in d['results']:
|
|
255
|
-
for reason in r['reasons']:
|
|
256
|
-
rs.add(reason['reason'])
|
|
257
|
-
print(','.join(sorted(rs)))
|
|
258
|
-
")
|
|
259
|
-
if [[ "${PS}" == "False" && "${REASONS}" == *"BATCH_TOUCHES_CONFLICT"* ]]; then
|
|
260
|
-
ok "D: parallel_safe:false with BATCH_TOUCHES_CONFLICT (reasons: ${REASONS})"
|
|
261
|
-
else
|
|
262
|
-
bad "D: expected parallel_safe:false + BATCH_TOUCHES_CONFLICT, got ${PS}/${REASONS} → ${PAYLOAD}"
|
|
263
|
-
fi
|
|
264
|
-
else
|
|
265
|
-
bad "D: expected 200, got ${CODE} → ${PAYLOAD}"
|
|
266
|
-
fi
|
|
267
|
-
for tid in "${TD1}" "${TD2}"; do
|
|
268
|
-
parse_call "$(call GET "/api/bongos/tasks/${tid}")"
|
|
269
|
-
S=$(python3 -c "import json,sys; print(json.loads('''${PAYLOAD}''')['task']['status'])")
|
|
270
|
-
if [[ "${S}" == "ready" ]]; then
|
|
271
|
-
ok "D: task #${tid} still 'ready' (validate did not claim)"
|
|
272
|
-
else
|
|
273
|
-
bad "D: task #${tid} status = ${S} (validate must never claim)"
|
|
274
|
-
fi
|
|
275
|
-
done
|
|
276
|
-
|
|
277
|
-
# ---- Case E: validate, 1 ready + 1 already-active → the active one invalid
|
|
278
|
-
echo
|
|
279
|
-
echo "--- E: validate 1 ready + 1 already-active (expect the active one invalid) ---"
|
|
280
|
-
TE1=$(mk_task E1 "__smoke__/batch-release/${ts}/e1"); CREATED_TASKS+=("${TE1}")
|
|
281
|
-
TE2=$(mk_task E2 "__smoke__/batch-release/${ts}/e2"); CREATED_TASKS+=("${TE2}")
|
|
282
|
-
CE1=$(claim_task "${TE1}"); CREATED_CLAIMS+=("${CE1}")
|
|
283
|
-
echo " #${TE1} pre-claimed (claim ${CE1}, now 'active'); #${TE2} stays 'ready'"
|
|
284
|
-
|
|
285
|
-
BODY_E=$(python3 -c "import json; print(json.dumps({'task_ids':[${TE1},${TE2}]}))")
|
|
286
|
-
parse_call "$(call POST /api/bongos/claims/batch/validate "${BODY_E}")"
|
|
287
|
-
if [[ "${CODE}" == "200" ]]; then
|
|
288
|
-
VALID_E1=$(python3 -c "
|
|
289
|
-
import json,sys
|
|
290
|
-
d = json.loads('''${PAYLOAD}''')
|
|
291
|
-
for r in d['results']:
|
|
292
|
-
if r['task_id'] == ${TE1}: print(r['valid'])
|
|
293
|
-
")
|
|
294
|
-
VALID_E2=$(python3 -c "
|
|
295
|
-
import json,sys
|
|
296
|
-
d = json.loads('''${PAYLOAD}''')
|
|
297
|
-
for r in d['results']:
|
|
298
|
-
if r['task_id'] == ${TE2}: print(r['valid'])
|
|
299
|
-
")
|
|
300
|
-
if [[ "${VALID_E1}" == "False" && "${VALID_E2}" == "True" ]]; then
|
|
301
|
-
ok "E: active task #${TE1} invalid, ready task #${TE2} valid"
|
|
302
|
-
else
|
|
303
|
-
bad "E: expected #${TE1}=invalid/#${TE2}=valid, got ${VALID_E1}/${VALID_E2} → ${PAYLOAD}"
|
|
304
|
-
fi
|
|
305
|
-
else
|
|
306
|
-
bad "E: expected 200, got ${CODE} → ${PAYLOAD}"
|
|
307
|
-
fi
|
|
308
|
-
|
|
309
|
-
echo
|
|
310
|
-
echo "--- summary ---"
|
|
311
|
-
if [[ "${fail}" -eq 0 ]]; then
|
|
312
|
-
echo "OK: batch-release + validate smoke passed"
|
|
313
|
-
else
|
|
314
|
-
echo "FAIL: one or more checks failed"
|
|
315
|
-
fi
|
|
316
|
-
exit "${fail}"
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# GDS claim-consistency smoke test (production). Renamed from PMS in V3.R01.
|
|
3
|
-
#
|
|
4
|
-
# Enforces criterion 7 of pms-v2.md: every surface that lists "your active
|
|
5
|
-
# claims" must read from the canonical helper (src/bongos/active-claims.js)
|
|
6
|
-
# and therefore return identical claim sets in identical order.
|
|
7
|
-
#
|
|
8
|
-
# Strategy:
|
|
9
|
-
# 1. Create 2 disjoint __smoke__ tasks
|
|
10
|
-
# 2. Claim both as the same builder
|
|
11
|
-
# 3. Hit every consumer surface that currently exists:
|
|
12
|
-
# - GET /api/bongos/me (always present)
|
|
13
|
-
# - GET /api/bongos/builders/me (PMS-V2 P6) (capability-gated)
|
|
14
|
-
# The /builder-start and /builder-session CLIs render server data;
|
|
15
|
-
# they do not constitute independent surfaces in the sense of
|
|
16
|
-
# criterion 7 (they consume /api/bongos/* responses). We assert at the
|
|
17
|
-
# API boundary, which is where the bug class lives.
|
|
18
|
-
# 4. Extract the ordered (task_id) sequence from each surface
|
|
19
|
-
# 5. Assert all surfaces return identical sequences
|
|
20
|
-
# 6. Release both claims, surfaces are cleaned up by the task lifecycle
|
|
21
|
-
#
|
|
22
|
-
# Surfaces that 404 are AUTO-SKIPPED so the smoke test passes against
|
|
23
|
-
# current production even before PMS-V2 P6 lands. A summary line records
|
|
24
|
-
# which surfaces were checked vs skipped.
|
|
25
|
-
#
|
|
26
|
-
# TODO: once PMS-V2 P6 (#48 — /builders web profile) ships, the
|
|
27
|
-
# /api/bongos/builders/me surface will start returning 200 and this smoke
|
|
28
|
-
# will automatically include it. No edits needed here.
|
|
29
|
-
#
|
|
30
|
-
# Usage:
|
|
31
|
-
# bash scripts/bongos/smoke-claim-consistency.sh
|
|
32
|
-
# Optional env:
|
|
33
|
-
# GDS_API_BASE / PMS_API_BASE override the API host (default: this instance's own,
|
|
34
|
-
# resolved from the session + branding pack — see lib.sh)
|
|
35
|
-
|
|
36
|
-
set -euo pipefail
|
|
37
|
-
|
|
38
|
-
# shellcheck source=scripts/bongos/lib.sh
|
|
39
|
-
source "$(dirname "$0")/lib.sh"
|
|
40
|
-
|
|
41
|
-
API="$(gds_api_base)"
|
|
42
|
-
TOKEN="$(gds_resolve_token)" || exit $?
|
|
43
|
-
|
|
44
|
-
ts=$(date +%Y%m%d-%H%M%S)
|
|
45
|
-
SMOKE_TITLE_A="__smoke__ claim-consistency-A ${ts}"
|
|
46
|
-
SMOKE_TITLE_B="__smoke__ claim-consistency-B ${ts}"
|
|
47
|
-
|
|
48
|
-
call() {
|
|
49
|
-
local method="$1" path="$2" body="${3:-}"
|
|
50
|
-
local args=(-sS -X "${method}" -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -w "\n%{http_code}")
|
|
51
|
-
if [[ -n "${body}" ]]; then args+=(-d "${body}"); fi
|
|
52
|
-
local out
|
|
53
|
-
out=$(curl "${args[@]}" "${API}${path}")
|
|
54
|
-
local code="${out##*$'\n'}"
|
|
55
|
-
local payload="${out%$'\n'*}"
|
|
56
|
-
echo "${payload}"
|
|
57
|
-
if [[ "${code}" -ge 300 ]]; then
|
|
58
|
-
echo "FAIL: ${method} ${path} -> HTTP ${code}" >&2
|
|
59
|
-
return 1
|
|
60
|
-
fi
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
# Returns the HTTP status code for a GET to PATH. Used for capability gating.
|
|
64
|
-
probe_status() {
|
|
65
|
-
local path="$1"
|
|
66
|
-
curl -sS -o /dev/null -w "%{http_code}" \
|
|
67
|
-
-H "Authorization: Bearer ${TOKEN}" \
|
|
68
|
-
"${API}${path}"
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
# Extract sorted task_id list from a JSON payload at a given JSON path.
|
|
72
|
-
# Args: <payload> <python-extract-expr-returning-list-of-ints>
|
|
73
|
-
extract_ids() {
|
|
74
|
-
local payload="$1" expr="$2"
|
|
75
|
-
echo "${payload}" | python3 -c "
|
|
76
|
-
import json, sys
|
|
77
|
-
data = json.load(sys.stdin)
|
|
78
|
-
ids = ${expr}
|
|
79
|
-
print(','.join(str(x) for x in ids))
|
|
80
|
-
"
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
create_task() {
|
|
84
|
-
local title="$1" suffix="$2"
|
|
85
|
-
local body
|
|
86
|
-
body=$(python3 -c "
|
|
87
|
-
import json
|
|
88
|
-
print(json.dumps({
|
|
89
|
-
'version_id': '${VERSION_ID}',
|
|
90
|
-
'title': '${title}',
|
|
91
|
-
'description': 'Synthetic smoke task. Auto-cleaned by smoke-claim-consistency.sh.',
|
|
92
|
-
'status': 'ready',
|
|
93
|
-
'touches': ['__smoke__/claim-consistency/${ts}/${suffix}'],
|
|
94
|
-
'est_minutes': 1,
|
|
95
|
-
'manual_degree': 1,
|
|
96
|
-
'priority': 5,
|
|
97
|
-
'automation_tag': 'overnight-safe',
|
|
98
|
-
'credits_reward': 0,
|
|
99
|
-
'source': 'smoke',
|
|
100
|
-
'source_ref': 'consistency-${ts}-${suffix}'
|
|
101
|
-
}))
|
|
102
|
-
")
|
|
103
|
-
local out
|
|
104
|
-
out=$(call POST /api/bongos/tasks "${body}")
|
|
105
|
-
echo "${out}" | python3 -c "import json,sys; print(json.load(sys.stdin)['task']['id'])"
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
claim_task() {
|
|
109
|
-
local task_id="$1"
|
|
110
|
-
local body
|
|
111
|
-
body=$(python3 -c "import json; print(json.dumps({'task_id': ${task_id}, 'worktree_name': '__smoke__'}))")
|
|
112
|
-
local out
|
|
113
|
-
out=$(call POST /api/bongos/claims "${body}")
|
|
114
|
-
echo "${out}" | python3 -c "import json,sys; print(json.load(sys.stdin)['claim']['id'])"
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
release_claim() {
|
|
118
|
-
local claim_id="$1"
|
|
119
|
-
call POST "/api/bongos/claims/${claim_id}/resolve" '{"outcome":"abandoned","notes_md":"smoke cleanup"}' >/dev/null || true
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
echo "=== GDS claim-consistency smoke test ==="
|
|
123
|
-
echo "API: ${API}"
|
|
124
|
-
echo "Titles: ${SMOKE_TITLE_A} | ${SMOKE_TITLE_B}"
|
|
125
|
-
echo
|
|
126
|
-
|
|
127
|
-
# task 1003166 (G02): resolve the version at RUNTIME. This file used to hardcode
|
|
128
|
-
# one; that version shipped, `version_closed` refused every create, and the smoke
|
|
129
|
-
# could not pass while /merge-mode still advertised it green (idea 1000823).
|
|
130
|
-
VERSION_ID=$(node "$(dirname "$0")/version-select.js") || {
|
|
131
|
-
echo "FAIL: could not resolve a building version — see version-select.js" >&2
|
|
132
|
-
exit 1
|
|
133
|
-
}
|
|
134
|
-
echo "Version: ${VERSION_ID}"
|
|
135
|
-
|
|
136
|
-
echo "--- 1. create 2 smoke tasks ---"
|
|
137
|
-
TASK_A=$(create_task "${SMOKE_TITLE_A}" "A")
|
|
138
|
-
TASK_B=$(create_task "${SMOKE_TITLE_B}" "B")
|
|
139
|
-
echo "task A=#${TASK_A} task B=#${TASK_B}"
|
|
140
|
-
|
|
141
|
-
# Always clean up on exit, even if assertions fail.
|
|
142
|
-
CLAIM_A=""
|
|
143
|
-
CLAIM_B=""
|
|
144
|
-
cleanup() {
|
|
145
|
-
local rc=$?
|
|
146
|
-
echo
|
|
147
|
-
echo "--- cleanup ---"
|
|
148
|
-
[[ -n "${CLAIM_A}" ]] && release_claim "${CLAIM_A}" && echo "released claim ${CLAIM_A}"
|
|
149
|
-
[[ -n "${CLAIM_B}" ]] && release_claim "${CLAIM_B}" && echo "released claim ${CLAIM_B}"
|
|
150
|
-
exit "${rc}"
|
|
151
|
-
}
|
|
152
|
-
trap cleanup EXIT
|
|
153
|
-
|
|
154
|
-
echo
|
|
155
|
-
echo "--- 2. claim both as same builder (A first, then B) ---"
|
|
156
|
-
CLAIM_A=$(claim_task "${TASK_A}")
|
|
157
|
-
# Tiny pause so claimed_at differs and ordering is unambiguous.
|
|
158
|
-
sleep 1
|
|
159
|
-
CLAIM_B=$(claim_task "${TASK_B}")
|
|
160
|
-
echo "claim A=#${CLAIM_A} claim B=#${CLAIM_B}"
|
|
161
|
-
|
|
162
|
-
EXPECTED="${TASK_A},${TASK_B}"
|
|
163
|
-
echo "expected ordered task_ids: ${EXPECTED}"
|
|
164
|
-
|
|
165
|
-
echo
|
|
166
|
-
echo "--- 3. probe each surface, extract ordered task_id sequence ---"
|
|
167
|
-
checked=0
|
|
168
|
-
skipped=0
|
|
169
|
-
fail=0
|
|
170
|
-
|
|
171
|
-
# Surface 1: /api/bongos/me — always present.
|
|
172
|
-
ME_PAYLOAD=$(call GET /api/bongos/me)
|
|
173
|
-
ME_IDS=$(extract_ids "${ME_PAYLOAD}" "[c['task_id'] for c in data.get('active_claims', [])]")
|
|
174
|
-
# Filter to just our 2 smoke task_ids in case the builder has other live claims.
|
|
175
|
-
ME_FILTERED=$(python3 -c "
|
|
176
|
-
ids = '${ME_IDS}'.split(',') if '${ME_IDS}' else []
|
|
177
|
-
keep = [x for x in ids if x in ('${TASK_A}', '${TASK_B}')]
|
|
178
|
-
print(','.join(keep))
|
|
179
|
-
")
|
|
180
|
-
echo "/api/bongos/me -> ${ME_FILTERED}"
|
|
181
|
-
if [[ "${ME_FILTERED}" == "${EXPECTED}" ]]; then
|
|
182
|
-
echo " PASS /api/bongos/me ordering matches"
|
|
183
|
-
checked=$((checked+1))
|
|
184
|
-
else
|
|
185
|
-
echo " FAIL /api/bongos/me ordering mismatch (expected ${EXPECTED}, got ${ME_FILTERED})"
|
|
186
|
-
fail=1
|
|
187
|
-
fi
|
|
188
|
-
|
|
189
|
-
# Surface 2: /api/bongos/builders/me — PMS-V2 P6, capability-gated.
|
|
190
|
-
BUILDERS_ME_CODE=$(probe_status /api/bongos/builders/me)
|
|
191
|
-
if [[ "${BUILDERS_ME_CODE}" == "200" ]]; then
|
|
192
|
-
BME_PAYLOAD=$(call GET /api/bongos/builders/me)
|
|
193
|
-
# Try both common shapes: top-level active_claims, or nested under builder/profile.
|
|
194
|
-
BME_IDS=$(extract_ids "${BME_PAYLOAD}" "[c['task_id'] for c in (data.get('active_claims') or data.get('builder', {}).get('active_claims') or data.get('profile', {}).get('active_claims') or [])]")
|
|
195
|
-
BME_FILTERED=$(python3 -c "
|
|
196
|
-
ids = '${BME_IDS}'.split(',') if '${BME_IDS}' else []
|
|
197
|
-
keep = [x for x in ids if x in ('${TASK_A}', '${TASK_B}')]
|
|
198
|
-
print(','.join(keep))
|
|
199
|
-
")
|
|
200
|
-
echo "/api/bongos/builders/me -> ${BME_FILTERED}"
|
|
201
|
-
if [[ "${BME_FILTERED}" == "${EXPECTED}" ]]; then
|
|
202
|
-
echo " PASS /api/bongos/builders/me ordering matches /api/bongos/me"
|
|
203
|
-
checked=$((checked+1))
|
|
204
|
-
else
|
|
205
|
-
echo " FAIL /api/bongos/builders/me ordering mismatch (expected ${EXPECTED}, got ${BME_FILTERED})"
|
|
206
|
-
fail=1
|
|
207
|
-
fi
|
|
208
|
-
else
|
|
209
|
-
echo "/api/bongos/builders/me -> HTTP ${BUILDERS_ME_CODE} (SKIP — PMS-V2 P6 not live yet)"
|
|
210
|
-
skipped=$((skipped+1))
|
|
211
|
-
fi
|
|
212
|
-
|
|
213
|
-
echo
|
|
214
|
-
echo "--- summary ---"
|
|
215
|
-
echo "surfaces checked: ${checked}"
|
|
216
|
-
echo "surfaces skipped: ${skipped}"
|
|
217
|
-
if [[ "${fail}" -eq 0 ]]; then
|
|
218
|
-
echo "OK: claim-consistency smoke passed (task A=#${TASK_A}, task B=#${TASK_B})"
|
|
219
|
-
else
|
|
220
|
-
echo "FAIL: one or more surfaces disagreed on active-claims ordering"
|
|
221
|
-
fi
|
|
222
|
-
exit "${fail}"
|