@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,208 @@
|
|
|
1
|
+
# 0012 — Ground-object cell split: terrain becomes ground + sparse object layer
|
|
2
|
+
|
|
3
|
+
- **Status:** Accepted
|
|
4
|
+
- **Date:** 2026-05-09
|
|
5
|
+
- **Deciders:** Lars
|
|
6
|
+
- **Supersedes (in part):** [ADR 0011](./0011-terrain-id-rendering-model.md) — extends its data model; the dispatched render-strategies architecture stays valid.
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
[ADR 0011](./0011-terrain-id-rendering-model.md) established that each
|
|
11
|
+
map cell stores a TERRAIN id and the renderer dispatches per terrain to
|
|
12
|
+
a render strategy (`single` / `blob47` / `path16`). It worked, but the
|
|
13
|
+
first browser session uncovered a structural bug: the V1 top band has
|
|
14
|
+
GRASS, SAND, and ROCK randomly intermixed (1/11 rock, 3/11 sand,
|
|
15
|
+
7/11 grass), and the autotile picker — which checks `n === my` for
|
|
16
|
+
each neighbor — treated rocks and sand as "different from grass" the
|
|
17
|
+
same way. Every grass cell with a rock neighbor rendered a boundary
|
|
18
|
+
tile, even though a rock isn't a kind of land — it's a thing sitting
|
|
19
|
+
on land. The result was a marble-flagstone appearance instead of the
|
|
20
|
+
intended meadow.
|
|
21
|
+
|
|
22
|
+
A scoped fix (per-terrain `interiorEquivalents` to mark "rocks count
|
|
23
|
+
as same-as-grass for the picker," option B in the scoping note) would
|
|
24
|
+
have removed the artifact in ~12 LOC. We chose to pay down the deeper
|
|
25
|
+
debt instead, because:
|
|
26
|
+
|
|
27
|
+
1. The wider problem is conflation: a single terrain id at every cell
|
|
28
|
+
tries to mean both "what's the visual surface here" AND "what's
|
|
29
|
+
blocking movement here." That conflation breaks at any cell whose
|
|
30
|
+
surface differs from its overlay (rocks on grass, containers on
|
|
31
|
+
sand, future trees / fences / signs / item drops on whatever).
|
|
32
|
+
2. The world is about to grow. Doing the architectural split now,
|
|
33
|
+
while the map is small and entirely procedural, costs ~2 hours.
|
|
34
|
+
Doing it later, after we've baked the assumption into level data,
|
|
35
|
+
gameplay events, and persistence, costs much more.
|
|
36
|
+
3. Industry-standard tile renderers (Tiled, RPG Maker, FireRed itself)
|
|
37
|
+
separate ground tiles from object overlays. Aligning with that
|
|
38
|
+
convention makes future contributions cheaper.
|
|
39
|
+
|
|
40
|
+
## Decision
|
|
41
|
+
|
|
42
|
+
Each cell carries TWO independent pieces of data:
|
|
43
|
+
|
|
44
|
+
- **Ground terrain** — always defined. Drives the autotile renderer.
|
|
45
|
+
Walkable unless declared in `BLOCKING_TERRAINS`. The set is small
|
|
46
|
+
and stable: `GRASS`, `SAND`, `SEA`, `MARBLE_PATH`. Future additions
|
|
47
|
+
are alternative ground types.
|
|
48
|
+
- **Object** — optional (zero or one per cell in V1; lists in V2 if
|
|
49
|
+
needed). Painted in a second draw pass at depth 1. May block
|
|
50
|
+
movement (`BLOCKING_OBJECTS`). Currently: `ROCK` plus the 8
|
|
51
|
+
`CONTAINER_PANEL_*` ids that compose the shipping container.
|
|
52
|
+
|
|
53
|
+
`INITIAL_MAP` exports `{ ground, objects }` — two parallel 2D arrays.
|
|
54
|
+
Both client (`public/game/world/map.js`) and server (`src/world/map.js`)
|
|
55
|
+
build them with identical logic. The shape is JSON-serializable for
|
|
56
|
+
the eventual move to a Postgres-backed map.
|
|
57
|
+
|
|
58
|
+
The autotile picker (`pickAutotileIndex` in
|
|
59
|
+
[`public/game/world/terrain.js`](../../public/game/world/terrain.js))
|
|
60
|
+
takes the ground grid only. Objects never enter its view. That is the
|
|
61
|
+
core invariant that fixes the marble-flagstone artifact: a grass cell
|
|
62
|
+
with a rock object on top is, to the picker, just a grass cell — its
|
|
63
|
+
neighbors are ground terrains too, and only sand neighbors at the
|
|
64
|
+
y=6 transition trigger the autotile boundary tile.
|
|
65
|
+
|
|
66
|
+
### Render pipeline
|
|
67
|
+
|
|
68
|
+
`WorldScene.drawMap(map)` runs two passes:
|
|
69
|
+
|
|
70
|
+
1. **Ground pass.** For every cell, paint
|
|
71
|
+
`pickGroundTextureKey(scene, map.ground, x, y)` at depth 0. Uses the
|
|
72
|
+
autotile dispatch from ADR 0011.
|
|
73
|
+
2. **Object pass.** For every cell where `map.objects[y][x]`, paint
|
|
74
|
+
`pickObjectTextureKey(scene, map.objects, x, y)` at depth 1. Single-
|
|
75
|
+
tile per object id; no autotile dispatch on the object layer.
|
|
76
|
+
|
|
77
|
+
Vendor and player sprites continue to live at higher depths (8 and 10
|
|
78
|
+
respectively) above objects. The vendor at (13, 9) sits visually atop
|
|
79
|
+
the door panel object, exactly as before.
|
|
80
|
+
|
|
81
|
+
### Walkability
|
|
82
|
+
|
|
83
|
+
`isBlocked(x, y)`:
|
|
84
|
+
```
|
|
85
|
+
out-of-bounds → blocked
|
|
86
|
+
ground in BLOCKING_TERRAINS → blocked (SEA only, in V1)
|
|
87
|
+
object in BLOCKING_OBJECTS → blocked (ROCK + 8 container panels, in V1)
|
|
88
|
+
otherwise → walkable
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Server (`src/world/map.js`) is the source of truth for movement
|
|
92
|
+
validation. Client honors the same rule for prediction. Both read from
|
|
93
|
+
the same shared `terrain.js` enums + sets. Tests in
|
|
94
|
+
[`tests/walkability.mjs`](../../tests/walkability.mjs) exercise the
|
|
95
|
+
server module directly to guard against drift.
|
|
96
|
+
|
|
97
|
+
### Asset implications
|
|
98
|
+
|
|
99
|
+
- `rock_small.png` (AI-generated, currently RGB no-alpha): renders
|
|
100
|
+
opaquely on top of the ground autotile. Acceptable for V1 — the rock
|
|
101
|
+
visually fills its cell, identical to the pre-split look. The win
|
|
102
|
+
is in the surrounding GRASS cells, which now render smooth meadow
|
|
103
|
+
instead of marble-flagstone borders. Future polish: regenerate with
|
|
104
|
+
magenta-key transparent BG so the autotiled grass shows through at
|
|
105
|
+
the rock's corners (~$0.04). Not blocking V1.
|
|
106
|
+
- The procedural rock fallback in [`tilePalette.js`](../../public/game/world/tilePalette.js)
|
|
107
|
+
was updated to drop its grass-green BG fillRect — the canvas is
|
|
108
|
+
transparent by default, so the procedural rock now correctly shows
|
|
109
|
+
the underlying ground at corners.
|
|
110
|
+
- Container panels: stay opaque. The container is a solid building
|
|
111
|
+
covering its 8 cells of sand. Opaque is correct.
|
|
112
|
+
|
|
113
|
+
### Cross-verify safety
|
|
114
|
+
|
|
115
|
+
The Python↔JS autotile lookup table cross-verifier
|
|
116
|
+
([`tests/autotile_xverify.mjs`](../../tests/autotile_xverify.mjs))
|
|
117
|
+
tests `selectBlob47` / `selectPath16` directly — unchanged by this
|
|
118
|
+
ADR. Picker behavior change is captured in the new
|
|
119
|
+
[`tests/terrain_picker.mjs`](../../tests/terrain_picker.mjs), which
|
|
120
|
+
asserts the ground-only invariant.
|
|
121
|
+
|
|
122
|
+
## Consequences
|
|
123
|
+
|
|
124
|
+
### Positive
|
|
125
|
+
|
|
126
|
+
- **The marble-flagstone bug is gone by construction.** The picker
|
|
127
|
+
cannot see objects, so rocks (and any future overlays) cannot
|
|
128
|
+
pollute boundary tile selection.
|
|
129
|
+
- **Clean walkability.** Movement rules read like the intent: "is the
|
|
130
|
+
ground impassable, OR is the object impassable?" No more entanglement
|
|
131
|
+
between visual identity and blocking.
|
|
132
|
+
- **Future objects are nearly free.** Trees, signs, fences, item
|
|
133
|
+
drops, multi-tile structures all slot in as new `OBJECT` enum
|
|
134
|
+
entries + manifest tile + (if blocking) `BLOCKING_OBJECTS` entry.
|
|
135
|
+
No renderer changes per addition.
|
|
136
|
+
- **Container scales.** Adding a second container, a market stall, a
|
|
137
|
+
multi-cell tent — all just place more object-cell sets. The picker
|
|
138
|
+
paints clean ground around each.
|
|
139
|
+
- **Persistence-ready data shape.** `objects[y][x]` maps directly to
|
|
140
|
+
a `(x, y, object_id)` table when player-placed objects need to
|
|
141
|
+
persist. `ground[y][x]` maps to a separate ground table that
|
|
142
|
+
rarely changes.
|
|
143
|
+
- **Aligned with industry convention.** Tiled, RPG Maker, FireRed all
|
|
144
|
+
use ground + object layers. Future contributors recognize the model.
|
|
145
|
+
|
|
146
|
+
### Negative / costs
|
|
147
|
+
|
|
148
|
+
- **Two-file mirror tax doubles** — now `terrain.js` AND `map.js` each
|
|
149
|
+
exist as CJS server + ESM client twins (4 files). Same fix as before:
|
|
150
|
+
consolidate when the world becomes data-driven from Postgres.
|
|
151
|
+
- **Container is 8 distinct object ids** rather than an anchor + 2×4
|
|
152
|
+
footprint. Per-cell is simpler for V1; anchor-based becomes
|
|
153
|
+
attractive when we have many multi-tile structures (V2+).
|
|
154
|
+
- **Z-order between objects is V1-flat** — every object renders at
|
|
155
|
+
depth 1. A future "tall object in front of player" effect needs
|
|
156
|
+
per-object depth-sort by `(y + footprint_height)`. Not urgent.
|
|
157
|
+
- **Per-cell object limit is one** in V1. A flower next to a sign in
|
|
158
|
+
the same cell would need `objects[y][x]: string[]`. Trivial to lift
|
|
159
|
+
when needed.
|
|
160
|
+
|
|
161
|
+
### What this does not change
|
|
162
|
+
|
|
163
|
+
- ADR 0011's dispatched render strategies (`single` / `blob47` /
|
|
164
|
+
`path16`) are unchanged. They now operate on the GROUND grid only.
|
|
165
|
+
- The autotile pipeline (ADR 0009) and the family pipeline (ADR 0008)
|
|
166
|
+
are unchanged. Container panels are still generated by the family
|
|
167
|
+
pipeline; their PNGs are interpreted as object overlays now.
|
|
168
|
+
- Vendor placement, dialog, interact semantics: unchanged. The vendor
|
|
169
|
+
at (13, 9) still occupies the door cell. The cell is still blocked
|
|
170
|
+
(now via object-blocking, was previously via terrain-blocking).
|
|
171
|
+
- The hardcoded V1 map geometry: unchanged. The container is still 4
|
|
172
|
+
wide × 2 tall at anchor (13, 8); rocks scatter on the same noise
|
|
173
|
+
function.
|
|
174
|
+
- Cost ledger and budget rules: unchanged.
|
|
175
|
+
|
|
176
|
+
## Migration path
|
|
177
|
+
|
|
178
|
+
Single commit, atomic switch. Server and client move together. The
|
|
179
|
+
`players` table has no terrain references (only x/y/facing); the
|
|
180
|
+
`world_events` table has no terrain references in payloads; nothing
|
|
181
|
+
external needs migrating. The Colyseus smoke tests in `/tmp/colyseus-*`
|
|
182
|
+
still validate movement against the same `isBlocked()` API surface.
|
|
183
|
+
|
|
184
|
+
## Testing
|
|
185
|
+
|
|
186
|
+
- [`tests/terrain_picker.mjs`](../../tests/terrain_picker.mjs) (10
|
|
187
|
+
cases) — picker dispatch shape, neighbor lookup, ground-only
|
|
188
|
+
invariant, path16 sanity (lone node = 0; cross junction = 15).
|
|
189
|
+
- [`tests/walkability.mjs`](../../tests/walkability.mjs) (13 cases) —
|
|
190
|
+
enum sanity, isBlocking{Terrain,Object}, isBlocked over the actual
|
|
191
|
+
INITIAL_MAP for sea / sand / grass / rock-on-grass / all 8 container
|
|
192
|
+
cells / vendor cell / cell south of vendor / out-of-bounds.
|
|
193
|
+
- Both wired into `art/pipeline/smoke_test.sh` step 3b. The smoke test
|
|
194
|
+
fails the build if either test fails.
|
|
195
|
+
|
|
196
|
+
## Future work this enables
|
|
197
|
+
|
|
198
|
+
- **Trees** (decorative, blocking): one OBJECT entry + tile.
|
|
199
|
+
- **Signs** (interactive, blocking, dialog payload): OBJECT entry +
|
|
200
|
+
tile + a small `INTERACTIONS` map keyed by `(x, y)` consumed by
|
|
201
|
+
`WorldScene.handleInteract`.
|
|
202
|
+
- **Item drops** (non-blocking, pickable): OBJECT entry + tile,
|
|
203
|
+
exclude from `BLOCKING_OBJECTS`. Pickup is a server event that
|
|
204
|
+
mutates `objects[y][x] = null` and broadcasts.
|
|
205
|
+
- **Multiple buildings / placed objects**: just place more
|
|
206
|
+
object-cell sets. Ground autotile renders cleanly around them.
|
|
207
|
+
- **Persistent player-placed objects**: `objects` grid is the natural
|
|
208
|
+
persistence shape (`(x, y, object_id)`).
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# 0013 — Paths as object overlays with autotile dispatch
|
|
2
|
+
|
|
3
|
+
- **Status:** Accepted
|
|
4
|
+
- **Date:** 2026-05-10
|
|
5
|
+
- **Deciders:** Lars
|
|
6
|
+
- **Extends:** [ADR 0012](./<redacted>.md) (cell model), [ADR 0011](./0011-terrain-id-rendering-model.md) (render dispatch), [ADR 0009](./0009-autotile-architecture.md) (autotile families)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
The V1 world places a marble flagstone path running 4 cells north-to-south
|
|
11
|
+
through the sand band (cells `(13, 10..13)`). Up until now the path was
|
|
12
|
+
declared as a **ground terrain** (`TERRAIN.MARBLE_PATH`) with a `path16`
|
|
13
|
+
render strategy. The `marble_path` autotile family was generated with
|
|
14
|
+
three primitives: `path_terrain` (the surrounding ground texture), `path_node`
|
|
15
|
+
(centered marble cluster), and `path_arm_N` (vertical strip of marble).
|
|
16
|
+
Each composed tile was an opaque RGB image — the path arms and node
|
|
17
|
+
pasted onto a `path_terrain` background that filled the whole 32×32.
|
|
18
|
+
|
|
19
|
+
That model has two structural problems:
|
|
20
|
+
|
|
21
|
+
1. **Terrain mismatch.** The composed path tiles include their own
|
|
22
|
+
`path_terrain` margins. The V1 world places the path over `SAND`, but
|
|
23
|
+
the family was designed for paths through grass (per the prompt). The
|
|
24
|
+
path tiles' margins read as grass, the surrounding world ground reads
|
|
25
|
+
as sand → visible color discontinuity at every path cell's edge,
|
|
26
|
+
which Lars correctly described as "visible gaps showing through."
|
|
27
|
+
2. **Combinatorial family explosion.** If V2 adds paths that run through
|
|
28
|
+
grass *and* paths through marble plazas *and* paths through cobble,
|
|
29
|
+
each pairing needs its own family — `marble_path_on_sand`,
|
|
30
|
+
`marble_path_on_grass`, etc. The number of families is `paths × grounds`,
|
|
31
|
+
which doesn't scale.
|
|
32
|
+
|
|
33
|
+
ADR 0012's whole point was that **objects are overlays on top of ground**,
|
|
34
|
+
free from polluting ground rendering. That model fits paths perfectly —
|
|
35
|
+
a path is a thing you walk on top of the ground, not a kind of ground.
|
|
36
|
+
But ADR 0012 limited objects to single-tile rendering, which doesn't
|
|
37
|
+
support the autotile dispatch a path needs to pick the right
|
|
38
|
+
straight/junction/end-cap tile based on its neighbors.
|
|
39
|
+
|
|
40
|
+
## Decision
|
|
41
|
+
|
|
42
|
+
**Paths become objects with autotile dispatch.** Specifically:
|
|
43
|
+
|
|
44
|
+
- A new object id `OBJECT.PATH_MARBLE` (declared on the OBJECT enum,
|
|
45
|
+
added to neither `BLOCKING_OBJECTS` nor `BLOCKING_TERRAINS` — a path is
|
|
46
|
+
walkable). The world places the path on the **objects** layer; the
|
|
47
|
+
ground at those cells is `SAND` (just like the surrounding cells).
|
|
48
|
+
- `OBJECT_RENDER` extends from `{ tile }` only to the same dispatch
|
|
49
|
+
shape that `TERRAIN_RENDER` already supports:
|
|
50
|
+
`{ strategy: 'single' | 'path16' | 'blob47', family, fallbackTile }`.
|
|
51
|
+
Single-tile is preserved for back-compat (legacy short-form `{ tile }`
|
|
52
|
+
still accepted, normalized internally).
|
|
53
|
+
- A new `pickObjectAutotileIndex(object, neighbors)` mirrors the existing
|
|
54
|
+
`pickAutotileIndex(terrain, neighbors)` — same dispatch logic, looks up
|
|
55
|
+
in `OBJECT_RENDER` instead of `TERRAIN_RENDER`. The picker queries the
|
|
56
|
+
**objects** grid for neighbors of the same object id. (`neighborsAt`
|
|
57
|
+
itself is unchanged — already generic over any 2D grid.)
|
|
58
|
+
- The `marble_path` autotile family drops the `path_terrain` primitive
|
|
59
|
+
entirely. Its tiles are now produced as **RGBA with alpha-keyed
|
|
60
|
+
backgrounds**: the marble flagstones are opaque, everything else is
|
|
61
|
+
transparent. The world's ground tile is painted first (depth 0); the
|
|
62
|
+
path tile renders on top (depth 1). The surrounding sand-or-grass-or-
|
|
63
|
+
whatever shows through wherever the marble doesn't cover.
|
|
64
|
+
- A new `kind='alpha_tile'` in `post_process.process()` does explicit
|
|
65
|
+
magenta-key transparency removal *before* palette quantization (the
|
|
66
|
+
locked palette doesn't contain pure `#FF00FF`, so magenta would
|
|
67
|
+
otherwise palette-snap to a near-purple and dodge the threshold). The
|
|
68
|
+
autotile orchestrator routes primitives with `transparent_bg: true`
|
|
69
|
+
to this kind.
|
|
70
|
+
- `compose_path16` in `autotile_compositor.py` defaults to a transparent
|
|
71
|
+
RGBA canvas when no `terrain` primitive is present. Legacy families
|
|
72
|
+
that still ship a terrain primitive get the old opaque behavior.
|
|
73
|
+
- `family_checks.color_profile_check` masks alpha=0 pixels out of the
|
|
74
|
+
in-range fraction so transparent regions don't skew the score.
|
|
75
|
+
|
|
76
|
+
The runtime renderer is unchanged in shape: `WorldScene.drawMap` still
|
|
77
|
+
does ground pass + object pass. Phaser's `add.image` blits RGBA natively;
|
|
78
|
+
the alpha pixels just don't paint over the ground that's already there.
|
|
79
|
+
|
|
80
|
+
## Consequences
|
|
81
|
+
|
|
82
|
+
**Paths are now terrain-agnostic.** The same `marble_path` family works
|
|
83
|
+
over sand, grass, marble plazas, and any future ground. The V1 world's
|
|
84
|
+
path strip renders correctly — sand shows through where the marble
|
|
85
|
+
doesn't cover, no gaps, no color mismatch.
|
|
86
|
+
|
|
87
|
+
**Object-layer autotile dispatch is now a first-class pattern.** Future
|
|
88
|
+
linear or regional overlays (fences, low walls, rivers, trails, footpaths
|
|
89
|
+
in dirt, bridges, vine borders) reuse this without further architectural
|
|
90
|
+
work. Pick `path16` for line connections, `blob47` for region overlays.
|
|
91
|
+
|
|
92
|
+
**The cell model stays at two layers.** This is *not* a layer-count
|
|
93
|
+
expansion. Ground is the always-defined surface; object is the optional
|
|
94
|
+
overlay. Both layers can autotile-dispatch — the dispatch generalizes,
|
|
95
|
+
not the cell shape.
|
|
96
|
+
|
|
97
|
+
**`MARBLE_PATH` ground terrain is now vestigial.** It's declared and its
|
|
98
|
+
`TERRAIN_RENDER` entry remains for back-compat, but `INITIAL_MAP` no
|
|
99
|
+
longer places it. A future cleanup task can remove the enum entry once
|
|
100
|
+
no other code references it; not urgent.
|
|
101
|
+
|
|
102
|
+
**The walkability test grew by 1 case** (the path strip is walkable
|
|
103
|
+
across all 4 cells) and the existing `(13, 10) is sand` assertion
|
|
104
|
+
loosened to require `ground = SAND, object = PATH_MARBLE` instead of
|
|
105
|
+
`ground = MARBLE_PATH, object = null`. `terrain_picker.mjs` gained 4
|
|
106
|
+
cases covering object-layer autotile dispatch — including the
|
|
107
|
+
**OBJECT-LAYER AUTOTILE INVARIANT** mirror of ADR 0012's ground invariant
|
|
108
|
+
(object autotile sees only the object grid; ground never affects it).
|
|
109
|
+
|
|
110
|
+
**Alpha rendering has a known generation cost.** Each new alpha-keyed
|
|
111
|
+
family needs primitives generated with magenta-key backdrops. The model
|
|
112
|
+
needs explicit instruction to use `#FF00FF` solid backgrounds; in
|
|
113
|
+
practice the family pipeline's color profile gate caught the path_node
|
|
114
|
+
at 39% in-range (1pt below the 40% threshold) on retry, but accepted
|
|
115
|
+
best-effort because the gate is WARN-not-block in V1. Future iteration
|
|
116
|
+
can hard-block on color once the pipeline reliably hits ≥80%.
|
|
117
|
+
|
|
118
|
+
## Alternatives considered
|
|
119
|
+
|
|
120
|
+
**Option A — Pragmatic regen of `marble_path.path_terrain` to be sand.**
|
|
121
|
+
~$0.08 of generation work. Visible problem disappears for V1. But binds
|
|
122
|
+
the family to one underlying terrain forever — the moment a path needs
|
|
123
|
+
to run through grass, this model breaks again. We chose the architectural
|
|
124
|
+
fix because the explicit goal of this stress-test session is improving
|
|
125
|
+
the building architecture, not patching surface symptoms.
|
|
126
|
+
|
|
127
|
+
**Option B — Multi-layer ground cells.** Instead of two layers (ground
|
|
128
|
+
+ object), let ground itself be a stack: `[sand, marble_path]` for path
|
|
129
|
+
cells. Cleaner conceptually for "path on top of ground" framing, but a
|
|
130
|
+
much larger schema change — affects every consumer of `INITIAL_MAP.ground`,
|
|
131
|
+
breaks the "ground is always one terrain" invariant ADR 0011 leans on,
|
|
132
|
+
and doesn't generalize beyond paths.
|
|
133
|
+
|
|
134
|
+
**Option C — Composite at preload.** Generate the full opaque path tile
|
|
135
|
+
at runtime by stitching `world_ground_tile + path_alpha_overlay` once
|
|
136
|
+
per cell when the world loads. Equivalent visual outcome to the chosen
|
|
137
|
+
approach, but does the compositing in JS (slow), per-cell (lots of
|
|
138
|
+
texture cache pressure), and at preload (delays first render). The
|
|
139
|
+
chosen approach offloads the compositing to the GPU at draw time, which
|
|
140
|
+
is what Phaser is already optimized for.
|
|
141
|
+
|
|
142
|
+
## Verification
|
|
143
|
+
|
|
144
|
+
- `tests/walkability.mjs` — 14/14 passing. New: PATH_MARBLE non-blocking;
|
|
145
|
+
4-cell strip walkable; ground=SAND object=PATH_MARBLE at the path cells.
|
|
146
|
+
- `tests/terrain_picker.mjs` — 14/14 passing. New: OBJECT_RENDER strategy
|
|
147
|
+
enumeration; `pickObjectAutotileIndex` dispatch correctness on
|
|
148
|
+
isolated, vertical-strip, top/bottom end-cap configurations; the
|
|
149
|
+
object-layer autotile invariant.
|
|
150
|
+
- `tests/autotile_xverify.mjs` — unchanged, still green (the JS↔Python
|
|
151
|
+
lookup tables didn't change; only the dispatch wrapper shifted).
|
|
152
|
+
- Visual: `/tmp/path-on-sand-preview.png` (rendered at session time)
|
|
153
|
+
shows a 4-tile vertical strip with marble flagstones running down the
|
|
154
|
+
center column and sand visible on left/right margins — no magenta, no
|
|
155
|
+
terrain mismatch, no gaps. The browser will reproduce this at runtime.
|
|
156
|
+
- The `_magenta_mask` detector runs before palette quantization, on raw
|
|
157
|
+
model output, with threshold `R>180 ∧ G<80 ∧ B>140` (caught 61% of
|
|
158
|
+
pixels in `path_node`, 33% in `path_arm_N`).
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# 0014 — `families.json` is canonical over `vocabulary.json` for any shared id
|
|
2
|
+
|
|
3
|
+
- **Status:** Accepted
|
|
4
|
+
- **Date:** 2026-05-11
|
|
5
|
+
- **Deciders:** Lars
|
|
6
|
+
- **Track:** `internal` (art pipeline)
|
|
7
|
+
- **Extends:** [ADR 0008-a](./<redacted>.md) (family-based tile generation), [ADR 0009](./0009-autotile-architecture.md) (autotile architecture)
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
The pixel-art pipeline grew in two phases:
|
|
12
|
+
|
|
13
|
+
1. **Phase 0** seeded `art/template/vocabulary.json`. Each entry is one
|
|
14
|
+
atomic tile or sprite, generated one-at-a-time, scored against the
|
|
15
|
+
per-tile rubric.
|
|
16
|
+
2. **Phase 1+** introduced `art/template/families.json`. A family is a
|
|
17
|
+
*group* of related members (a player spritesheet, the 8 container
|
|
18
|
+
panels, an autotile family). Families carry richer metadata: edge
|
|
19
|
+
contracts, color profiles, member kinds, anchor refinement,
|
|
20
|
+
deterministic checks, layout cell coordinates, sliceable strategies.
|
|
21
|
+
|
|
22
|
+
Both files coexisted while families were being migrated from per-tile
|
|
23
|
+
generation. That migration is now far enough along that several ids
|
|
24
|
+
appear in *both* files:
|
|
25
|
+
|
|
26
|
+
- `player_down_idle`, `player_up_idle`, `player_left_idle`,
|
|
27
|
+
`player_right_idle` — vocab + `player_character` family members
|
|
28
|
+
- `rock_small` — vocab + `rock` family member
|
|
29
|
+
- `vendor_hyperion` — vocab id + `vendor_hyperion` family id (whose
|
|
30
|
+
members are `vendor_hyperion_idle` / `..._talk`)
|
|
31
|
+
- `marble_path` — vocab id + autotile family id
|
|
32
|
+
|
|
33
|
+
Duplication has two failure modes:
|
|
34
|
+
1. **Drift.** A descriptor or `game_key` updated in one file but not
|
|
35
|
+
the other. Whichever file the running pipeline reads from "wins"
|
|
36
|
+
silently; the other becomes stale.
|
|
37
|
+
2. **Double-publish.** `build_tilesheet.py` writes every vocab entry
|
|
38
|
+
then every family member. Same id from both sources overwrites the
|
|
39
|
+
manifest entry twice — order-dependent, fragile.
|
|
40
|
+
|
|
41
|
+
We need one canonical source for any id that has both representations.
|
|
42
|
+
|
|
43
|
+
## Decision
|
|
44
|
+
|
|
45
|
+
**We will treat `families.json` as the canonical source for any id that
|
|
46
|
+
appears in both files.** `vocabulary.json` is reserved for legacy
|
|
47
|
+
per-tile entries that are *not* covered by any family — atomic singletons
|
|
48
|
+
from Phase 0 (e.g. `amphora`, `column_base`, `olive_tree`) that have not
|
|
49
|
+
yet been migrated to a family and may never need to be.
|
|
50
|
+
|
|
51
|
+
Concretely:
|
|
52
|
+
|
|
53
|
+
1. Vocabulary entries whose `id` matches any of (a) a family id,
|
|
54
|
+
(b) a family member id, or (c) an autotile family id are **removed**
|
|
55
|
+
from `vocabulary.json`. As of GDS [#139](https://example.com/builders#/task/139) that's 7 entries:
|
|
56
|
+
`marble_path`, `player_{down,up,left,right}_idle`, `rock_small`,
|
|
57
|
+
`vendor_hyperion`.
|
|
58
|
+
2. `build_tilesheet.py` builds the set of "family-owned" ids at the top
|
|
59
|
+
of `main()` and silently skips any vocab entry whose id is in that
|
|
60
|
+
set. This is defense in depth — even if a future edit re-introduces
|
|
61
|
+
an overlapping vocab entry, families.json wins by construction.
|
|
62
|
+
3. Future migrations (e.g. `amphora` → an amphora family) follow the
|
|
63
|
+
same pattern: add the family entry to `families.json`, then remove
|
|
64
|
+
the now-redundant entry from `vocabulary.json` in the same change.
|
|
65
|
+
4. `vocabulary.json`'s `_comment` field documents this canon rule and
|
|
66
|
+
points back at this ADR.
|
|
67
|
+
|
|
68
|
+
## Alternatives considered
|
|
69
|
+
|
|
70
|
+
- **Merge both files into one `assets.json`.** Cleaner long-term but
|
|
71
|
+
the rubric / schema / orchestrator code-paths are different enough
|
|
72
|
+
(per-tile review vs. family review with deterministic gates) that
|
|
73
|
+
merging now would invite churn. Defer until Phase 0 is fully drained.
|
|
74
|
+
- **Keep both files, prefer vocabulary.json when both define an id.**
|
|
75
|
+
Backwards but symmetrical. Rejected because families.json carries
|
|
76
|
+
strictly more metadata — the deterministic checks, color profiles,
|
|
77
|
+
and edge contracts are not expressible in the vocabulary schema, so
|
|
78
|
+
preferring vocabulary would be a regression in fidelity.
|
|
79
|
+
- **Auto-generate vocabulary.json from families.json at build time.**
|
|
80
|
+
Possible but introduces a generated-file invariant we'd have to
|
|
81
|
+
guard in CI. The remaining 16 vocab-only entries don't justify the
|
|
82
|
+
tooling cost yet.
|
|
83
|
+
|
|
84
|
+
## Consequences
|
|
85
|
+
|
|
86
|
+
- **One file owns each id.** No more drift between two
|
|
87
|
+
descriptors for the same sprite.
|
|
88
|
+
- **Per-tile pipeline still works** for legacy entries — Phase 0
|
|
89
|
+
outputs continue to land at `art/generated/tiles/<id>.png` and get
|
|
90
|
+
published by the vocabulary loop. Nothing about the orchestrator
|
|
91
|
+
changes.
|
|
92
|
+
- **build_tilesheet.py is monotone:** for any given manifest id, exactly
|
|
93
|
+
one publishing pass writes it. The order of (vocab pass → family pass
|
|
94
|
+
→ autotile pass) is no longer load-bearing, because the vocab pass
|
|
95
|
+
skips family-owned ids up front.
|
|
96
|
+
- **Migration motion is mechanical.** Promoting a vocab entry to a
|
|
97
|
+
family: add the family, remove the vocab entry, regenerate. The
|
|
98
|
+
scanner / smoke tests catch any regression at the manifest level.
|
|
99
|
+
- **No game-side change.** Both `key` (vocab) and `game_key` (family)
|
|
100
|
+
resolve to the same texture-key conventions used by Player.js /
|
|
101
|
+
vendorSprite.js / tilePalette.js. The texture keys the game asks
|
|
102
|
+
for (`player_down`, `vendor_idle`, `tex_rock_small`, etc.) are all
|
|
103
|
+
still defined in the manifest after the dedup.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# ADR 0015 — Task dependencies + auto-promotion
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-05-17
|
|
4
|
+
**Context:** GDS-V3, task [#309](https://example.com/builders#/task/309) (V3.R02 — Task dependencies + auto-promotion system).
|
|
5
|
+
**Status:** Accepted.
|
|
6
|
+
|
|
7
|
+
## Problem
|
|
8
|
+
|
|
9
|
+
The GDS has a `tasks` table with a `status` column and a `priority` column, plus a `V<ver>.R##` rank prefix encoded in the title. Planning Session `#1` (2026-05-12) used the rank prefix as the "order to ship things in." But the system had no machinery to enforce that order:
|
|
10
|
+
|
|
11
|
+
- Every new task lands in `status='backlog'`.
|
|
12
|
+
- A task can only be claimed when `status='ready'`.
|
|
13
|
+
- `backlog → ready` only flips via manual `POST /tasks/:id/promote`. There is no auto-promotion rule.
|
|
14
|
+
- So the rank prefix was decorative — execution order was whatever happened to be promoted, which in practice meant "whatever was already `ready` from a previous version."
|
|
15
|
+
|
|
16
|
+
Lars hit this on 2026-05-17: he wanted to claim the top-rank GDS-V3 task and the API offered him one option (V3.R18) — the only `ready` task — when the ranking implied he should be working on V3.R02.
|
|
17
|
+
|
|
18
|
+
We needed three things:
|
|
19
|
+
|
|
20
|
+
1. **A way to declare "task A must wait for task B."**
|
|
21
|
+
2. **A rule that promotes tasks automatically as their dependencies ship**, so the queue self-feeds.
|
|
22
|
+
3. **A claim-time guard** so a task can't be worked while its deps are still open, even if it ended up `ready` manually.
|
|
23
|
+
|
|
24
|
+
## Decision
|
|
25
|
+
|
|
26
|
+
Add a `task_dependencies` join table, a `tasks` UPDATE trigger that auto-promotes dependents on ship, a claim-time check that refuses `DEPS_NOT_SHIPPED`, and an API surface for managing deps.
|
|
27
|
+
|
|
28
|
+
### Schema
|
|
29
|
+
|
|
30
|
+
```sql
|
|
31
|
+
CREATE TABLE task_dependencies (
|
|
32
|
+
task_id bigint NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
33
|
+
depends_on_task_id bigint NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
34
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
35
|
+
PRIMARY KEY (task_id, depends_on_task_id),
|
|
36
|
+
CONSTRAINT no_self_dep CHECK (task_id <> depends_on_task_id)
|
|
37
|
+
);
|
|
38
|
+
CREATE INDEX idx_task_deps_task ON task_dependencies (task_id);
|
|
39
|
+
CREATE INDEX idx_task_deps_depends_on ON task_dependencies (depends_on_task_id);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Many-to-many. Cascade on delete because a task being removed orphans its edges. Self-deps are constrained out at the DB layer; cycles are checked at the application layer (recursive CTE in `addTaskDependency` / `setTaskDependencies`).
|
|
43
|
+
|
|
44
|
+
### Trigger
|
|
45
|
+
|
|
46
|
+
```sql
|
|
47
|
+
CREATE TRIGGER trg_promote_dependents_on_ship
|
|
48
|
+
AFTER UPDATE OF status ON tasks
|
|
49
|
+
FOR EACH ROW
|
|
50
|
+
EXECUTE FUNCTION promote_dependents_on_ship();
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The function fires when `NEW.status='shipped' AND OLD.status<>'shipped'`. It scans rows in `task_dependencies` where `depends_on_task_id = NEW.id`, and for each dependent task that is `backlog`, is NOT `kind='spike'`, and has zero remaining unshipped deps, flips it to `ready` and stamps `promoted_at`.
|
|
54
|
+
|
|
55
|
+
### Claim-time guard
|
|
56
|
+
|
|
57
|
+
`claimTask` in [src/bongos/db.js](../../src/bongos/db.js) checks `unshippedDependencies(taskId, client)` before inserting the claim row. If any dep is unshipped, throws `{ code: 'DEPS_NOT_SHIPPED', deps: [...] }`. The route handler maps that to HTTP 409, the CLI prints a clean error listing the blockers.
|
|
58
|
+
|
|
59
|
+
`claimTasksBatch` does the same check per-task but treats batch-internal deps as "OK" (the batch is worked serially).
|
|
60
|
+
|
|
61
|
+
### API surface
|
|
62
|
+
|
|
63
|
+
| Verb | Path | Body / returns |
|
|
64
|
+
|----------|-----------------------------------------------|----------------------------------------------------------|
|
|
65
|
+
| `GET` | `/api/gds/tasks/:id` | `task` now includes `dependencies[]` + `dependents[]` arrays |
|
|
66
|
+
| `GET` | `/api/gds/tasks/:id/dependencies` | `{ dependencies, dependents }` |
|
|
67
|
+
| `POST` | `/api/gds/tasks/:id/dependencies` | `{ depends_on_task_id }` or `{ depends_on_task_ids: [N,...] }` |
|
|
68
|
+
| `PUT` | `/api/gds/tasks/:id/dependencies` | `{ depends_on_task_ids: [N,...] }` — replaces full set |
|
|
69
|
+
| `DELETE` | `/api/gds/tasks/:id/dependencies/:depId` | removes one edge |
|
|
70
|
+
|
|
71
|
+
Error codes: `self_dep` (400), `task_not_found` (404), `cycle` (409 — returns the path).
|
|
72
|
+
|
|
73
|
+
### Spike convention
|
|
74
|
+
|
|
75
|
+
Spikes (`kind='spike'`) NEVER auto-promote. They sit in backlog until a power-user manually calls `POST /tasks/:id/promote`. This is the "ambiguity gate" — spikes produce new task definitions or ADRs whose outputs reshape downstream work; auto-flowing them would skip the human review that justifies the spike's existence.
|
|
76
|
+
|
|
77
|
+
Non-spike tasks (`feature`, `bug`, `infra`, `cleanup`, `refactor`, `learning-capture`, `decision`, `blocker-resolution`, `unclassified`) auto-promote.
|
|
78
|
+
|
|
79
|
+
### Rank renumbering
|
|
80
|
+
|
|
81
|
+
The `V<ver>.R##` rank prefix is now a topological renumbering of the dep graph. For any A → deps → B, B's R## < A's R##. Tiebreaker: lower current R## (preserves planning intent), then alphabetical. The rank is decorative — `dependencies[]` is load-bearing — but a topologically-sorted rank makes the queue display read true.
|
|
82
|
+
|
|
83
|
+
Migration 021 did the initial pass for GDS-V3: 86 dep edges inserted, 72 of 87 non-shipped tasks renumbered.
|
|
84
|
+
|
|
85
|
+
## Alternatives considered
|
|
86
|
+
|
|
87
|
+
### One: `tasks.depends_on int[]` array column
|
|
88
|
+
|
|
89
|
+
Single column, no join table. Rejected because:
|
|
90
|
+
- Indexing both directions (forward + reverse) is harder with arrays.
|
|
91
|
+
- The cycle-detection CTE is uglier without a normalized edge list.
|
|
92
|
+
- The 1-row-per-edge model lets us add per-edge metadata later (e.g. `reason`) without schema churn.
|
|
93
|
+
|
|
94
|
+
### Two: `parent_task_id` for ordering
|
|
95
|
+
|
|
96
|
+
We already have a parent/child hierarchy column (PMS-V2 [#210](https://example.com/builders#/task/210)). Reuse it for ordering. Rejected because hierarchy is a *containment* relationship ("R17 is a sub-task of R15") and dependency is a *precedence* relationship ("R17 cannot start until R08 ships"). Two different things. Conflating them would make both unusable.
|
|
97
|
+
|
|
98
|
+
### Three: Cron-based promotion
|
|
99
|
+
|
|
100
|
+
A scheduled task walks the backlog every N minutes and promotes anything whose deps are clear. Rejected because:
|
|
101
|
+
- Latency: tasks could sit unpromoted for up to N minutes after a ship.
|
|
102
|
+
- More moving parts (one more scheduled task to monitor).
|
|
103
|
+
- The trigger is exactly correct here — it fires synchronously with the state change that matters.
|
|
104
|
+
|
|
105
|
+
### Four: No auto-promotion — keep manual `/promote`
|
|
106
|
+
|
|
107
|
+
Rejected because that's the system that was failing Lars in the first place. Manual promotion doesn't scale beyond one builder.
|
|
108
|
+
|
|
109
|
+
## Consequences
|
|
110
|
+
|
|
111
|
+
**Good:**
|
|
112
|
+
- A high-rank task that's stuck in backlog is now self-explanatory: look at its `dependencies[]`.
|
|
113
|
+
- A planning session's rank actually means something now — execution order can't drift from the spec.
|
|
114
|
+
- Parallel-safe: deps are evaluated per-claim, so two builders can independently claim tasks whose dep graphs don't overlap.
|
|
115
|
+
- The auto-promotion trigger is one place to read; it's the only thing that flips status from backlog → ready (other than `POST /promote` and the existing blocker-resolution trigger).
|
|
116
|
+
|
|
117
|
+
**Costs:**
|
|
118
|
+
- Migration 021 was hand-built for the GDS-V3 task set; future planning sessions will need their seed scripts to write the `task_dependencies` rows as part of the same atomic seed. The [planning-session SKILL](../../.claude/skills/planning-session/SKILL.md) Phase 4 now captures this.
|
|
119
|
+
- Cycle detection on every `addTaskDependency` is a recursive CTE walk. Cheap for V3-sized graphs (<100 nodes, <100 edges); will need an index review at 1000+ nodes if we ever get there.
|
|
120
|
+
- A planner who forgets to declare a dep will get the wrong execution order — but they'll see it immediately when the wrong task auto-promotes, and editing deps after the fact is cheap (`PUT /tasks/:id/dependencies` replaces the full set). The auto-promotion trigger doesn't retro-flip; if you add a dep to a task that's already `ready`, the task stays ready. That's intentional — auto-promotion is a forward-only signal.
|
|
121
|
+
|
|
122
|
+
**Operationally:**
|
|
123
|
+
- `/builder-start` filters by `status='ready'`, so a builder never sees a dep-blocked task in their menu. Good UX.
|
|
124
|
+
- `/builder-claim` returns `DEPS_NOT_SHIPPED` if a manually-promoted task is claimed before its deps land. CLI prints the blockers. Good UX.
|
|
125
|
+
- The `[ADR 0014](../adr/<redacted>.md)` ADR number was taken by the families work; this one is **0015**.
|