@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,411 @@
|
|
|
1
|
+
---
|
|
2
|
+
scope: art *pipeline* (code, design system, review loops) — the tooling builders use to make tiles, plus the tile PNGs it produces that ship into `public/assets/tiles/`.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Pixel-art generation pipeline — recipes and gotchas
|
|
6
|
+
|
|
7
|
+
**TL;DR**: AI image models will NOT produce true 32×32 pixel art on demand. The pipeline survives this by post-processing every output (median-downsample → palette quantize → snap) and by falling back to procedural Python when the AI repeatedly misses the subject. Self-review via Gemini 2.5 Flash vision against a structured rubric is what makes the loop autonomous.
|
|
8
|
+
|
|
9
|
+
## Critical recipes
|
|
10
|
+
|
|
11
|
+
### Generating a 32×32 tile from Nano Banana / Imagen
|
|
12
|
+
|
|
13
|
+
Both models output ~1024×1024. We don't ask for 32×32 directly — they ignore that constraint. Instead we:
|
|
14
|
+
|
|
15
|
+
1. **Ask for "32×32 logical pixels rendered at 1024×1024"** in the prompt — i.e., each "logical pixel" should appear as a clear ~32-pixel block in the output.
|
|
16
|
+
2. **Center-crop to a square** (Imagen sometimes pads).
|
|
17
|
+
3. **Median-downsample by block** (32×32 blocks → one output pixel per block via `np.median`). NOT nearest-neighbor — too noisy. NOT bilinear — introduces AA.
|
|
18
|
+
4. **Palette-quantize** every pixel to the nearest of the 64 colors in `modules/art-pipeline/template/palette.json`.
|
|
19
|
+
|
|
20
|
+
Code: `modules/art-pipeline/pipeline/post_process.py:process()`.
|
|
21
|
+
|
|
22
|
+
### When the AI refuses to produce the right subject
|
|
23
|
+
|
|
24
|
+
Empirically, Nano Banana frequently generates **sand-colored textures even when prompted explicitly for grass**. Multiple retries with stronger prompts didn't help. Imagen 4 had similar failure modes but on different subjects.
|
|
25
|
+
|
|
26
|
+
**The fix that worked**: a **Tier 5 procedural fallback** in `procedural_fallback.py`. For each common ground-tile id, we have a hand-coded Python generator that scatters palette colors at controlled density. Always palette-correct, always 32×32, always tileable. Score reliably ≥9 on objective criteria.
|
|
27
|
+
|
|
28
|
+
The orchestrator escalates to T5 only after T1–T4 fail twice each. So we burn AI cost first (looks more authentic when it works), and fall back to procedural only when stuck.
|
|
29
|
+
|
|
30
|
+
### Python TLS on macOS Python.org installer
|
|
31
|
+
|
|
32
|
+
Default Python from python.org doesn't trust system CAs. `urllib.request` against Google APIs throws `CERTIFICATE_VERIFY_FAILED`. Fix: install certifi (`pip install --user certifi`) and pass an SSL context built from `certifi.where()`. See top of `gen_api.py` and `review.py`. **Windows:** native Windows Python usually trusts the system CA store, so this often isn't needed; if it is, run `py -m pip install certifi` (`python3`/`--user` semantics differ on Windows).
|
|
33
|
+
|
|
34
|
+
### Output buffering during long runs
|
|
35
|
+
|
|
36
|
+
Python's `print()` is line-buffered when stdout is a TTY but fully buffered otherwise. Long-running orchestrator runs show no live output unless launched with `python3 -u …` or `PYTHONUNBUFFERED=1`. Per-attempt state IS persisted to `modules/art-pipeline/iterations/<tile>/log.jsonl` regardless, so progress is observable even without live stdout. (**Windows:** `python3` is usually `py`/`python`; the `PYTHONUNBUFFERED=1 python3 …` inline-env form is bash-only — set it separately first: `set PYTHONUNBUFFERED=1` in cmd / `$env:PYTHONUNBUFFERED=1` in PowerShell, or just use `py -u …`.)
|
|
37
|
+
|
|
38
|
+
## Structural insights
|
|
39
|
+
|
|
40
|
+
### The reference clusters carry the style
|
|
41
|
+
|
|
42
|
+
Slicing the 24 Pokemon FireRed reference maps on a 16×16 grid yields ~8,800 unique tiles. K-means on RGB histograms collapses them into 64 visual clusters. The **cluster overview sheet** (`modules/art-pipeline/template/cluster_overview.png`, 8×8 grid of representative tiles) is what we pass to the AI reviewer as the "what FireRed looks like" reference. It carries more style information than any prose description.
|
|
43
|
+
|
|
44
|
+
Each vocab item in `vocabulary.json` lists `ref_clusters` — the cluster ids most relevant to that tile (e.g. grass tiles reference c19, c04, c21). Tier 2 generation passes representative tiles from those clusters as image-conditioning, which improves style match.
|
|
45
|
+
|
|
46
|
+
### The locked palette is non-negotiable
|
|
47
|
+
|
|
48
|
+
64 colors extracted from the Pokemon reference corpus via weighted k-means. **Every output pixel must snap to one of these colors.** This guarantees:
|
|
49
|
+
- Coherent visual world (no two tiles fight each other).
|
|
50
|
+
- AA-free outputs (palette is small enough that quantization snaps blurry edges hard).
|
|
51
|
+
- Diff-able tile evolution: if a tile changes, the change is in pixel choices, not subtle color drift.
|
|
52
|
+
|
|
53
|
+
If we ever want to expand the palette (e.g. add cooler marble tones), it's an ADR-worthy decision and a one-line update to `palette.json` — but every existing tile needs re-quantizing.
|
|
54
|
+
|
|
55
|
+
### The rubric is the memory
|
|
56
|
+
|
|
57
|
+
Lars feedback ("trees too modern, more gnarled") becomes a rule appended to `style_guide.md`. The rule influences every subsequent generation because the reviewer reads the style guide on every call. **The system improves over time without manual prompt-engineering** — feedback is durable, not conversational.
|
|
58
|
+
|
|
59
|
+
## What does NOT work (do not waste time on these)
|
|
60
|
+
|
|
61
|
+
- **Asking the model directly for 32×32 output.** Models output 1024×1024 regardless of prompt. Always post-process.
|
|
62
|
+
- **Generating sprites with transparent backgrounds via prompt.** Gemini fights this. Use solid magenta (#FF00FF) background, then color-key it out in post-process.
|
|
63
|
+
- **Using `nearest-neighbor downsample` for the AI→32×32 step.** Picks up too much per-pixel noise. Median is consistently better.
|
|
64
|
+
- **Trusting the AI's own "this is pixel art" claim.** It will produce pixel-art-styled outputs that have soft edges, wrong-grid alignment, and 1000+ colors. Always run deterministic checks before AI review.
|
|
65
|
+
- **Generating siblings independently.** Per-tile generation cannot produce sibling coherence (same character in different facings, paths that connect, transitions that line up). The model has no cross-call memory. See "Family pipeline" below for the fix.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Family pipeline (Phase 1+ architecture)
|
|
70
|
+
|
|
71
|
+
The original per-tile pipeline produced character sprites where each direction looked like a different person. Root cause: independent generations have no shared style anchor. The family pipeline (`modules/art-pipeline/pipeline/family_*.py`) fixes this by making the **family** — not the tile — the unit of generation.
|
|
72
|
+
|
|
73
|
+
For decision rationale and alternatives considered, see [ADR 0008](../adr/<redacted>.md).
|
|
74
|
+
|
|
75
|
+
### What good looks like (numerically)
|
|
76
|
+
|
|
77
|
+
After migrating the player character to a family:
|
|
78
|
+
|
|
79
|
+
| Metric | Per-tile pipeline | Family pipeline |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| Silhouette area CV across frames | 0.67 (177→900 px) | 0.11 (213→282 px) |
|
|
82
|
+
| Silhouette height CV | 0.08 | 0.00 (all 27 px) |
|
|
83
|
+
| Palette Jaccard, worst pair | 0.29 | 0.74 |
|
|
84
|
+
| Dominant-color overlap, worst pair | 0.00 | 0.60–0.80 |
|
|
85
|
+
| Luminance EMD, worst pair | 71.97 | 12–16 |
|
|
86
|
+
| Generations to a passing result | 4 separate calls | 1 sheet call |
|
|
87
|
+
| Cost per character set | ~$0.16 | ~$0.04 |
|
|
88
|
+
|
|
89
|
+
### Recipe: generating a family
|
|
90
|
+
|
|
91
|
+
1. **Define the family** in `modules/art-pipeline/template/families.json`. A family has `kind` (taxonomy), `layout` (e.g. `2x2`, `1x4`), `members` (each with a cell coordinate), `shared_style` (one paragraph that every member must respect), and optional per-family threshold overrides.
|
|
92
|
+
2. **One image-gen call** per family. The sheet prompt instructs the model on the cell layout *and* the cross-cell coherence rules. Code: `family_generator.build_sheet_prompt()`.
|
|
93
|
+
3. **Slice** the returned sheet by the family's layout. Each cell becomes a 32×32 PIL image after median-downsample + palette-quantize. Code: `family_generator.slice_sheet()`.
|
|
94
|
+
4. **Run deterministic family checks** on the sliced cells. These compute numeric coherence metrics (silhouette area CV, height CV, palette Jaccard, dominant-color overlap, luminance EMD). Hard-fail if any is below its threshold. Code: `family_checks.run_all()`.
|
|
95
|
+
5. **Only if step 4 passes**, run the Gemini family-coherence review. The review is told which deterministic checks already passed, so it focuses on subjective criteria (`family_consistency`, `character_identity`, `grid_alignment`, `firered_match`, `mythic_greek`). Code: `family_review.review_family()`.
|
|
96
|
+
6. **Atomic-swap to publish.** The orchestrator does NOT auto-publish. Run with `--publish` to copy sliced cells into `modules/art-pipeline/generated/tiles/`. Default behavior is "save under `iterations/_families/<id>/` and let the human approve."
|
|
97
|
+
|
|
98
|
+
### Recipe: composing the sheet prompt
|
|
99
|
+
|
|
100
|
+
The prompt is built in three blocks:
|
|
101
|
+
- **Header**: "Generate ONE pixel-art sheet for a 16-bit RPG tile-set in the style of Pokemon FireRed, restyled for ancient Mediterranean Greece. Output a single image laid out as a {rows}-row by {cols}-column grid of {n} cells."
|
|
102
|
+
- **Discipline**: "REQUIREMENTS for every cell: top-down view, hard pixel edges, NO anti-aliasing, NO blur, NO frame, NO border between cells, NO text, NO labels, NO arrows, NO numbering."
|
|
103
|
+
- **Coherence**: "CRITICAL coherence rules across cells: every cell uses the SAME palette of colors, the SAME lighting direction (top-left), the SAME saturation level, and the SAME dithering density. The sheet must read as ONE coordinated set."
|
|
104
|
+
|
|
105
|
+
Per-cell descriptions then go in. For character families, an additional rule: *"All cells depict the SAME individual: identical body shape, identical clothing colors, identical hair, identical proportions. Only the facing direction changes."*
|
|
106
|
+
|
|
107
|
+
### Why deterministic-first ordering matters
|
|
108
|
+
|
|
109
|
+
Putting deterministic checks **before** the Gemini review changes the cost shape entirely:
|
|
110
|
+
|
|
111
|
+
- Old loop (per-tile): every retry burned a Gemini review call to discover failure.
|
|
112
|
+
- New loop (family): a failing family fails the deterministic gate for free, and the failure produces a *numeric* fix-hint ("CV 0.67 > 0.35, make characters same height") that's far more actionable than prose critique.
|
|
113
|
+
|
|
114
|
+
Gemini becomes a polish check, not a failure detector. On the player_character run, Gemini was called once. Old per-tile equivalent would have been 4–24 review calls.
|
|
115
|
+
|
|
116
|
+
### Anchor refinement (failure recovery)
|
|
117
|
+
|
|
118
|
+
The orchestrator's tier 5 (`t5_anchor_refine`) is the recovery move when the first attempt has *one* good cell but family coherence fails:
|
|
119
|
+
|
|
120
|
+
1. After every attempt, `family_checks.find_anchor_member()` picks the member whose silhouette + palette is most representative of the family.
|
|
121
|
+
2. That member's PNG is saved as `iterations/_families/<id>/_anchor.png`.
|
|
122
|
+
3. On the next attempt, `t5_anchor_refine` passes the anchor as a reference image to nano-banana, with the prompt: *"The first attached image is the locked anchor. Every cell must match the anchor's clothing colors, hair, body proportions, and palette. Only the facing direction changes."*
|
|
123
|
+
|
|
124
|
+
In the player run this never fired (first attempt passed). It exists as the recovery path for harder families.
|
|
125
|
+
|
|
126
|
+
### Thresholds: per-family, not global
|
|
127
|
+
|
|
128
|
+
`families.json` has a top-level `defaults` block (currently 9.0/7.0 with default deterministic thresholds) and per-family overrides. Why per-family:
|
|
129
|
+
|
|
130
|
+
- A character family tolerates more palette variation than a ground-tile family (different shading per facing is expected).
|
|
131
|
+
- A ground-tile family must self-seam tightly (column 0 ≈ column 31), but characters have no self-seam concept at all.
|
|
132
|
+
- A path autotile must satisfy edge contracts that don't apply to characters.
|
|
133
|
+
|
|
134
|
+
Override only what differs. Inherited keys flow from `defaults.deterministic_thresholds` to the family.
|
|
135
|
+
|
|
136
|
+
### Phase 1 calibration: lower threshold to bootstrap, ramp later
|
|
137
|
+
|
|
138
|
+
For player_character we set `pass_threshold: 7.0`, `min_individual: 5.0` to get to a first pass cheaply and validate the architecture. The actual run scored 8.6 then 9.0 — well above the 7.0 bar, suggesting the architecture had more headroom than the lowered bar required. **Operating rule: leave the threshold at 7.0 until enough families have run that we have data on real ceiling.** Ramping prematurely just creates noise.
|
|
139
|
+
|
|
140
|
+
### Family-pipeline pitfalls observed
|
|
141
|
+
|
|
142
|
+
- **`.env.local` does not propagate to git worktrees.** It's gitignored, lives only in the worktree where it was created. When working in a new worktree, copy it from a sibling worktree before running anything that touches the Google API.
|
|
143
|
+
- **The Gemini reviewer can be flattering when the deterministic block tells it everything passed.** Stay vigilant: read at least one Gemini critique JSON per session to confirm the prose tracks the numbers.
|
|
144
|
+
- **Cell magenta-keying still has occasional residue** at the seam between sprite and the cell's magenta border. Same fix as the per-tile pipeline: ensure the model's magenta is pure (no shading, no dithering on the magenta) and trust the post-process keying.
|
|
145
|
+
- **Sheet aspect ratio matters.** A 2×2 layout produces a square output (good — both Imagen and Nano Banana prefer 1:1). A 1×4 layout produces 4:1, which Imagen's `aspect` parameter supports but Nano Banana's wrapper does not control. Prefer 2×2 over 1×4 for 4-member families until that's resolved.
|
|
146
|
+
|
|
147
|
+
### When to migrate an existing tile into a family
|
|
148
|
+
|
|
149
|
+
The old per-tile pipeline still works for the 22 non-character tiles. We migrate when:
|
|
150
|
+
1. The existing per-tile output is unsatisfactory (e.g., the four player frames).
|
|
151
|
+
2. The tile has natural siblings (transitions, autotiles, multi-tile objects, character spritesheets).
|
|
152
|
+
3. We're rebuilding the area for some other reason and might as well do it right.
|
|
153
|
+
|
|
154
|
+
Otherwise leave existing tiles alone — they're published and working.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Stress test (Phase 1.5) — 8 families, three generation patterns
|
|
159
|
+
|
|
160
|
+
After the player_character family validated the architecture for one pattern, we ran a stress test against 8 families spanning every shape of family we could think of: characters, transitions, multi-tile objects, paths, cliffs, houses, boats, coastlines. Round 1 surfaced an architecture gap; Round 2 fixed the prompt strategy; Round 3 fixed the check dispatch. Final result: 7 of 8 families pass, with the 8th failing on a real subjective style judgment (not architecture).
|
|
161
|
+
|
|
162
|
+
Total stress-test cost: **$1.44 of $80**. Three rounds, ~30 image-gen calls, ~20 Gemini reviews.
|
|
163
|
+
|
|
164
|
+
### The three patterns (this is what we learned)
|
|
165
|
+
|
|
166
|
+
What initially looked like one architecture is actually **three**. Each needs different prompt language and different check dispatch.
|
|
167
|
+
|
|
168
|
+
#### Pattern A — coordinated variants
|
|
169
|
+
Each cell is a different *view of one concept*. Cells never sit adjacent in-game — different cells get placed at different world locations. Coherence = identity (same character, same boundary style, same foam color).
|
|
170
|
+
|
|
171
|
+
Examples: `player_character` (4 facings), `vendor_hyperion` (1 pose), `transition_grass_sand` (4 directional boundaries), `coastline_sand_sea` (4 directional shorelines), `small_boat` (1 sprite).
|
|
172
|
+
|
|
173
|
+
- Prompt: describe each cell separately with strong cross-cell coherence rules ("identical clothing, identical hair, identical foam color across all cells").
|
|
174
|
+
- Deterministic checks that apply: cross-cell color coherence (palette Jaccard, dominant overlap, luminance EMD) + sprite silhouette CV for character kinds.
|
|
175
|
+
- Edge contracts: do NOT apply (cells aren't placed adjacent in-game).
|
|
176
|
+
- Gemini family-review: judges identity coherence + style match.
|
|
177
|
+
|
|
178
|
+
#### Pattern B — continuous illustration
|
|
179
|
+
The family is **one object** drawn as a single illustration that we slice on a virtual grid afterward. The model is NOT told about cells at all. Cells are different *parts of one drawing*; their palettes are *naturally* different (a roof and a foundation are different colors, by design).
|
|
180
|
+
|
|
181
|
+
Examples: `container` (one shipping container in 4 cells), `small_house` (one Mediterranean dwelling in 9 cells), `cliff_face` (one cliff in 3 cells, vertically).
|
|
182
|
+
|
|
183
|
+
- Prompt: describe the whole subject as a single illustration filling the image edge-to-edge. Explicitly forbid "cell borders, panel separators, frames, grid lines." Tell the model: *"the image will be sliced afterward, but you do not need to think about that."*
|
|
184
|
+
- Deterministic checks that apply: only per-cell post-processing (palette quantize, dimensions, AA). NO cross-cell coherence (false negatives — different parts have different palettes by design). NO edge contracts (tautological — the slicer guarantees adjacency by construction).
|
|
185
|
+
- Gemini family-review: judges whether the assembled illustration reads as one coherent thing AND matches the project style.
|
|
186
|
+
|
|
187
|
+
#### Pattern C — true autotile family (not yet validated)
|
|
188
|
+
A set of tiles where each cell is a different *topology* (NW corner, straight, T-junction, cross, etc.) that must connect cleanly at specific edges. Pattern A doesn't work (the model can't keep the path width identical across separate variant generations). Pattern B doesn't work either — the path autotile we tried produced a "border tile set" (square frame with no interior cross) when the model drew it as one continuous loop, which is not the same as a 9-topology autotile.
|
|
189
|
+
|
|
190
|
+
Best evidence: `path_autotile` under continuous_illustration produced usable tiles for paths-along-borders but lost the four-way cross that a full autotile needs.
|
|
191
|
+
|
|
192
|
+
**Pattern C likely requires a third strategy not yet built**: cell-by-cell generation with the previously-generated cell's edge as an image-conditioning reference. This is the academic "Wang tile" / image-conditioning approach. We have not yet implemented it. **Open architectural question.**
|
|
193
|
+
|
|
194
|
+
### How to set the strategy
|
|
195
|
+
|
|
196
|
+
`families.json` field: `slice_strategy`. Values:
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
"slice_strategy": "coordinated_variants" // Pattern A (default if absent)
|
|
200
|
+
"slice_strategy": "continuous_illustration" // Pattern B
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Per-strategy required fields:
|
|
204
|
+
- Pattern A: per-member `desc` describing each cell.
|
|
205
|
+
- Pattern B: top-level `continuous_description` describing the whole subject as one illustration. Per-member `desc` becomes a label-only field used for the slice filename.
|
|
206
|
+
|
|
207
|
+
### What was wrong with our first attempt
|
|
208
|
+
|
|
209
|
+
Round 1 used Pattern A's prompt for everything. For continuous-object families this was wrong because:
|
|
210
|
+
- The model interpreted "grid of cells" as a sprite-sheet brief and drew **black panel borders between every cell**, even when explicitly told "no border between cells."
|
|
211
|
+
- Each cell was treated as an independent painting, so palette and lighting drifted dramatically (e.g. a 3×3 house had 3 different palettes, one per row, with luminance EMD = 84).
|
|
212
|
+
- Edge contracts measured 0–50% match.
|
|
213
|
+
|
|
214
|
+
Round 2 fixed the prompt strategy. Edge contracts immediately jumped (some hit 100%). Round 3 fixed the check dispatch (skip cross-cell + edge contracts for Pattern B). All four continuous-illustration families passed Gemini review.
|
|
215
|
+
|
|
216
|
+
### Round-by-round measurements (durable record)
|
|
217
|
+
|
|
218
|
+
| Family | Pattern | R1 result | R2 result | R3 result | Final Gemini |
|
|
219
|
+
|---|---|---|---|---|---|
|
|
220
|
+
| vendor_hyperion | A (singleton) | ✅ pass | — | — | 8.0 |
|
|
221
|
+
| transition_grass_sand | A (variants) | ✅ pass | — | — | 9.0 |
|
|
222
|
+
| small_boat | A (singleton) | ✅ pass | — | — | 9.25 |
|
|
223
|
+
| coastline_sand_sea | A (variants) | ❌ palette/dominant fail | ✅ pass (tightened anchor) | — | 8.5 |
|
|
224
|
+
| container | B (continuous) | ❌ edge 9–50% | partial (50–100%) | ✅ pass | 8.25 |
|
|
225
|
+
| small_house | B (continuous) | ❌ all 15 checks fail | worse (luminance EMD 116) | ✅ pass | 8.5 |
|
|
226
|
+
| cliff_face | B (continuous) | ❌ edge 0–25% | ❌ edge 0–60% | ⚠️ style fail (Gemini 6.25 — "too painterly, not FireRed enough") | 6.25 |
|
|
227
|
+
| path_autotile | B (continuous) | ❌ edge 0–50% | partial (50–90%) | ✅ pass (as border tile set, not full autotile) | 8.0 |
|
|
228
|
+
|
|
229
|
+
### Insights worth keeping
|
|
230
|
+
|
|
231
|
+
1. **Different patterns need different prompt language AND different check dispatch.** Conflating them makes the architecture appear broken when only the prompt strategy is wrong.
|
|
232
|
+
|
|
233
|
+
2. **The model can draw beautiful single illustrations** when not constrained to a "grid of cells" brief. Round 2's container, house, cliff, and path images were genuinely good art — the original problem was framing.
|
|
234
|
+
|
|
235
|
+
3. **Edge contracts are a Pattern-A concept misapplied to Pattern B.** For continuous illustrations, the slicer guarantees adjacency by construction. Checking pixel-match at slice lines is meaningless and misleading.
|
|
236
|
+
|
|
237
|
+
4. **Cross-cell color coherence is a Pattern-A concept.** For continuous illustrations, different parts naturally have different palettes (roof ≠ foundation, sky ≠ ground). The check correctly flagged this as "incoherent" but in fact it was a feature, not a bug.
|
|
238
|
+
|
|
239
|
+
5. **Gemini's right role is subjective polish, not failure detection.** When the deterministic gate is appropriately scoped, Gemini reliably catches subjective style problems (cliff_face's "too painterly, blended transitions instead of hard pixel edges" was a real, useful critique). When the deterministic gate is wrongly scoped, Gemini calls get wasted on false positives.
|
|
240
|
+
|
|
241
|
+
6. **The fix from 4/8 to 7/8 was small.** Two contained changes: (a) add a `slice_strategy` field with a new prompt builder branch; (b) skip cross-cell + edge-contract checks for `continuous_illustration` in `family_checks.run_all()`. About 60 lines of Python plus the schema field. The architecture core (family schema, generator pipeline, retry logic, Gemini review prompt) was unchanged.
|
|
242
|
+
|
|
243
|
+
7. **Stress-testing surfaces gaps cheaply.** Each round was ~$0.50. The full 3-round stress test cost ~$1.44 to identify and validate fixes for an architectural assumption that would have shipped silently broken if we'd kept moving on player_character → vendor → next-family.
|
|
244
|
+
|
|
245
|
+
### Open questions surfaced (not yet resolved)
|
|
246
|
+
|
|
247
|
+
- **Pattern C strategy (true autotile families).** Path autotile under Pattern B produced a usable border-tile set but lost the topology variants a full autotile needs. Solution likely involves cell-by-cell generation with image-conditioning anchors. Defer until V1 actually needs an autotile path.
|
|
248
|
+
- **Cliff style failure.** Gemini consistently scored cliff at 6.25 across attempts, citing "too painterly, soft transitions, blended dithering." The model produces beautiful illustrations but they don't match FireRed's hard-pixel-edge discipline. Possible fixes: (a) tighter style-specific prompt for vertical structures, (b) post-processing to flatten dithering, (c) accept that cliff is a V2 problem. Not yet decided.
|
|
249
|
+
- **"Object-as-asset" vs "object-as-tile-set" question.** Pattern B continuous illustrations might be better used as a single sprite asset placed across multiple grid cells in-game, rather than as 4 / 9 independent tiles. Either model works visually; the choice is about the game-engine integration. **Defer to whenever we're ready to place a multi-tile object in the world map.**
|
|
250
|
+
|
|
251
|
+
### Pattern B operational rule
|
|
252
|
+
|
|
253
|
+
When adding a new continuous-illustration family:
|
|
254
|
+
|
|
255
|
+
1. Set `slice_strategy: "continuous_illustration"`.
|
|
256
|
+
2. Provide a top-level `continuous_description` describing the whole subject as ONE illustration. Use language like *"filling the entire image edge-to-edge,"* *"NO cell borders,"* *"the image will be sliced afterward."*
|
|
257
|
+
3. Pick a layout that matches the natural orientation (e.g. 3×1 for a vertical cliff, 3×3 for a building front, 2×2 for a square object).
|
|
258
|
+
4. Per-member `desc` becomes label-only — describe what each slice will contain post-hoc, but don't expect the model to read these.
|
|
259
|
+
5. Don't define `edge_contracts` — they're skipped anyway.
|
|
260
|
+
6. Trust the slicer + Gemini family-review.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Pattern C — autotile families (Phase A–D)
|
|
265
|
+
|
|
266
|
+
For a region of one terrain surrounded by another (grass islands in sand, sand
|
|
267
|
+
beaches against sea) and for line/path topology (marble flagstones threading
|
|
268
|
+
through grass), neither Pattern A nor Pattern B works. We hit this in stress
|
|
269
|
+
testing: the path autotile under Pattern B produced a usable border tile set
|
|
270
|
+
but lost the topology variants a real autotile needs. The model is good at
|
|
271
|
+
texture appearance; it is not good at producing all the topology variants of
|
|
272
|
+
a tile set as one image.
|
|
273
|
+
|
|
274
|
+
The fix: **AI generates 3–5 small primitive textures; a pure-Python compositor
|
|
275
|
+
deterministically composes the 47 (or 16) tiles by per-quadrant masking.**
|
|
276
|
+
Standards-compliant: 47-blob (RPG Maker A2 / Tiled / Cr31 / Godot blob) for
|
|
277
|
+
region terrain, 16-path (4-cardinal) for line terrain. For decision rationale
|
|
278
|
+
see [ADR 0009](../adr/0009-autotile-architecture.md).
|
|
279
|
+
|
|
280
|
+
### Why this works
|
|
281
|
+
|
|
282
|
+
**Edges match by construction.** Every tile that has the same edge configuration
|
|
283
|
+
samples its boundary pixels from the same primitive at the same logical
|
|
284
|
+
position. So when two such tiles sit next to each other in the world, the seam
|
|
285
|
+
pixels are guaranteed identical to within bounded jitter. We didn't need a
|
|
286
|
+
retry loop for seam alignment — the compositor produces correct seams on the
|
|
287
|
+
first pass. Validated by 100% edge-match on the all-interior composition test.
|
|
288
|
+
|
|
289
|
+
**The model only does what it's good at.** The AI generates 3–5 small texture
|
|
290
|
+
chunks (interior, exterior, edge, concave-corner, convex-corner). These are
|
|
291
|
+
within the model's competence — they're each a small piece of a coherent
|
|
292
|
+
texture. The model is not asked to plan tile-set topology, which is what
|
|
293
|
+
breaks down.
|
|
294
|
+
|
|
295
|
+
**Cost is dramatically lower.** A 47-tile family from 5 primitive generations
|
|
296
|
+
is ~$0.20–0.45 vs ~$1.88 if every tile were generated independently. Per
|
|
297
|
+
final tile this is ~$0.005–0.010 vs ~$0.040 — about 4–8× cheaper.
|
|
298
|
+
|
|
299
|
+
### Recipe: building a region autotile family (47-blob)
|
|
300
|
+
|
|
301
|
+
1. **Define the family** in `modules/art-pipeline/template/families.json` with
|
|
302
|
+
`kind: "autotile_blob_47"`. Required fields: `interior_terrain`,
|
|
303
|
+
`exterior_terrain`, `interior_short`, `exterior_short`, `shared_style`,
|
|
304
|
+
and a `primitives` array of 5 entries with roles
|
|
305
|
+
`interior` / `exterior` / `patch_horiz_NW` / `patch_concave_NW` /
|
|
306
|
+
`patch_convex_NW`. Each primitive has its own `id`, `desc`, and `size_px`
|
|
307
|
+
(32 for interior/exterior textures, 16 for boundary patches).
|
|
308
|
+
2. **Run the orchestrator**:
|
|
309
|
+
`python3 modules/art-pipeline/pipeline/autotile_orchestrator.py <family_id>`.
|
|
310
|
+
3. The orchestrator generates each primitive with retries (up to 3 attempts
|
|
311
|
+
for texture-role primitives, 1 attempt for non-texture primitives), applies
|
|
312
|
+
seamless-enforcement to texture roles, calls
|
|
313
|
+
`autotile_compositor.compose_blob47()`, and saves all 47 tiles.
|
|
314
|
+
4. The validation harness renders three test compositions (all-interior,
|
|
315
|
+
island, organic) and reports edge-match scores.
|
|
316
|
+
|
|
317
|
+
### Recipe: building a path autotile family (16-path)
|
|
318
|
+
|
|
319
|
+
Same as region but with `kind: "autotile_path_16"` and a 3-primitive bundle:
|
|
320
|
+
`terrain` / `path_node` / `path_arm_N`. The path_arm_N primitive is anchored
|
|
321
|
+
at the top edge with the path running vertically; the compositor rotates it
|
|
322
|
+
for the other 3 cardinal directions.
|
|
323
|
+
|
|
324
|
+
### Recipe: seamless texture enforcement (the trick that made it work)
|
|
325
|
+
|
|
326
|
+
AI-generated textures don't naturally tile seamlessly — col 0 ≠ col 31 in the
|
|
327
|
+
raw output. The seamless-enforcement step in
|
|
328
|
+
`autotile_orchestrator._make_seamless()` averages the leftmost and rightmost
|
|
329
|
+
columns of pixels, applies the average to both columns, repeats for top/bottom
|
|
330
|
+
rows, then re-quantizes to the locked palette. Result: col 0 == col 31 and row
|
|
331
|
+
0 == row 31 by construction. The visible cost: the 4 outermost pixels of every
|
|
332
|
+
edge are slightly blended versions of opposite-edge content. For texture-style
|
|
333
|
+
primitives (grass, sand, sea) this is invisible.
|
|
334
|
+
|
|
335
|
+
Without this step, even a "seamless" prompt produces ~50–70% edge match in
|
|
336
|
+
all-interior compositions. With the step, 100%.
|
|
337
|
+
|
|
338
|
+
### Why we still split silhouette / color / luminance / edge-contracts
|
|
339
|
+
|
|
340
|
+
The deterministic-checks framework (Pattern A/B) doesn't apply to autotiles:
|
|
341
|
+
- Cross-cell color coherence: primitives are independent; we don't compare them.
|
|
342
|
+
- Edge contracts: tautological for autotiles (the compositor produces matching
|
|
343
|
+
edges by construction).
|
|
344
|
+
|
|
345
|
+
The autotile validation harness uses a different scoring metric: **edge-match
|
|
346
|
+
score on rendered test compositions**. For each adjacent tile pair in a
|
|
347
|
+
rendered composition, count how many seam pixels match within a perceptual
|
|
348
|
+
tolerance. 100% means the composition is seamless when displayed.
|
|
349
|
+
|
|
350
|
+
### Pattern C results — Phase B/C run
|
|
351
|
+
|
|
352
|
+
| Family | Primitives | all_interior | island | organic / winding | cost |
|
|
353
|
+
|---|---|---|---|---|---|
|
|
354
|
+
| grass_on_sand | 5 | 100.0% | 85.7% | 77.2% | $0.47 |
|
|
355
|
+
| sand_on_sea | 5 | 100.0% | 85.7% | 74.7% | $0.23 |
|
|
356
|
+
| marble_path | 3 | n/a | n/a | winding 99.2% / cross 99.1% | $0.16 |
|
|
357
|
+
| cliff_top | 5 | 100.0% | 86.2% | 74.7% | $0.27 |
|
|
358
|
+
|
|
359
|
+
**100% match on all-interior compositions** validates the seamless-tile
|
|
360
|
+
approach. The 75–86% scores on boundary compositions (island, organic) reflect
|
|
361
|
+
the boundary primitives being independently generated — they're stylistically
|
|
362
|
+
coherent but not pixel-identical at every transition. Acceptable for V1;
|
|
363
|
+
generating boundary primitives in pairs with image conditioning would close
|
|
364
|
+
this gap and is a V2 candidate.
|
|
365
|
+
|
|
366
|
+
The marble_path 99% score is dramatically higher because path tiles are stamps
|
|
367
|
+
on a uniform background — most seams are terrain-to-terrain (perfectly
|
|
368
|
+
tileable), only a few are path-to-terrain.
|
|
369
|
+
|
|
370
|
+
### Pattern C pitfalls observed
|
|
371
|
+
|
|
372
|
+
- **Direction-asymmetric terrain breaks 47-blob.** Cliffs need different tiles
|
|
373
|
+
for north-facing vs south-facing edges (the south edge shows a stone face;
|
|
374
|
+
the north edge is just grass). 47-blob produces the same edge tile on all
|
|
375
|
+
four sides of a cliff region. Result: cliff_top is topologically correct
|
|
376
|
+
but stylistically weak. **For real cliffs, V1+ needs a direction-aware
|
|
377
|
+
cliff scheme** (per-edge tile selection or a 4-orientation autotile
|
|
378
|
+
variant). Document and defer.
|
|
379
|
+
- **Per-tile interior repetition.** Without per-tile sample-offset jitter,
|
|
380
|
+
every interior tile looks identical. Visible in large interior fields.
|
|
381
|
+
Phase A–D ships without jitter; V2 candidate.
|
|
382
|
+
- **Triple junctions are unrepresentable.** Where 3 terrains meet at one
|
|
383
|
+
tile, the 47-blob convention can't pick a tile. Forbid triple junctions
|
|
384
|
+
in level design (this is the standard solution in the industry).
|
|
385
|
+
- **Two-way terrain pairs need two families.** `grass_on_sand` does not
|
|
386
|
+
serve `sand_on_grass` — the boundary direction matters. For V1, declare
|
|
387
|
+
the families you need.
|
|
388
|
+
|
|
389
|
+
### Runtime architecture
|
|
390
|
+
|
|
391
|
+
The autotile picker is split-implementation:
|
|
392
|
+
- `modules/art-pipeline/pipeline/autotile_mapping.py` — Python source of truth, used by the
|
|
393
|
+
compositor at build time.
|
|
394
|
+
- `public/game/world/autotile.js` — JavaScript mirror, used by the in-game
|
|
395
|
+
renderer. Cross-verified against the Python table at build time (a
|
|
396
|
+
smoke-test compares all 256 inputs).
|
|
397
|
+
|
|
398
|
+
When the runtime data-model refactor lands (Phase D, deferred for review):
|
|
399
|
+
the world map stores terrain ids per cell; the renderer iterates cells and
|
|
400
|
+
calls `selectBlob47(myTerrain, neighbors)` or `selectPath16(neighbors)` to
|
|
401
|
+
pick the tile index, then loads the corresponding PNG from the family's
|
|
402
|
+
tile set.
|
|
403
|
+
|
|
404
|
+
### Open question
|
|
405
|
+
|
|
406
|
+
**Cliffs deserve a direction-aware scheme.** The 47-blob approach gives a
|
|
407
|
+
stylized "shelf" look on all four edges of a cliff region. Real cliff
|
|
408
|
+
autotiles in RPG Maker (A4 layer) and similar systems use a strip-based
|
|
409
|
+
scheme where the south-facing edge is drawn as a vertical wall while other
|
|
410
|
+
edges are flat transitions. If V1 ships cliffs, this needs to be built.
|
|
411
|
+
Otherwise defer to V2. Decision pending Lars.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Recipe — private-first npm distribution (core + client)
|
|
2
|
+
|
|
3
|
+
> Implements [ADR 0134](../adr/<redacted>.md). Pre-launch, `@cloudbongos/core` and `@cloudbongos/client` publish as **private, scoped** npm packages on a paid `cloudbongos` npm org; at launch they flip to public. The daily command is `bongos` regardless of package name.
|
|
4
|
+
>
|
|
5
|
+
> **Why private must be scoped:** on npm, *unscoped* names (like `cloudbongos`) are always public — only *scoped* names (`@cloudbongos/…`) can be private, and only on a paid plan. The repo already uses the `@cloudbongos` scope, so no rename is needed now.
|
|
6
|
+
|
|
7
|
+
## The pieces
|
|
8
|
+
|
|
9
|
+
| Package | What it is | Built by |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `@cloudbongos/core` | the platform an instance installs + the `bongos` CLI (`bin`) | `bongos package-core` (`scripts/gds/package-core.js`) — synthesizes the package.json + a pruned lockfile, redacts, and packs a `.tgz` |
|
|
12
|
+
| `@cloudbongos/client` | the generated typed API client | `node scripts/gds/gen-api-client.js` (regenerates `clients/bongos-client/`) |
|
|
13
|
+
|
|
14
|
+
Both carry `publishConfig: { access: "restricted" }`, so **publishing them is private by default** — no public leak if a flag is forgotten.
|
|
15
|
+
|
|
16
|
+
## One-time owner setup (only the owner can do these)
|
|
17
|
+
|
|
18
|
+
These involve payment and permanent, account-level actions. They are **not** done inside a build session.
|
|
19
|
+
|
|
20
|
+
1. **Put the `cloudbongos` npm org on a paid plan.** Private scoped publishing requires it. On npmjs.com → your org → Billing → upgrade to a plan that allows private packages (npm Teams, ~$7/member/month). Add as members only the people who need to publish or install during pre-launch — each is a billed seat.
|
|
21
|
+
2. **Create an access token.** npmjs.com → Access Tokens → *Generate New Token* → **Granular/Automation**, with **read-write** on the `@cloudbongos` packages (for publishing) — a **read-only** token is enough for machines that only install. Store it as an environment variable, never in a committed file:
|
|
22
|
+
```sh
|
|
23
|
+
export NPM_TOKEN=<redacted>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Publish (the real, permanent step — owner)
|
|
27
|
+
|
|
28
|
+
Always preview with a dry-run first (no upload, no login needed):
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
# Core — build the tarball and DRY-RUN the private publish:
|
|
32
|
+
node scripts/gds/package-core.js --publish
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Look for `restricted access` and the `@cloudbongos/core@<version>` line. When it looks right, publish for real (this is **permanent** — npm can't delete a name after 72h):
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
npm login # once per machine (+ 2FA)
|
|
39
|
+
node scripts/gds/package-core.js --publish --live # actually publishes, still private
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
For the client (note the `./` — without it, npm reads the path as a git package spec, not a folder):
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
node scripts/gds/gen-api-client.js # ensure it's fresh
|
|
46
|
+
npm pack ./clients/bongos-client --dry-run # token-free content preview
|
|
47
|
+
npm publish ./clients/bongos-client # real (publishConfig makes it restricted; needs npm login)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Install a private package (any consumer machine or instance)
|
|
51
|
+
|
|
52
|
+
Add a one-line `.npmrc` (repo-root or `~/.npmrc`) that reads the token from the environment:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
//registry.npmjs.org/:_authToken=<redacted>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Then, with `NPM_TOKEN` set in the environment:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
npm install -g @cloudbongos/core # global → the `bongos` command, then `bongos init`
|
|
62
|
+
npm install @cloudbongos/client # in a project that calls the API
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Without a valid token + org membership the install 404s — that is the private gate working.
|
|
66
|
+
|
|
67
|
+
> Provisioning still installs the core from a **vendored tarball** committed into each instance repo (task 2053) — that path is unchanged and needs no token. Wiring provisioning to pull the pinned core from the private registry instead is a tracked follow-up.
|
|
68
|
+
|
|
69
|
+
## Going public at launch
|
|
70
|
+
|
|
71
|
+
Pick either — both keep the daily `bongos` command working:
|
|
72
|
+
|
|
73
|
+
- **Flip the same scoped packages public** (simplest):
|
|
74
|
+
```sh
|
|
75
|
+
npm access public @cloudbongos/core
|
|
76
|
+
npm access public @cloudbongos/client
|
|
77
|
+
```
|
|
78
|
+
(Or change `publishConfig.access` to `"public"` and republish.) Public installs need no token; the paid seats can be dropped.
|
|
79
|
+
- **Also publish the unscoped vanity name** for `npm install -g cloudbongos` — that is [task 2025](https://example.com/builders#/task/2025) (rename in `package-core.js`/`upgrade.js` + docs), done at launch.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Recipe — GDS search-index ingestion (repo markdown)
|
|
2
|
+
|
|
3
|
+
How the `search_chunks` index (the recall layer, [ADR 0060](../adr/0060-gds-retrieval-layer.md)) gets populated from repo markdown, and how to operate it. Read before touching `scripts/gds/search-ingest-md.js` or the deploy hook.
|
|
4
|
+
|
|
5
|
+
> The query side is [`src/bongos/search.js`](../../src/bongos/search.js) + [`POST /api/gds/search`](../../src/bongos/routes/search.js) ([#949](https://example.com/builders#/task/949)); rank/owner scoping + its isolation suite are [#950](https://example.com/builders#/task/950). Ingestion has two halves: **repo markdown** (this recipe's first sections — [#947](https://example.com/builders#/task/947), the deploy hook) and **DB prose** (the [DB-prose nightly](#db-prose-nightly-timer) section below — [#948](https://example.com/builders#/task/948), a systemd timer).
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
`node scripts/gds/search-ingest-md.js` walks the repo's markdown (~226 files), chunks each file via the heading-aware chunker ([`src/bongos/search-chunker.js`](../../src/bongos/search-chunker.js)), and upserts the chunks into `search_chunks`:
|
|
10
|
+
|
|
11
|
+
- **Delta-driven.** Each chunk's `content_hash` (sha256 of its body) is the change key. The upsert's `ON CONFLICT … DO UPDATE … WHERE content_hash IS DISTINCT FROM EXCLUDED.content_hash` makes an unchanged chunk a **no-op** (no row rewrite). A re-run over an unchanged tree writes nothing.
|
|
12
|
+
- **Prunes shrinkage.** If a file loses sections, chunks beyond the new count are deleted; if a file is removed from the tree entirely, all its chunks are deleted (`source_kind='doc' AND source_ref NOT IN (present)`).
|
|
13
|
+
- **Scopes by rank.** Most docs are `min_rank='xenos'` (shared). Read-sensitive documentation surfaces are tagged `min_rank='metic'` so a sub-Metic search can never surface them ([ADR 0060](../adr/0060-gds-retrieval-layer.md) §6 / [ADR 0043](../adr/<redacted>.md)). The metic set is curated in `SENSITIVE_DOC_GLOBS`: `docs/canonical-permissions.md`, `docs/security/`, `docs/audits/`, and the two trust-boundary ADRs (0016, 0043). **`CLAUDE.md` is deliberately `xenos`** — it's write-protected but the universal read-public onboarding index. Docs are never owner-scoped (`owner_builder_id` stays NULL); per-builder private content is the DB-prose ingester's job (memory rows).
|
|
14
|
+
|
|
15
|
+
## When it runs
|
|
16
|
+
|
|
17
|
+
A **non-blocking step in the prod deploy** ([`scripts/deploy/deploy-prod.sh`](../../scripts/deploy/deploy-prod.sh), mirrored in the droplet's hand-maintained `~/deploy.sh`), after the code update + migrations + healthz, where the new markdown and the DB are both on disk. It's wrapped `timeout 60 … || echo "…deploy unaffected"` — **an ingest failure never fails a deploy**; the next deploy (or a manual run) catches up.
|
|
18
|
+
|
|
19
|
+
> ⚠️ `scripts/deploy/deploy-prod.sh` is a **byte-faithful mirror** of the droplet's `~/deploy.sh`, which is **hand-maintained and NOT auto-installed** (the ci deploy key is forced-command-locked — [ADR 0042](../adr/<redacted>.md)/[0043](../adr/<redacted>.md)). When you change the mirror, **re-apply the same edit to `~/deploy.sh` on the droplet by hand** (`ssh lars@REDACTED_IP`), or the deploy hook won't actually run there. (Same caveat as the [prod deploy-script mirror](../../docs/recipes/ops-gotchas.md) note.)
|
|
20
|
+
|
|
21
|
+
## Operating it
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Dry-run: report file/chunk counts + which sources are metic-tagged. No DB, no writes.
|
|
25
|
+
node scripts/gds/search-ingest-md.js --dry-run
|
|
26
|
+
|
|
27
|
+
# Full ingest (writes to search_chunks). Idempotent — safe to re-run; unchanged
|
|
28
|
+
# chunks are skipped. Run on the droplet (DB on the local socket) or anywhere the
|
|
29
|
+
# GDS Postgres env (PGHOST/PGDATABASE) resolves.
|
|
30
|
+
node scripts/gds/search-ingest-md.js
|
|
31
|
+
|
|
32
|
+
# Initial backfill after first deploy of the recall layer: just run the full
|
|
33
|
+
# ingest once on the droplet — it indexes the whole corpus from empty.
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Output reports `inserted / updated / unchanged / pruned / deleted_sources_chunks` so you can see the delta. A first run over an empty index inserts everything; subsequent runs over an unchanged tree report all-unchanged.
|
|
37
|
+
|
|
38
|
+
## DB prose (nightly timer)
|
|
39
|
+
|
|
40
|
+
`node scripts/gds/search-ingest-db.js` indexes the prose that lives in the DB, not in git, as `source_kind='db'`: task descriptions + value summaries (`task:<id>`), learnings (`learning:<id>`), idea inbox (`idea:<id>`), done-when criteria (`criterion:<id>`), blockers (`blocker:<id>`), session-log notes (`session_log:<id>`), grade notes (`grade:<id>`), per-builder memory (`memory:<builder>:<path>`), and recent git commit subjects (`commit:<sha>`). Same delta-by-content_hash + prune-vanished behavior as the repo-md ingester.
|
|
41
|
+
|
|
42
|
+
Security ([ADR 0060](../adr/0060-gds-retrieval-layer.md) §6 / [ADR 0016](../adr/<redacted>.md) / [ADR 0022](../adr/0022-secrets-policy.md)):
|
|
43
|
+
|
|
44
|
+
- **`builder_memory` is owner-scoped** — each chunk carries `owner_builder_id`, so a builder's private memory only ever surfaces to that builder (the search route's owner filter, [#950](https://example.com/builders#/task/950)).
|
|
45
|
+
- **`security_sensitive` tasks are tagged `min_rank='metic'`**.
|
|
46
|
+
- **`vulnerability_reports` + `security_reports` are excluded entirely** — raw security findings don't belong in a broadly-searchable index.
|
|
47
|
+
- **Session/memory/grade text is scrubbed** through `ship.js` `scrubSecrets` (known shapes + high-entropy) before storage — the index must never hold a leaked credential.
|
|
48
|
+
|
|
49
|
+
It runs on a **nightly systemd timer** ([`infra/search-index-db.timer`](../../infra/search-index-db.timer) → [`infra/search-index-db.service`](../../infra/search-index-db.service), 03:30 UTC, 30 min before the pg_dump so they don't contend), modeled on `gds-db-backup`. DB prose changes more slowly than docs, so nightly is fresh enough; the repo-md half stays intra-day via the deploy hook.
|
|
50
|
+
|
|
51
|
+
**Operator install (one-time, on the droplet):**
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Copy the units into place, reload, enable + start the timer, then run once.
|
|
55
|
+
sudo cp /home/lars/example/infra/search-index-db.{service,timer} /etc/systemd/system/
|
|
56
|
+
sudo systemctl daemon-reload
|
|
57
|
+
sudo systemctl enable --now search-index-db.timer
|
|
58
|
+
systemctl list-timers search-index-db.timer # confirm it's scheduled
|
|
59
|
+
sudo systemctl start search-index-db.service # initial backfill now (don't wait for 03:30)
|
|
60
|
+
journalctl -u search-index-db.service -n 20 --no-pager # check the run
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Gotchas
|
|
64
|
+
|
|
65
|
+
- **`node` must be on PATH** in the deploy shell (it is — systemd runs the app via node). The script connects via the shared `src/db.js` pool (the same Postgres the app uses), so it needs the GDS env, not a token.
|
|
66
|
+
- **The index lags the merge by one deploy** for any doc changed in a PR that doesn't itself trigger a deploy — acceptable; the deploy hook re-indexes on every prod deploy, and the [staleness monitor + /watch tile](https://example.com/builders) (`#972`) surfaces a stalled index.
|
|
67
|
+
- **Don't lower the chunk size** without re-checking the eval set ([#939](https://example.com/builders#/task/939)) — chunk granularity affects recall quality and (later) embedding cost.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Self-hosting Cloud Bongos (Docker)
|
|
2
|
+
|
|
3
|
+
Bring up a vanilla Cloud Bongos instance — the build platform + builders' hall + status dashboard, with no game — on any machine with Docker. Shipped by V4.R63 ([task #1202](https://example.com/builders#/task/1202), [ADR 0062](../adr/<redacted>.md)).
|
|
4
|
+
|
|
5
|
+
> **Relation to configurable-root ([ADR 0108](../adr/<redacted>.md)):** this is the **single-checkout** self-host shape — the whole repo (core + config) is baked into one image, so `resolveCoreRoot()` and `resolveInstanceRoot()` ([`src/instance-config.js`](../../src/instance-config.js)) both resolve to `/app` inside the container. ADR 0108 does not deprecate this path — it stays the cheap, supported shape for a quick reskin (this is how `cloudbongos.com` runs). The *installed-as-a-dependency* shape (a consumer repo running `npm install @cloudbongos/core`) is the separate, heavier path ADR 0108 targets for a project that wants its own repo and its own upgrade cadence — see [`docs/recipes/packaging-the-core.md`](packaging-the-core.md).
|
|
6
|
+
|
|
7
|
+
## One command
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
docker compose up
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
That builds the image, starts Postgres, applies the build-system migrations (game-module migrations are skipped — this is a GDS-only instance), and serves the builders' hall at **http://localhost:3000**.
|
|
14
|
+
|
|
15
|
+
- The instance is **vanilla** by default: the neutral Cloud Bongos brand, every feature module (game, art pipeline, Discord, dev boxes) **off**. `.dockerignore` keeps the host's `config/branding.json` and `config/modules.json` out of the image, so it resolves to `config/branding.neutral.json` + `config/modules.neutral.json`.
|
|
16
|
+
- **No OTB scope-truth is seeded.** OTB/product data (game versions, goals, done-when criteria) lives in opt-in seed migrations under `migrations/instance/` (plus a few guarded blocks in the mixed files 003/006). `scripts/migrate.sh` skips them unless `GDS_APPLY_INSTANCE_SEEDS=1`, so a fresh DB comes up with only the schema and platform-universal defaults (ranks, achievements) — no crash, no foreign-key failures, no leftover versions. Platform system principals (`bfg-system`, `discord-bot-system`) are generic and remain. See task 1704 / [ADR 0105](../adr/<redacted>.md).
|
|
17
|
+
- **No prod topology** is referenced: the database is a local container, the credentials are local demo values, and the app reaches Postgres over TCP via `PG*` env (see `docker-compose.yml`).
|
|
18
|
+
|
|
19
|
+
To stop and wipe: `docker compose down -v` (the `-v` drops the `cloudbongos-db` volume).
|
|
20
|
+
|
|
21
|
+
## Branding / configuring your instance
|
|
22
|
+
|
|
23
|
+
The image is intentionally vanilla. To make it yours, supply your own config at runtime by mounting it over the build:
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
# docker-compose.override.yml
|
|
27
|
+
services:
|
|
28
|
+
app:
|
|
29
|
+
volumes:
|
|
30
|
+
- ./config/branding.json:/app/config/branding.json:ro
|
|
31
|
+
- ./config/modules.json:/app/config/modules.json:ro
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Author `config/branding.json` from the neutral starter — see [the branding contract](../branding-contract.md) and [`docs/branding-fill-prompt.md`](../branding-fill-prompt.md). Choose which features to enable in `config/modules.json` — see [the module contract](../modules-contract.md). Both resolve **over** the neutral starters, so you only specify what differs.
|
|
35
|
+
|
|
36
|
+
**Or scaffold it with `bongos init`** ([task #1204](https://example.com/builders#/task/1204)): a short interview (or `bongos init --from spec.json` for a hands-free / CI run) that writes both config files, **seeds your first version + its done-when goal**, and **files the human-only kickoff steps** (register a GitHub OAuth app, first owner sign-in, repo binding, admission) as real tracked tasks — so a fresh instance has a claimable queue on day one instead of an empty hall. It never invents your branding (it points you at the fill prompt for that). Preview the whole plan with `bongos init --dry-run`.
|
|
37
|
+
|
|
38
|
+
**Production hosting, optional (the `provisioning` module — [ADR 0111](../adr/<redacted>.md) §3).** If you enable the `provisioning` module and answer the interview's hosting questions (shape — co-tenant `$0` or a dedicated droplet — bring-your-own domain, credential ref, tier), init turns those answers into a real **provisioning request** (a queued `provision` intent the control-plane runner drains) instead of only filing a manual "production topology" task. The two irreducibly-human legs — the GitHub OAuth app and the first owner sign-in — stay guided/manual. If the module isn't enabled on the target instance, init falls back to the manual production-topology task, so nothing is silently skipped.
|
|
39
|
+
|
|
40
|
+
## Configuration surface
|
|
41
|
+
|
|
42
|
+
| Env var | Meaning | Compose default |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `PGHOST` / `PGPORT` / `PGUSER` / `PGPASSWORD` / `PGDATABASE` | Postgres connection (read by both the app pool and the migration runner) | the local `db` service |
|
|
45
|
+
| `HOST` / `PORT` | bind address inside the container | `0.0.0.0` / `3000` |
|
|
46
|
+
| `MEDUSA_GDS_ONLY` | `1` = hard force-skip the OTB **instance-seed** migrations (`migrations/instance/`) — belt-and-suspenders over the default. A vanilla instance never wants OTB's versions/goals/criteria (task 1704 / [ADR 0105](../adr/<redacted>.md)). | `1` |
|
|
47
|
+
| `GDS_APPLY_INSTANCE_SEEDS` | `1` = opt IN to applying the bundled OTB instance-seed migrations. Default (unset) = **skip** — so a self-host never inherits OTB scope-truth. Only the owning instance sets this, and only when rebuilding its DB from scratch (DR). | unset |
|
|
48
|
+
| `CLOUDBONGOS_PUBLIC_ORIGIN` | public origin for OAuth callbacks etc. | `http://localhost:3000` |
|
|
49
|
+
|
|
50
|
+
(The env prefix is the instance's `envPrefix` from its branding pack — `CLOUDBONGOS` for vanilla.)
|
|
51
|
+
|
|
52
|
+
## What the image contains
|
|
53
|
+
|
|
54
|
+
- `node src/platform-server.js` — the GDS-only entrypoint (no Colyseus, no game rooms, no game assets).
|
|
55
|
+
- `postgresql-client` (for `scripts/migrate.sh`) + `tini` as PID 1.
|
|
56
|
+
- Runs as the unprivileged `node` user; a `HEALTHCHECK` polls `/healthz`.
|
|
57
|
+
|
|
58
|
+
## Production notes
|
|
59
|
+
|
|
60
|
+
For a real deployment, put a TLS-terminating reverse proxy (Caddy/Cloudflare/nginx) in front, point `CLOUDBONGOS_PUBLIC_ORIGIN` (and the builders/status origins) at your domain, and use managed or backed-up Postgres rather than the bundled container volume. The bundled `db` service is for a self-contained local instance, not a production database.
|