@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,279 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// scripts/gds/main-audit.js — post-push main audit (SEC #863, ADR 0043).
|
|
3
|
+
//
|
|
4
|
+
// LAYER 3, the AUTHORITATIVE net. The pre-push hook (layer 1) and the grader
|
|
5
|
+
// pre-pass (layer 2) gate the cooperative path, but a free-plan private repo
|
|
6
|
+
// can't forbid a raw `git push origin main` at GitHub, and a builder can
|
|
7
|
+
// `--no-verify`. This audit reads the REAL git history on main and the REAL
|
|
8
|
+
// builder ranks (from the GDS roster) and flags commits where a builder BELOW
|
|
9
|
+
// Metic edited a permission-sensitive surface — exactly the Builder 25 incident
|
|
10
|
+
// (a Thetes editing the rank-tier CASE in src/bongos/db.js and pushing to main).
|
|
11
|
+
//
|
|
12
|
+
// Two modes:
|
|
13
|
+
// (report, default) list findings on a commit range; non-zero exit if any
|
|
14
|
+
// blocker — usable from CI.
|
|
15
|
+
// --verify-head gate for the deploy step (infra/deploy.sh): exit non-zero
|
|
16
|
+
// if HEAD's range contains a blocker, so a poisoned main
|
|
17
|
+
// never reaches production. THIS is the bridge to Option
|
|
18
|
+
// A: even though builders technically can push main today,
|
|
19
|
+
// the DEPLOY refuses un-authorized commits.
|
|
20
|
+
//
|
|
21
|
+
// Identity: a commit's author NAME is the builder's github_login in this
|
|
22
|
+
// pipeline (verified on the #863 commit: author "IAMMASTERQUA"). We resolve the
|
|
23
|
+
// author against the GDS roster (github_login / display_name). MERGE commits are
|
|
24
|
+
// skipped — their protected-path content is attributed to the feature commits
|
|
25
|
+
// they bring in (which carry the real author). An author we cannot resolve to a
|
|
26
|
+
// rank on a protected-path commit is a 'review' finding (in --verify-head it
|
|
27
|
+
// blocks unless --allow-unverified, fail-closed).
|
|
28
|
+
//
|
|
29
|
+
// Usage:
|
|
30
|
+
// node scripts/gds/main-audit.js # audit last 50 on origin/main
|
|
31
|
+
// node scripts/gds/main-audit.js --range A..B # audit an explicit range
|
|
32
|
+
// node scripts/gds/main-audit.js --verify-head # deploy gate: HEAD~30..HEAD
|
|
33
|
+
// node scripts/gds/main-audit.js --verify-head --db # deploy gate on the droplet (rank from Postgres)
|
|
34
|
+
// node scripts/gds/main-audit.js --revert # also print `git revert` plan
|
|
35
|
+
// node scripts/gds/main-audit.js --strict # also block on unresolved authors
|
|
36
|
+
// node scripts/gds/main-audit.js --db # resolve ranks from Postgres instead of the API
|
|
37
|
+
|
|
38
|
+
'use strict';
|
|
39
|
+
|
|
40
|
+
const { execSync } = require('node:child_process');
|
|
41
|
+
const ppc = require(require('node:path').join(__dirname, '..', '..', 'src', 'bongos', 'permission-path-check.js'));
|
|
42
|
+
const { cliClient } = require('./cli-lib');
|
|
43
|
+
|
|
44
|
+
// ---------- pure analyzer (tested in tests/main_audit.mjs) ----------
|
|
45
|
+
|
|
46
|
+
// commits: [{ sha, subject, authorName, authorEmail, isMerge, files: [] }]
|
|
47
|
+
// rankByIdentity: { '<lowercased login-or-name-or-email>': '<rank>' }
|
|
48
|
+
// Returns { ok, hardFail, findings[] }.
|
|
49
|
+
// strict=true escalates "author couldn't be resolved to a rank" from a
|
|
50
|
+
// 'review' note to a hard blocker. Default is NON-strict: only a RESOLVED
|
|
51
|
+
// sub-Metic author is a blocker (the high-confidence, zero-false-positive
|
|
52
|
+
// signal — the #863 case). This matters because the trusted operator/deployer
|
|
53
|
+
// commits under a git author name ('Lars Kristensen') that is a display name,
|
|
54
|
+
// not a GDS github_login, and every builder shares one commit email — so the
|
|
55
|
+
// author NAME is the only distinguishing signal, and an unresolved name is
|
|
56
|
+
// 'needs a human glance', not 'definitely a violation'.
|
|
57
|
+
function analyzeCommits(commits, rankByIdentity, { strict = false } = {}) {
|
|
58
|
+
const findings = [];
|
|
59
|
+
for (const c of commits || []) {
|
|
60
|
+
// #863-followup (finding #5): we no longer blanket-skip merges. For a
|
|
61
|
+
// regular commit, `files` is its name-only diff. For a MERGE commit, the
|
|
62
|
+
// git layer (parseCommits) populates `files` with the EVIL-MERGE surface —
|
|
63
|
+
// the `git diff-tree --cc` set, i.e. changes the merge introduced that are
|
|
64
|
+
// in NEITHER parent (conflict resolutions / smuggled edits). A normal
|
|
65
|
+
// pipeline merge has an empty --cc set → no files → no finding, so feature
|
|
66
|
+
// changes are still attributed to their feature commits (no double-count);
|
|
67
|
+
// but a merge that smuggles a protected change is now caught and attributed
|
|
68
|
+
// to the MERGE author.
|
|
69
|
+
const hits = ppc.matchProtected(c.files || []);
|
|
70
|
+
if (hits.length === 0) continue;
|
|
71
|
+
|
|
72
|
+
const rank = resolveRank(c, rankByIdentity);
|
|
73
|
+
const fileList = hits.map((h) => h.file).join(', ');
|
|
74
|
+
if (rank == null) {
|
|
75
|
+
findings.push({
|
|
76
|
+
severity: strict ? 'blocker' : 'review',
|
|
77
|
+
sha: c.sha,
|
|
78
|
+
author: c.authorName,
|
|
79
|
+
rank: null,
|
|
80
|
+
files: hits.map((h) => h.file),
|
|
81
|
+
summary: `commit ${short(c.sha)} by '${c.authorName}' touched permission-sensitive path(s) [${fileList}] but the author could not be resolved to a GDS rank. Verify it is Metic+ work.`,
|
|
82
|
+
});
|
|
83
|
+
} else if (ppc.isBelowFloor(rank)) {
|
|
84
|
+
findings.push({
|
|
85
|
+
severity: 'blocker',
|
|
86
|
+
sha: c.sha,
|
|
87
|
+
author: c.authorName,
|
|
88
|
+
rank,
|
|
89
|
+
files: hits.map((h) => h.file),
|
|
90
|
+
summary: `commit ${short(c.sha)} by '${c.authorName}' (rank '${rank}', below Metic) modified permission-sensitive path(s) [${fileList}] — this is the SEC #863 violation class. It must be reverted and re-landed by an Archon if genuinely needed.`,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
ok: findings.every((f) => f.severity !== 'blocker'),
|
|
96
|
+
hardFail: findings.some((f) => f.severity === 'blocker'),
|
|
97
|
+
findings,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// #863-followup (red-team finding #6): resolve ONLY against github_login.
|
|
102
|
+
// We deliberately do NOT match on email (everyone shares one commit email —
|
|
103
|
+
// non-distinguishing) nor display_name (builder-controlled — a malicious builder
|
|
104
|
+
// can set display_name to another builder's login to ALIAS/poison resolution).
|
|
105
|
+
// github_login is GitHub-controlled and immutable per account. A commit whose
|
|
106
|
+
// git author name is not a known github_login resolves to null → handled by the
|
|
107
|
+
// strict gate (block) rather than silently passing.
|
|
108
|
+
function resolveRank(c, rankByIdentity) {
|
|
109
|
+
const name = (c.authorName || '').toLowerCase();
|
|
110
|
+
return name && rankByIdentity[name] != null ? rankByIdentity[name] : null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function short(sha) {
|
|
114
|
+
return String(sha || '').slice(0, 9);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ---------- git + API glue (CLI) ----------
|
|
118
|
+
|
|
119
|
+
function git(args) {
|
|
120
|
+
return execSync(`git ${args}`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Parse `git log --name-only` with a NUL-delimited custom format into commits.
|
|
124
|
+
function parseCommits(range) {
|
|
125
|
+
// %x00 = NUL. Format: NUL sha NUL parents NUL authorName NUL authorEmail NUL subject \n files...
|
|
126
|
+
const fmt = '%x00%H%x00%P%x00%an%x00%ae%x00%s';
|
|
127
|
+
let out;
|
|
128
|
+
try {
|
|
129
|
+
out = git(`log ${range} --name-only --format=${JSON.stringify(fmt)}`);
|
|
130
|
+
} catch (e) {
|
|
131
|
+
return { error: `git log failed for range ${range}: ${e.message}` };
|
|
132
|
+
}
|
|
133
|
+
const records = out.split('\x00').slice(1); // first chunk is empty / pre-first-NUL
|
|
134
|
+
const commits = [];
|
|
135
|
+
// Each commit emits: sha, parents, an, ae, "subject\nfile\nfile...". We split
|
|
136
|
+
// on NUL so chunks come in groups of 5; the 5th holds subject + file list.
|
|
137
|
+
for (let i = 0; i + 4 < records.length; i += 5) {
|
|
138
|
+
const sha = records[i].trim();
|
|
139
|
+
const parents = records[i + 1].trim();
|
|
140
|
+
const authorName = records[i + 2];
|
|
141
|
+
const authorEmail = records[i + 3];
|
|
142
|
+
const rest = records[i + 4].split('\n');
|
|
143
|
+
const subject = rest.shift();
|
|
144
|
+
const files = rest.map((s) => s.trim()).filter(Boolean);
|
|
145
|
+
if (!sha) continue;
|
|
146
|
+
const isMerge = parents.split(/\s+/).filter(Boolean).length > 1;
|
|
147
|
+
commits.push({ sha, subject, authorName, authorEmail, isMerge, files });
|
|
148
|
+
}
|
|
149
|
+
// #863-followup (finding #5): `git log --name-only` emits NO files for merge
|
|
150
|
+
// commits, so a merge that SMUGGLES a protected change (an "evil merge" /
|
|
151
|
+
// conflict resolution that edits a file present in neither parent) would slip
|
|
152
|
+
// through. Backfill each merge's `files` with the combined-diff (`--cc`)
|
|
153
|
+
// surface — exactly the changes the merge introduced vs. all parents. A clean
|
|
154
|
+
// pipeline merge has an empty --cc set (nothing to flag); a smuggled edit
|
|
155
|
+
// shows up here and is attributed to the merge author by analyzeCommits.
|
|
156
|
+
for (const c of commits) {
|
|
157
|
+
if (!c.isMerge) continue;
|
|
158
|
+
try {
|
|
159
|
+
const cc = git(`diff-tree --cc --name-only --no-commit-id -r ${c.sha}`);
|
|
160
|
+
c.files = cc.split('\n').map((s) => s.trim()).filter(Boolean);
|
|
161
|
+
} catch (_) {
|
|
162
|
+
c.files = []; // can't compute → empty (the nightly full-history audit re-checks)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return { commits };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// #863-followup (finding #6): key ONLY on github_login. display_name is
|
|
169
|
+
// builder-controlled — keying it let a malicious builder alias another login's
|
|
170
|
+
// rank (last-write-wins poisoning). github_login is GitHub-controlled.
|
|
171
|
+
function rowsToMap(rows) {
|
|
172
|
+
const map = {};
|
|
173
|
+
for (const b of rows || []) {
|
|
174
|
+
if (b.github_login) map[String(b.github_login).toLowerCase()] = b.rank;
|
|
175
|
+
}
|
|
176
|
+
return map;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// API mode (default): for an Archon session / operator laptop. DB mode (--db):
|
|
180
|
+
// for the droplet deploy gate, which has DB access but no GDS session — it reads
|
|
181
|
+
// the roster straight from Postgres. db.js is lazy-required so importing this
|
|
182
|
+
// module (e.g. in tests) never pulls in pg.
|
|
183
|
+
async function fetchRankMap({ useDb = false } = {}) {
|
|
184
|
+
if (useDb) {
|
|
185
|
+
try {
|
|
186
|
+
const db = require('../../src/bongos/db.js');
|
|
187
|
+
const roster = await db.getBuildersRoster({ staleHours: 24 });
|
|
188
|
+
return rowsToMap(roster.builders || roster);
|
|
189
|
+
} catch (e) {
|
|
190
|
+
console.error(`main-audit: --db roster read failed (${e.message})`);
|
|
191
|
+
return {};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
const api = await cliClient({ allowUnauthenticated: true });
|
|
196
|
+
const res = await api.builders.getBuildersRoster();
|
|
197
|
+
if (res && res.ok) return rowsToMap(res.data?.builders || []);
|
|
198
|
+
} catch (_) { /* offline / not archon — map stays empty → unresolved authors */ }
|
|
199
|
+
return {};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function arg(name, fallback = null) {
|
|
203
|
+
const i = process.argv.indexOf(name);
|
|
204
|
+
return i >= 0 ? (process.argv[i + 1] && !process.argv[i + 1].startsWith('--') ? process.argv[i + 1] : true) : fallback;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function main() {
|
|
208
|
+
const verifyHead = process.argv.includes('--verify-head');
|
|
209
|
+
const doRevert = process.argv.includes('--revert');
|
|
210
|
+
const strict = process.argv.includes('--strict');
|
|
211
|
+
const useDb = process.argv.includes('--db');
|
|
212
|
+
let range = arg('--range');
|
|
213
|
+
// #863-followup (findings #8/#14): the verify-head window was a fixed
|
|
214
|
+
// HEAD~30..HEAD — a poisoned commit buried under >30 commits (merges inflate
|
|
215
|
+
// the count) or landed before a rebase/force-push could escape it. The deploy
|
|
216
|
+
// gate now passes the EXACT previously-deployed SHA via OTB_AUDIT_RANGE
|
|
217
|
+
// (deploy-main-audit-gate.sh sets it to <prev-deployed-sha>..HEAD), so the
|
|
218
|
+
// gate audits precisely what this deploy introduces — no window to slip under.
|
|
219
|
+
// Fallbacks widen to HEAD~200 (verify-head) / a deeper origin scan otherwise.
|
|
220
|
+
if ((!range || range === true) && process.env.OTB_AUDIT_RANGE) {
|
|
221
|
+
range = process.env.OTB_AUDIT_RANGE;
|
|
222
|
+
}
|
|
223
|
+
if (!range || range === true) {
|
|
224
|
+
if (verifyHead) {
|
|
225
|
+
range = 'HEAD~200..HEAD';
|
|
226
|
+
} else {
|
|
227
|
+
// Default: recent origin/main. Fetch first so we're auditing the truth.
|
|
228
|
+
try { git('fetch origin main'); } catch (_) { /* offline — audit local */ }
|
|
229
|
+
range = 'origin/main~200..origin/main';
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const parsed = parseCommits(range);
|
|
234
|
+
if (parsed.error) {
|
|
235
|
+
console.error(`main-audit: ${parsed.error}`);
|
|
236
|
+
process.exit(2);
|
|
237
|
+
}
|
|
238
|
+
const rankMap = await fetchRankMap({ useDb });
|
|
239
|
+
if (Object.keys(rankMap).length === 0) {
|
|
240
|
+
console.error('main-audit: WARNING — could not load the GDS roster (offline / not Archon / no DB). Authors will be unresolved; run as an Archon or with --db (on the droplet) for a definitive audit.');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const result = analyzeCommits(parsed.commits, rankMap, { strict });
|
|
244
|
+
|
|
245
|
+
console.log(`\nMain audit (SEC #863) — range ${range}, ${parsed.commits.length} commit(s)`);
|
|
246
|
+
if (result.findings.length === 0) {
|
|
247
|
+
console.log(' ✓ clean — no sub-Metic edits to permission-sensitive paths.\n');
|
|
248
|
+
process.exit(0);
|
|
249
|
+
}
|
|
250
|
+
for (const f of result.findings) {
|
|
251
|
+
const tag = f.severity === 'blocker' ? '\x1b[31m[BLOCKER]\x1b[0m' : '\x1b[33m[review]\x1b[0m';
|
|
252
|
+
console.log(` ${tag} ${f.summary}`);
|
|
253
|
+
}
|
|
254
|
+
if (doRevert) {
|
|
255
|
+
const blockers = result.findings.filter((f) => f.severity === 'blocker');
|
|
256
|
+
if (blockers.length) {
|
|
257
|
+
console.log('\nRevert plan (review before running — an Archon decides):');
|
|
258
|
+
for (const f of blockers) console.log(` git revert --no-edit ${f.sha} # ${f.author} / ${f.rank}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
console.log('');
|
|
262
|
+
|
|
263
|
+
// verify-head is the deploy gate: any blocker (and, unless allowed, any
|
|
264
|
+
// unresolved author) must stop the deploy.
|
|
265
|
+
if (verifyHead) {
|
|
266
|
+
process.exit(result.hardFail ? 1 : 0);
|
|
267
|
+
}
|
|
268
|
+
// report mode: non-zero on a real blocker so CI can fail.
|
|
269
|
+
process.exit(result.hardFail ? 1 : 0);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (require.main === module) {
|
|
273
|
+
main().catch((e) => {
|
|
274
|
+
console.error(`main-audit: ${e.message}`);
|
|
275
|
+
process.exit(2);
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
module.exports = { analyzeCommits, resolveRank, parseCommits };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Show the current builder profile, leaderboard top 10, and active claim.
|
|
3
|
+
|
|
4
|
+
const { cliClient, requireSession } = require('./cli-lib');
|
|
5
|
+
|
|
6
|
+
(async () => {
|
|
7
|
+
await requireSession();
|
|
8
|
+
const api = await cliClient();
|
|
9
|
+
const me = await api.me.getMe();
|
|
10
|
+
if (!me.ok) {
|
|
11
|
+
console.error('me failed:', me.data);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
const lb = await api.leaderboard.getLeaderboard();
|
|
15
|
+
|
|
16
|
+
const b = me.data.builder;
|
|
17
|
+
const rankLabel = b.rank ? b.rank.charAt(0).toUpperCase() + b.rank.slice(1) : 'Thetes';
|
|
18
|
+
console.log(`${b.display_name} (@${b.github_login})`);
|
|
19
|
+
console.log(`Builder #${b.id} · ${rankLabel} · ${b.total_credits} credits`);
|
|
20
|
+
// V3 auth-flow slice 1: the /me call we just made succeeded, which means the
|
|
21
|
+
// session is valid AND just rolled forward (mig 035 refreshes expires_at to
|
|
22
|
+
// NOW()+1h on every authenticated request). Surface that so 1h-rolling is
|
|
23
|
+
// visible to the builder rather than being silent infrastructure.
|
|
24
|
+
console.log(`Session valid — auto-refreshes on every API call (1h rolling TTL).`);
|
|
25
|
+
|
|
26
|
+
// Streak panel — shown only when current streak > 0 (per task spec).
|
|
27
|
+
const s = me.data.streak;
|
|
28
|
+
if (s && s.current > 0) {
|
|
29
|
+
console.log('');
|
|
30
|
+
console.log(`Streak: ${s.current} day${s.current === 1 ? '' : 's'} 🔥 (longest: ${s.longest})`);
|
|
31
|
+
if (s.last_ship_day) {
|
|
32
|
+
console.log(`Last ship-day: ${s.last_ship_day}${s.today === s.last_ship_day ? ' (today)' : ''}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const claims = me.data.active_claims || (me.data.active_claim ? [me.data.active_claim] : []);
|
|
37
|
+
if (claims.length === 0) {
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log('No active claims.');
|
|
40
|
+
} else {
|
|
41
|
+
console.log('');
|
|
42
|
+
console.log(`Active claim${claims.length > 1 ? 's' : ''} (${claims.length}):`);
|
|
43
|
+
for (const c of claims) {
|
|
44
|
+
console.log(` #${c.task_id} ${c.title}`);
|
|
45
|
+
console.log(` Version: ${c.version_id} · P${c.priority ?? '?'} · ${c.credits_reward}c reward`);
|
|
46
|
+
console.log(` Claimed: ${new Date(c.claimed_at).toLocaleString()}`);
|
|
47
|
+
if (c.worktree_name) console.log(` Worktree: ${c.worktree_name}`);
|
|
48
|
+
// Streak preview — only when qualifying + extending (skip the noisy
|
|
49
|
+
// "today-already-counted" + "task-not-found" cases).
|
|
50
|
+
const sp = c.streak_preview;
|
|
51
|
+
if (sp && sp.qualifies && sp.projected_streak > sp.current_streak) {
|
|
52
|
+
console.log(` 🔥 Shipping this would extend streak to ${sp.projected_streak} day${sp.projected_streak === 1 ? '' : 's'}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Recent quality grades (task 197). Surface only when the builder has at
|
|
58
|
+
// least one graded task so a fresh builder sees no empty section.
|
|
59
|
+
const grades = me.data.grades || {};
|
|
60
|
+
const recent = grades.recent || [];
|
|
61
|
+
const rolling = grades.rolling || {};
|
|
62
|
+
if (recent.length > 0) {
|
|
63
|
+
console.log('');
|
|
64
|
+
console.log('Recent quality marks (last 5):');
|
|
65
|
+
for (const g of recent) {
|
|
66
|
+
const verdict = g.passed ? 'PASS' : 'FAIL';
|
|
67
|
+
const dateStr = new Date(g.graded_at).toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
|
|
68
|
+
console.log(` ${dateStr} #${g.task_id} ${Number(g.score).toFixed(1)}/10 ${verdict} ${g.title || ''}`);
|
|
69
|
+
}
|
|
70
|
+
if (Number(rolling.n) > 0) {
|
|
71
|
+
const avg = Number(rolling.avg_score).toFixed(1);
|
|
72
|
+
console.log(` 14-day avg: ${avg}/10 across ${rolling.n} task${rolling.n === 1 ? '' : 's'} (${rolling.n_passed} passed)`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (lb.ok) {
|
|
77
|
+
console.log('\nLeaderboard (top 10):');
|
|
78
|
+
let i = 1;
|
|
79
|
+
for (const row of (lb.data.leaderboard || []).slice(0, 10)) {
|
|
80
|
+
const me = row.id === b.id ? ' ← you' : '';
|
|
81
|
+
console.log(` ${i.toString().padStart(2)}. ${row.display_name} (@${row.github_login}) — ${row.total_credits}c${me}`);
|
|
82
|
+
i++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
})().catch((err) => {
|
|
86
|
+
console.error('fatal:', err);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
});
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// memory-map.js — keep the always-loaded memory MAP (MEMORY.md) light.
|
|
3
|
+
//
|
|
4
|
+
// MEMORY.md is the index the Claude Code harness loads IN FULL every session:
|
|
5
|
+
// one line per memory → its topic file (the full fact). The topic files are the
|
|
6
|
+
// "drawer" — they live on disk, sync to the GDS server (builder_memory), and are
|
|
7
|
+
// searchable via /recall (ADR 0060), so they cost nothing until something fetches
|
|
8
|
+
// them. The map is the only part paid for every session, so it must stay small.
|
|
9
|
+
//
|
|
10
|
+
// Nothing kept it small, so it re-bloated until the harness's ~24.4KB truncation
|
|
11
|
+
// fired (too late — by then it was dropping lines). This module is the cure
|
|
12
|
+
// (task 1362): a budget GUARD + an auto-TIDY that demotes the oldest non-rule
|
|
13
|
+
// entries out of the map. **Demote = delete the entry's LINE from MEMORY.md only;
|
|
14
|
+
// the topic file is never touched** — it stays on disk + server + /recall, one
|
|
15
|
+
// query away. Standing rules (feedback_*/user memories) are never demoted.
|
|
16
|
+
//
|
|
17
|
+
// This file holds the PURE, testable logic. The session-start hook
|
|
18
|
+
// (.claude/hooks/pull-memory.js) calls it; the actual file write is done by the
|
|
19
|
+
// caller so it can be parallel-safe (optimistic: skip if the file changed since
|
|
20
|
+
// read — the builder runs many concurrent sessions).
|
|
21
|
+
|
|
22
|
+
'use strict';
|
|
23
|
+
const fs = require('node:fs');
|
|
24
|
+
const path = require('node:path');
|
|
25
|
+
|
|
26
|
+
// Budgets, in bytes of MEMORY.md (~4 chars/token for markdown prose).
|
|
27
|
+
const WARN_BYTES = 16000; // ~4K tok — drifting up; warn so it gets tidied.
|
|
28
|
+
const TIDY_BYTES = 20000; // ~5K tok — auto-compact kicks in (still well under the ~24.4KB harness truncation).
|
|
29
|
+
const TARGET_BYTES = 13000; // ~3.25K tok — compact back to about here.
|
|
30
|
+
const MAX_LINE_CHARS = 280; // an index line past this has slipped the "one line" rule.
|
|
31
|
+
const KEEP_NEWEST = 25; // newest non-rule entries always kept in the map.
|
|
32
|
+
|
|
33
|
+
const estTokens = (bytes) => Math.round(bytes / 4);
|
|
34
|
+
|
|
35
|
+
// A map entry is a top-level bullet linking a topic file:
|
|
36
|
+
// - [Title](some-file.md) — one-line hook
|
|
37
|
+
const ENTRY_RE = /^- \[([^\]]*)\]\(([A-Za-z0-9_-]+\.md)\)/;
|
|
38
|
+
|
|
39
|
+
// Parse MEMORY.md into ordered entries. Non-entry lines (blank, headers) are
|
|
40
|
+
// preserved positionally as { raw, entry:false } so render() can't drop them.
|
|
41
|
+
function parseLines(text) {
|
|
42
|
+
return text.split('\n').map((raw) => {
|
|
43
|
+
const m = raw.match(ENTRY_RE);
|
|
44
|
+
return m ? { raw, entry: true, title: m[1], file: m[2], len: raw.length } : { raw, entry: false };
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function entries(text) {
|
|
49
|
+
return parseLines(text).filter((l) => l.entry);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Measure the map: size, token estimate, count, and any over-long lines.
|
|
53
|
+
function measure(text) {
|
|
54
|
+
const bytes = Buffer.byteLength(text, 'utf8');
|
|
55
|
+
const es = entries(text);
|
|
56
|
+
const longLines = es.filter((e) => e.len > MAX_LINE_CHARS).map((e) => ({ file: e.file, len: e.len }));
|
|
57
|
+
return {
|
|
58
|
+
bytes,
|
|
59
|
+
tokens: estTokens(bytes),
|
|
60
|
+
count: es.length,
|
|
61
|
+
longLines,
|
|
62
|
+
overWarn: bytes > WARN_BYTES,
|
|
63
|
+
overTidy: bytes > TIDY_BYTES,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// type/mtime for a topic file. feedback_* and `user`-type memories are STANDING
|
|
68
|
+
// RULES — never demoted. Everything else is demotable by age.
|
|
69
|
+
function metaOf(file, memoryDir, deps = {}) {
|
|
70
|
+
const readFile = deps.readFile || ((p) => fs.readFileSync(p, 'utf8'));
|
|
71
|
+
const stat = deps.stat || ((p) => fs.statSync(p));
|
|
72
|
+
let type = /^feedback_/.test(file) ? 'feedback' : 'unknown';
|
|
73
|
+
let mtime = 0;
|
|
74
|
+
let pin = false;
|
|
75
|
+
const abs = path.join(memoryDir, file);
|
|
76
|
+
try {
|
|
77
|
+
mtime = stat(abs).mtimeMs;
|
|
78
|
+
const fm = readFile(abs).match(/^---\n([\s\S]*?)\n---/);
|
|
79
|
+
if (fm) {
|
|
80
|
+
if (type === 'unknown') {
|
|
81
|
+
const t = fm[1].match(/(?:^|\n)\s*type:\s*([a-z]+)/);
|
|
82
|
+
if (t) type = t[1];
|
|
83
|
+
}
|
|
84
|
+
// `pin: true` in frontmatter marks an entry the owner always wants on the
|
|
85
|
+
// home screen — kept regardless of age or budget (e.g. the live-version
|
|
86
|
+
// pointer, standing security alerts).
|
|
87
|
+
pin = /(?:^|\n)\s*pin:\s*(?:true|yes)\b/i.test(fm[1]);
|
|
88
|
+
}
|
|
89
|
+
} catch { /* missing file → treat as demotable, oldest */ }
|
|
90
|
+
return { type, mtime, pin };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const isRule = (type) => type === 'feedback' || type === 'user';
|
|
94
|
+
// Never demoted: a standing rule (feedback_*/user) OR an explicitly pinned entry.
|
|
95
|
+
const keepAlways = (meta) => isRule(meta.type) || !!meta.pin;
|
|
96
|
+
|
|
97
|
+
// Decide what stays in the map and what gets demoted to the drawer.
|
|
98
|
+
// Keep: every standing rule + the newest `keepNewest` of the rest; then, if still
|
|
99
|
+
// over targetBytes, demote more from the oldest kept until under target.
|
|
100
|
+
// Rules are NEVER demoted. Returns { newText, demote:[{file,title}], willChange }.
|
|
101
|
+
function planCompaction(text, opts = {}) {
|
|
102
|
+
const memoryDir = opts.memoryDir;
|
|
103
|
+
const targetBytes = opts.targetBytes ?? TARGET_BYTES;
|
|
104
|
+
const keepNewest = opts.keepNewest ?? KEEP_NEWEST;
|
|
105
|
+
const meta = opts.metaOf || ((file) => metaOf(file, memoryDir, opts.deps));
|
|
106
|
+
|
|
107
|
+
const lines = parseLines(text);
|
|
108
|
+
const es = lines.filter((l) => l.entry);
|
|
109
|
+
const enriched = es.map((e) => ({ ...e, ...meta(e.file) }));
|
|
110
|
+
|
|
111
|
+
const rules = new Set(enriched.filter((e) => keepAlways(e)).map((e) => e.file));
|
|
112
|
+
const others = enriched.filter((e) => !keepAlways(e)).sort((a, b) => b.mtime - a.mtime); // newest first
|
|
113
|
+
const keptOthers = others.slice(0, keepNewest);
|
|
114
|
+
const demote = new Map(others.slice(keepNewest).map((e) => [e.file, e.title]));
|
|
115
|
+
|
|
116
|
+
// Still over target? Demote more from the OLDEST end of the kept others.
|
|
117
|
+
const sizeIfKept = () => {
|
|
118
|
+
const drop = new Set(demote.keys());
|
|
119
|
+
return Buffer.byteLength(lines.filter((l) => !(l.entry && drop.has(l.file))).map((l) => l.raw).join('\n') + '\n', 'utf8');
|
|
120
|
+
};
|
|
121
|
+
for (let i = keptOthers.length - 1; i >= 0 && sizeIfKept() > targetBytes; i--) {
|
|
122
|
+
demote.set(keptOthers[i].file, keptOthers[i].title);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const drop = new Set(demote.keys());
|
|
126
|
+
const keptLines = lines.filter((l) => !(l.entry && drop.has(l.file)));
|
|
127
|
+
const newText = keptLines.map((l) => l.raw).join('\n').replace(/\n*$/, '') + '\n';
|
|
128
|
+
return {
|
|
129
|
+
newText,
|
|
130
|
+
demote: [...demote.entries()].map(([file, title]) => ({ file, title })),
|
|
131
|
+
willChange: drop.size > 0,
|
|
132
|
+
keptCount: keptLines.filter((l) => l.entry).length,
|
|
133
|
+
ruleCount: rules.size,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Parallel-safe apply: only write if the file on disk still matches what we read
|
|
138
|
+
// (another concurrent session may have just rewritten it — don't clobber it).
|
|
139
|
+
function applyCompaction(mapPath, expectedText, newText, deps = {}) {
|
|
140
|
+
const readFile = deps.readFile || ((p) => fs.readFileSync(p, 'utf8'));
|
|
141
|
+
const writeFile = deps.writeFile || ((p, c) => fs.writeFileSync(p, c));
|
|
142
|
+
let current;
|
|
143
|
+
try { current = readFile(mapPath); } catch { return { written: false, reason: 'missing' }; }
|
|
144
|
+
if (current !== expectedText) return { written: false, reason: 'changed-since-read' };
|
|
145
|
+
writeFile(mapPath, newText);
|
|
146
|
+
return { written: true };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = {
|
|
150
|
+
WARN_BYTES, TIDY_BYTES, TARGET_BYTES, MAX_LINE_CHARS, KEEP_NEWEST,
|
|
151
|
+
estTokens, parseLines, entries, measure, metaOf, isRule, keepAlways,
|
|
152
|
+
planCompaction, applyCompaction,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// CLI: `node scripts/gds/memory-map.js [--dir <memoryDir>] [--apply]`
|
|
156
|
+
// Prints the measurement + the compaction plan; --apply writes it (parallel-safe).
|
|
157
|
+
if (require.main === module) {
|
|
158
|
+
const args = process.argv.slice(2);
|
|
159
|
+
const dirArg = args.indexOf('--dir');
|
|
160
|
+
const memoryDir = dirArg >= 0 ? args[dirArg + 1] : process.env.OTB_MEMORY_DIR;
|
|
161
|
+
if (!memoryDir) { console.error('usage: memory-map.js --dir <memoryDir> [--apply]'); process.exit(2); }
|
|
162
|
+
const mapPath = path.join(memoryDir, 'MEMORY.md');
|
|
163
|
+
let text; try { text = fs.readFileSync(mapPath, 'utf8'); } catch { console.error('no MEMORY.md at', mapPath); process.exit(0); }
|
|
164
|
+
const m = measure(text);
|
|
165
|
+
console.log(`map: ${m.bytes} bytes (~${m.tokens} tok), ${m.count} entries · overWarn=${m.overWarn} overTidy=${m.overTidy} · longLines=${m.longLines.length}`);
|
|
166
|
+
const plan = planCompaction(text, { memoryDir });
|
|
167
|
+
if (!plan.willChange) { console.log('nothing to demote — map is within target.'); process.exit(0); }
|
|
168
|
+
console.log(`would demote ${plan.demote.length} entries to the drawer (topic files kept):`);
|
|
169
|
+
for (const d of plan.demote) console.log(` - ${d.file}`);
|
|
170
|
+
if (args.includes('--apply')) {
|
|
171
|
+
const r = applyCompaction(mapPath, text, plan.newText);
|
|
172
|
+
console.log(r.written ? `applied — map now ${Buffer.byteLength(plan.newText)} bytes` : `not written (${r.reason})`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// CLI wrapper so the /merge-mode skill shares the SAME merge mutex as ship.js's
|
|
3
|
+
// auto-merge (V3.R50 / #269, criterion C6). Before #269 the lock lived inside
|
|
4
|
+
// ship.js, so a manual /merge-mode run could collide with a concurrent ship on
|
|
5
|
+
// the shared main worktree. /merge-mode now acquires this lock before it
|
|
6
|
+
// checks out main + merges, and releases it after deploy.
|
|
7
|
+
//
|
|
8
|
+
// Usage:
|
|
9
|
+
// node scripts/gds/merge-lock.js acquire # blocks up to 30s; exit 0 acquired, 3 if held
|
|
10
|
+
// node scripts/gds/merge-lock.js release # remove a manual hold
|
|
11
|
+
// node scripts/gds/merge-lock.js status # report holder + age
|
|
12
|
+
//
|
|
13
|
+
// The hold is recorded as mode='manual' (pid=0) because the acquiring CLI
|
|
14
|
+
// process exits immediately — there's no long-lived owner. Manual holds are
|
|
15
|
+
// reclaimed by time only (merge-lock.MANUAL_STALE_MS), so an operator who
|
|
16
|
+
// walks away mid-merge doesn't deadlock the queue forever.
|
|
17
|
+
|
|
18
|
+
const path = require('node:path');
|
|
19
|
+
const { execSync } = require('node:child_process');
|
|
20
|
+
// the merge-lock lib carved to modules/lifecycle/ (BV1.R86); a CLI may require a
|
|
21
|
+
// module directly (outside the kernel boundary — the grading/economy precedent).
|
|
22
|
+
const lock = require('../../modules/lifecycle/merge-lock');
|
|
23
|
+
|
|
24
|
+
// Resolve the main checkout root regardless of which worktree we're invoked
|
|
25
|
+
// from: dirname of the shared common .git directory. Rename-proof — matches
|
|
26
|
+
// the /merge-mode SKILL.md REPO_ROOT derivation and ship.js's findMainWorktree.
|
|
27
|
+
function mainWorktreeRoot() {
|
|
28
|
+
const common = execSync('git rev-parse --git-common-dir', {
|
|
29
|
+
encoding: 'utf8',
|
|
30
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
31
|
+
}).trim();
|
|
32
|
+
const abs = path.isAbsolute(common) ? common : path.resolve(process.cwd(), common);
|
|
33
|
+
return path.dirname(abs);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const cmd = process.argv[2];
|
|
37
|
+
let root;
|
|
38
|
+
try {
|
|
39
|
+
root = mainWorktreeRoot();
|
|
40
|
+
} catch (e) {
|
|
41
|
+
console.error('merge-lock: not a git repo (cannot resolve main worktree):', e.message);
|
|
42
|
+
process.exit(2);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (cmd === 'acquire') {
|
|
46
|
+
// Manual hold: pid=0 (no long-lived owner), reclaimed by time only.
|
|
47
|
+
const ok = lock.acquire(root, { mode: 'manual', pid: 0, waitMs: 30000 });
|
|
48
|
+
if (ok) {
|
|
49
|
+
console.log('merge-lock: acquired (manual hold). Release with `node scripts/gds/merge-lock.js release` when the merge run is done.');
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
console.error('merge-lock: held by another ship or merge run — wait and retry, or run `merge-lock status` to inspect the holder.');
|
|
53
|
+
process.exit(3);
|
|
54
|
+
} else if (cmd === 'release') {
|
|
55
|
+
lock.release(root);
|
|
56
|
+
console.log('merge-lock: released.');
|
|
57
|
+
process.exit(0);
|
|
58
|
+
} else if (cmd === 'status') {
|
|
59
|
+
const rec = lock.readLock(root);
|
|
60
|
+
if (!rec) {
|
|
61
|
+
console.log('merge-lock: free.');
|
|
62
|
+
process.exit(0);
|
|
63
|
+
}
|
|
64
|
+
const ageS = Math.round((Date.now() - rec.ts) / 1000);
|
|
65
|
+
const stale = lock.isStale(rec) ? ' (STALE — reclaimable)' : '';
|
|
66
|
+
console.log(`merge-lock: HELD mode=${rec.mode} pid=${rec.pid} age=${ageS}s${stale}`);
|
|
67
|
+
process.exit(0);
|
|
68
|
+
} else {
|
|
69
|
+
console.error('usage: node scripts/gds/merge-lock.js acquire|release|status');
|
|
70
|
+
process.exit(2);
|
|
71
|
+
}
|