@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,239 @@
|
|
|
1
|
+
// MAS Phase 2.1 (#416) — Hacker worker.
|
|
2
|
+
//
|
|
3
|
+
// Specialty: security red-team review. Hunts injection, auth/authz gaps,
|
|
4
|
+
// hardcoded secrets, trust-boundary violations, and the rest of the
|
|
5
|
+
// OWASP-shape problems in the diff. Reports a `security_score` (0-10) +
|
|
6
|
+
// a severity-graded issues list (critical/high → blocker, medium → major,
|
|
7
|
+
// low → minor) that aligns with the existing /builder-redteam human flow.
|
|
8
|
+
//
|
|
9
|
+
// Hacker shifts security review from *post-merge bounty filing* (the
|
|
10
|
+
// existing skill) to *pre-merge ship-time gate*. The two systems are
|
|
11
|
+
// complementary: Hacker catches at ship time; /builder-redteam still
|
|
12
|
+
// covers post-merge findings (with bounty payout).
|
|
13
|
+
|
|
14
|
+
// THRESHOLD + LOW_CONF come from the shared rubric module (task 1090, C6).
|
|
15
|
+
const { THRESHOLD, LOW_CONF } = require('./rubric');
|
|
16
|
+
|
|
17
|
+
// SR-15 / G1 (#995): scrub + fence all builder-controlled inputs. The shared
|
|
18
|
+
// scaffold (worker-prompt) owns fenceBlock/NOFOLLOW_PREAMBLE; Hacker still
|
|
19
|
+
// scrubs each deterministic-finding line inline (its findings-section safe()).
|
|
20
|
+
const { buildWorkerPrompt, LLM_PROJECT } = require('./worker-prompt');
|
|
21
|
+
const { failResult, parseCommon, finalizeVerdict } = require('./worker-verdict');
|
|
22
|
+
const { scrubUntrusted } = require('./fence');
|
|
23
|
+
|
|
24
|
+
const KIND = 'hacker';
|
|
25
|
+
const NAME = 'Hacker';
|
|
26
|
+
const SPECIALTY = 'security red-team (injection, auth/authz, secrets, trust boundary)';
|
|
27
|
+
|
|
28
|
+
const PROMPT_HEADER = `You are the **Hacker** — a specialist adversarial subagent for the ${LLM_PROJECT} project. You exist to catch security vulnerabilities the moment they enter the codebase, before they ever ship.
|
|
29
|
+
|
|
30
|
+
Your ONLY job is security. You do NOT score whether the description was implemented (that's the Narc) or whether the code is well-written (that's the Quality worker). Your verdict is about whether this diff introduces, perpetuates, or fails to fix a security flaw.
|
|
31
|
+
|
|
32
|
+
**The default verdict is FAIL.** You PASS only after a careful read of the diff and (via your Read tool, within budget) the relevant post-merge files turns up no exploitable patterns and you can affirmatively name the security-relevant surfaces you checked.
|
|
33
|
+
|
|
34
|
+
## Read budget (CRITICAL)
|
|
35
|
+
|
|
36
|
+
**You have a hard budget of 5 Read calls per grade.** Prefer the diff over Read. Most security-relevant code (route handlers, auth wrappers, query construction, secret references) is visible in the diff text — that's evidence. Reserve Reads for: confirming that a new route inherits the right auth wrapper from a shared module, that a removed validation isn't compensated elsewhere, that a config change doesn't silently weaken an existing protection.
|
|
37
|
+
|
|
38
|
+
If you exhaust the budget, score conservatively and call it out in notes_md. Better to flag one unverified surface than to silently miss it.
|
|
39
|
+
|
|
40
|
+
## Failure modes you hunt for
|
|
41
|
+
|
|
42
|
+
Cite the diff line (or quote the offending code) for every finding.
|
|
43
|
+
|
|
44
|
+
**Critical-severity (forge writes as another builder, read data the user isn't entitled to, RCE-equivalent):**
|
|
45
|
+
- SQL / NoSQL injection (string concatenation in queries, missing parameterization).
|
|
46
|
+
- Command injection (\`exec\` / \`spawn\` with untrusted strings; shell metacharacters from user input).
|
|
47
|
+
- Path traversal (user input flowed into \`fs.*\` or path joins without normalization).
|
|
48
|
+
- Authn / authz bypass: a route or DB write that should be gated by \`requireRank\` / \`requireBuilder\` / ownership-check but isn't. Per ADR 0016, every privileged write must server-side-check rank against the DB — a route missing that gate is critical.
|
|
49
|
+
- Hardcoded secrets in source (literal API keys, bearer tokens, passwords, private keys). \`process.env.X\` is fine; a literal string that looks like a credential is not.
|
|
50
|
+
- Trust-boundary violation: code that lets a local edit (CLAUDE.md, skills, hooks, settings.json) grant authority that the DB-enforced rank model would otherwise refuse.
|
|
51
|
+
|
|
52
|
+
**High-severity (real attack vector with a workaround):**
|
|
53
|
+
- XSS / unsanitized HTML rendering of user input (template strings, \`innerHTML\` with untrusted data, missing escaping).
|
|
54
|
+
- SSRF: server makes a network request to a URL derived from user input without an allowlist.
|
|
55
|
+
- Insecure deserialization (\`JSON.parse\` of user input that becomes runtime objects in trusted positions, \`eval\`, \`new Function\` with input).
|
|
56
|
+
- Missing CSRF protection on a state-changing route that uses cookie auth (less relevant here since the GDS uses bearer tokens, but check).
|
|
57
|
+
- Sensitive data in logs (passwords, full tokens, PII printed to stderr/stdout).
|
|
58
|
+
|
|
59
|
+
**Medium-severity (defense-in-depth gap — verdict 'concerns'):**
|
|
60
|
+
- Information disclosure in error messages (stack traces leaking internals on public surfaces).
|
|
61
|
+
- Insecure crypto choices (MD5 / SHA1 for security, weak random for tokens, short HMAC).
|
|
62
|
+
- Time-of-check-time-of-use races in security-relevant code (auth state read, then mutated, without locking).
|
|
63
|
+
- Permissive CORS / Caddy config without justification.
|
|
64
|
+
- Dependency added from a non-standard registry / pinned to a tag instead of a hash for sensitive packages.
|
|
65
|
+
|
|
66
|
+
**Low-severity (hardening recommendation — verdict 'pass' with notes):**
|
|
67
|
+
- Missing rate limiting on a public endpoint that doesn't yet need it.
|
|
68
|
+
- Could-be-tighter input validation that isn't currently exploitable.
|
|
69
|
+
- Missing security headers (HSTS, X-Frame-Options) on a surface where they'd be belt-and-braces.
|
|
70
|
+
|
|
71
|
+
## How you work
|
|
72
|
+
|
|
73
|
+
1. Walk the diff. For every NEW or CHANGED route handler / DB write / external API call / fs operation / template rendering, ask: what's the threat model here? Is the auth gate present? Is input sanitized? Is the secret handling right?
|
|
74
|
+
|
|
75
|
+
2. For every NEW dependency introduced via package.json or imports: is it from a reputable source? Does it match the package-lock.json hash if security-sensitive?
|
|
76
|
+
|
|
77
|
+
3. Spend Reads where the diff alone leaves a question open (e.g., new route — Read the auth.js to see what \`requireRank\` actually does; new query — Read the db.js to see if there's a parameterization helper).
|
|
78
|
+
|
|
79
|
+
4. Score \`security_score\` (0-10):
|
|
80
|
+
- 10 = production-quality, no exploitable patterns, hardening choices are sound.
|
|
81
|
+
- 8 = clean; one or two low-severity hardening notes.
|
|
82
|
+
- 6 = ships but with at least one named medium-severity defense-in-depth gap. (Threshold for passing the gate.)
|
|
83
|
+
- 4 = one high-severity issue found.
|
|
84
|
+
- 2 = multiple high-severity issues OR one critical-severity issue.
|
|
85
|
+
- 0 = clear critical exposure (auth bypass, injection, hardcoded credential).
|
|
86
|
+
|
|
87
|
+
5. Map severities to issue.severity: critical → \`blocker\`, high → \`blocker\`, medium → \`major\`, low → \`minor\`.
|
|
88
|
+
|
|
89
|
+
6. Confidence (0-1): if the diff touches a surface you can't fully evaluate within budget (large refactor to auth.js, new external API integration where you can't see the SDK's contract), set confidence LOW (< 0.4). Honest uncertainty > over-confident pass.
|
|
90
|
+
|
|
91
|
+
## Sanity checks
|
|
92
|
+
|
|
93
|
+
- A PASS verdict on a diff that touched route handlers must affirmatively name which auth wrapper protects each new/changed handler. "No security issues found" with no specifics is not a valid PASS.
|
|
94
|
+
- A FAIL verdict requires at least one issue. Name the specific line.
|
|
95
|
+
- A score below 6 with no \`major\`-or-\`blocker\` issue is inconsistent — name the high-or-critical finding.
|
|
96
|
+
- Don't moralize about style. Don't flag patterns that are normal for this codebase if the surrounding code does the same thing safely (e.g., bearer-token auth is fine even though cookie auth would have CSRF concerns).
|
|
97
|
+
- Trust-boundary rule (ADR 0016) is load-bearing: if a code change implies that editing a local file (CLAUDE.md, a skill, a hook, settings.json) could grant a builder authority they don't have in the DB — that's critical. Server-side rank checks must be re-read on every privileged request.
|
|
98
|
+
|
|
99
|
+
## Return ONLY JSON
|
|
100
|
+
|
|
101
|
+
No prose, no markdown fences:
|
|
102
|
+
|
|
103
|
+
\`\`\`
|
|
104
|
+
{
|
|
105
|
+
"security_score": <number 0-10>,
|
|
106
|
+
"confidence": <number 0-1>,
|
|
107
|
+
"reads_used": <integer 0-5>,
|
|
108
|
+
"surfaces_checked": [
|
|
109
|
+
{ "kind": "route"|"db_write"|"fs_op"|"external_api"|"template"|"secret_handling"|"auth_wrapper"|"other", "where": "<file:line OR description>", "verdict": "ok"|"flagged" }
|
|
110
|
+
],
|
|
111
|
+
"issues": [
|
|
112
|
+
{ "severity": "blocker"|"major"|"minor"|"nit", "file": "<path>", "summary": "<one line, names the security pattern and the specific risk>" }
|
|
113
|
+
],
|
|
114
|
+
"notes_md": "<short markdown — what surfaces you checked, what the threat model is, what you could not evaluate within budget>"
|
|
115
|
+
}
|
|
116
|
+
\`\`\`
|
|
117
|
+
|
|
118
|
+
You have a Read tool with a hard budget of 5 calls. Do not run tests, do not edit files, do not call the network.`;
|
|
119
|
+
|
|
120
|
+
function buildPrompt({ task, valueSummary, diff, changedFiles, deterministicFindings }) {
|
|
121
|
+
const t = task || {};
|
|
122
|
+
const findings = Array.isArray(deterministicFindings) ? deterministicFindings : [];
|
|
123
|
+
|
|
124
|
+
// Hacker owns a deterministic route-rank pre-check section before the diff,
|
|
125
|
+
// present only when the pre-pass produced findings.
|
|
126
|
+
const findingsLines = [];
|
|
127
|
+
if (findings.length > 0) {
|
|
128
|
+
findingsLines.push('---');
|
|
129
|
+
findingsLines.push('## Deterministic route-rank pre-check (INPUT for your adjudication)');
|
|
130
|
+
findingsLines.push('');
|
|
131
|
+
findingsLines.push('A deterministic check already ran over `src/bongos/routes/`. It flags routes it could NOT classify to a known rank — it found neither a `requireRank`/`requireBuilder` middleware nor a `rank:` annotation. Clearly-ungated WRITE routes are already a hard block; your job is to adjudicate INTENT for each flag below:');
|
|
132
|
+
findingsLines.push('');
|
|
133
|
+
findingsLines.push('- **Forgotten gate** → confirm it as a critical authz finding (`blocker`), naming the missing check per ADR 0016.');
|
|
134
|
+
findingsLines.push('- **Intentionally public** route that merely lacks the annotation → low-severity (`minor`): recommend adding a `rank:` annotation so the gate is verifiable. Do not score it as an exposure.');
|
|
135
|
+
findingsLines.push('');
|
|
136
|
+
// Defense-in-depth: route/file come from parsed source, so a builder could
|
|
137
|
+
// craft a path or `rank:` comment carrying instruction text. Strip control
|
|
138
|
+
// chars, Unicode bidi overrides (U+200E–200F, U+202A–202E, U+2066–2069),
|
|
139
|
+
// backticks, and the bracket chars used in the line template, then cap
|
|
140
|
+
// length — so a finding line can't break out and steer the LLM.
|
|
141
|
+
// On top of the shared SR-15 scrub (control + zero-width + bidi chars,
|
|
142
|
+
// fence.js), this single-line list template also collapses whitespace and
|
|
143
|
+
// strips backticks + the bracket chars of the `- [sev] route (file)` slot,
|
|
144
|
+
// then caps length \u2014 so a finding can't break out of its slot.
|
|
145
|
+
const safe = (s) => scrubUntrusted(s)
|
|
146
|
+
.replace(/[`[\]]/g, ' ')
|
|
147
|
+
.replace(/\s+/g, ' ').trim().slice(0, 120);
|
|
148
|
+
for (const f of findings) {
|
|
149
|
+
findingsLines.push(`- [${safe(f.severity)}] ${safe(f.route)} (${safe(f.file)})`);
|
|
150
|
+
}
|
|
151
|
+
findingsLines.push('');
|
|
152
|
+
findingsLines.push('Use a Read on the flagged route file (within budget) to decide which case applies.');
|
|
153
|
+
findingsLines.push('');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return buildWorkerPrompt({
|
|
157
|
+
header: PROMPT_HEADER,
|
|
158
|
+
task: t,
|
|
159
|
+
valueSummary,
|
|
160
|
+
diff,
|
|
161
|
+
changedFiles,
|
|
162
|
+
taskHeader: '## Task (context — Narc judges completion; you judge security)',
|
|
163
|
+
descLabel: '**Description:**',
|
|
164
|
+
emptyFilesText: '(no files changed — this is suspicious)',
|
|
165
|
+
readFilesHint: 'You can Read any of these files to see their post-merge state (5-call budget).',
|
|
166
|
+
finalInstruction: 'Now red-team. Default-fail unless the security-relevant surfaces affirmatively check out. Output ONLY the JSON object.',
|
|
167
|
+
beforeDiffLines: findingsLines,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// #79 (#493): delegate to the shared robust extractor so the v4 panel path
|
|
172
|
+
// gets the same parse-resilience (whole-string -> fenced -> balanced-brace) as
|
|
173
|
+
// grader.js, instead of the brittle first-{-to-last-} copy that flaked.
|
|
174
|
+
const { extractJson } = require('./extract-json');
|
|
175
|
+
|
|
176
|
+
// Hacker's per-worker verdict. Severity mapping (aligned with the existing
|
|
177
|
+
// /builder-redteam skill):
|
|
178
|
+
// critical / high → issue severity 'blocker' → worker verdict 'fail'
|
|
179
|
+
// medium → issue severity 'major' → worker verdict 'concerns'
|
|
180
|
+
// low → issue severity 'minor' → does not change verdict
|
|
181
|
+
function computeVerdict(parsed, meta = {}) {
|
|
182
|
+
if (meta.subprocess_error) {
|
|
183
|
+
return failResult({ notesMd: `Hacker: subagent error (${meta.subprocess_error}).`, error: meta.subprocess_error });
|
|
184
|
+
}
|
|
185
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
186
|
+
return failResult({ notesMd: 'Hacker: could not parse subagent output as JSON.', error: 'parse_error' });
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const sec = Number(parsed.security_score);
|
|
190
|
+
const { conf, issues, notesFromSubagent } = parseCommon(parsed);
|
|
191
|
+
const surfacesChecked = Array.isArray(parsed.surfaces_checked) ? parsed.surfaces_checked : [];
|
|
192
|
+
|
|
193
|
+
if (!Number.isFinite(sec) || sec < 0 || sec > 10) {
|
|
194
|
+
return failResult({ issues, notesMd: `Hacker: security_score was non-numeric or out of range (got ${parsed.security_score}).`, error: 'schema_error' });
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const secR = Math.round(sec * 10) / 10;
|
|
198
|
+
const blockerCount = issues.filter((i) => i.severity === 'blocker').length;
|
|
199
|
+
const majorCount = issues.filter((i) => i.severity === 'major').length;
|
|
200
|
+
const lowConfidence = conf != null && conf < LOW_CONF;
|
|
201
|
+
|
|
202
|
+
let verdict;
|
|
203
|
+
let notesPrefix;
|
|
204
|
+
if (blockerCount > 0 || secR < THRESHOLD) {
|
|
205
|
+
verdict = 'fail';
|
|
206
|
+
notesPrefix = `Hacker — FAIL (sec=${secR}/10`
|
|
207
|
+
+ (blockerCount > 0 ? `, ${blockerCount} critical/high finding${blockerCount === 1 ? '' : 's'}` : '')
|
|
208
|
+
+ `)`;
|
|
209
|
+
} else if (lowConfidence || majorCount > 0) {
|
|
210
|
+
verdict = 'concerns';
|
|
211
|
+
notesPrefix = `Hacker — CONCERNS (sec=${secR}/10`
|
|
212
|
+
+ (lowConfidence ? `, low confidence ${conf}` : '')
|
|
213
|
+
+ (majorCount > 0 ? `, ${majorCount} medium-severity finding${majorCount === 1 ? '' : 's'}` : '')
|
|
214
|
+
+ `)`;
|
|
215
|
+
} else {
|
|
216
|
+
verdict = 'pass';
|
|
217
|
+
notesPrefix = `Hacker — PASS (sec=${secR}/10, ${surfacesChecked.length} surface${surfacesChecked.length === 1 ? '' : 's'} checked, conf=${conf ?? '?'})`;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return finalizeVerdict({
|
|
221
|
+
verdict,
|
|
222
|
+
scores: { security_score: secR },
|
|
223
|
+
issues,
|
|
224
|
+
extra: { surfaces_checked: surfacesChecked },
|
|
225
|
+
notesPrefix,
|
|
226
|
+
notesFromSubagent,
|
|
227
|
+
confidence: conf,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
module.exports = {
|
|
232
|
+
KIND,
|
|
233
|
+
NAME,
|
|
234
|
+
SPECIALTY,
|
|
235
|
+
PROMPT_HEADER,
|
|
236
|
+
buildPrompt,
|
|
237
|
+
extractJson,
|
|
238
|
+
computeVerdict,
|
|
239
|
+
};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// MAS Phase 2.0 (#410) — Worker panel registry + shared runner.
|
|
2
|
+
//
|
|
3
|
+
// Each worker (narc.js, quality.js, …) exports:
|
|
4
|
+
// KIND, NAME, SPECIALTY — identification
|
|
5
|
+
// buildPrompt({...}) — produces the subagent prompt
|
|
6
|
+
// extractJson(rawString) — parses the subagent's JSON response
|
|
7
|
+
// computeVerdict(parsed, meta) — returns a partial WorkerResult
|
|
8
|
+
//
|
|
9
|
+
// runWorker() ties them together: build prompt → spawn subagent (via the
|
|
10
|
+
// existing grader.runSubagent) → parse → compute verdict → assemble the
|
|
11
|
+
// final WorkerResult (kind/name/scores/verdict/issues/notes/...).
|
|
12
|
+
//
|
|
13
|
+
// The DEFAULT_PANEL is the set of workers run by gradeSubagent today.
|
|
14
|
+
// Phase 2.0 ships narc + quality. Phase 2.1 will add 'hacker'. Phase 2.2
|
|
15
|
+
// will add 'efficiency'.
|
|
16
|
+
|
|
17
|
+
const narc = require('./narc');
|
|
18
|
+
const quality = require('./quality');
|
|
19
|
+
const hacker = require('./hacker');
|
|
20
|
+
const efficiency = require('./efficiency');
|
|
21
|
+
|
|
22
|
+
const REGISTRY = {
|
|
23
|
+
[narc.KIND]: narc,
|
|
24
|
+
[quality.KIND]: quality,
|
|
25
|
+
[hacker.KIND]: hacker,
|
|
26
|
+
[efficiency.KIND]: efficiency,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// The active panel for the ship-time gate. Order is presentation-only —
|
|
30
|
+
// workers run in parallel inside gradeSubagent.
|
|
31
|
+
const DEFAULT_PANEL = [narc.KIND, quality.KIND, hacker.KIND, efficiency.KIND];
|
|
32
|
+
|
|
33
|
+
// #465: transient subprocess/parse errors are infra noise, not a quality
|
|
34
|
+
// signal — auto-retry the worker ONCE on these before letting the error stand.
|
|
35
|
+
// Deliberately EXCLUDES:
|
|
36
|
+
// - SUBAGENT_TIMEOUT — a real budget signal (the worker ran out of wall-clock;
|
|
37
|
+
// retrying just burns another timeout). Handled via per-worker timeouts (#467).
|
|
38
|
+
// - null / a real verdict — that's signal, never retried.
|
|
39
|
+
// One retry only — never erodes the gate's strictness, just absorbs the ~1-in-3
|
|
40
|
+
// good ships that were flaking on a single noisy subagent (see #465 desc).
|
|
41
|
+
const TRANSIENT_WORKER_ERRORS = new Set([
|
|
42
|
+
'parse_error',
|
|
43
|
+
'schema_error',
|
|
44
|
+
'SUBAGENT_SPAWN_FAILED',
|
|
45
|
+
'SUBAGENT_NONZERO_EXIT',
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
// #467: per-worker subagent timeout. The global 240s applied to EVERY worker,
|
|
49
|
+
// which timed out the Read-heavy ones (Narc walks ACs + reads files — hence
|
|
50
|
+
// Phase 2.0.5's 5-read workaround; Quality is next-heaviest) while the light
|
|
51
|
+
// ones (Hacker, Efficiency) never needed that long. Per-worker budgets let the
|
|
52
|
+
// heavy lenses breathe without globally inflating every ship's worst-case wall
|
|
53
|
+
// time. A worker module may override by exporting its own MAX_TIMEOUT_MS;
|
|
54
|
+
// otherwise this map (keyed by KIND) is the single tuning surface. Falls back
|
|
55
|
+
// to runOpts.timeoutMs (then runSubagent's own 240s default) for any unlisted
|
|
56
|
+
// worker. Tune from the calibration data (#292) once it accrues.
|
|
57
|
+
const WORKER_MAX_TIMEOUT_MS = {
|
|
58
|
+
narc: 360_000, // Read-heavy: walks every acceptance criterion
|
|
59
|
+
quality: 360_000, // Read-heavy: reads changed files for cleanliness review
|
|
60
|
+
hacker: 240_000, // lighter: focused security scan
|
|
61
|
+
efficiency: 240_000, // lighter: focused performance scan
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Resolve the timeout for a worker: explicit module override > KIND map >
|
|
65
|
+
// caller's runOpts > undefined (runSubagent applies its own default).
|
|
66
|
+
function timeoutForWorker(worker, runOpts) {
|
|
67
|
+
return (
|
|
68
|
+
worker.MAX_TIMEOUT_MS ??
|
|
69
|
+
WORKER_MAX_TIMEOUT_MS[worker.KIND] ??
|
|
70
|
+
runOpts?.timeoutMs
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Resolve a list of worker kinds to their modules. Throws on unknown kinds
|
|
75
|
+
// so a typo in a custom panel surfaces immediately, not as a silent skip.
|
|
76
|
+
function resolvePanel(kinds) {
|
|
77
|
+
const out = [];
|
|
78
|
+
for (const k of kinds) {
|
|
79
|
+
const mod = REGISTRY[k];
|
|
80
|
+
if (!mod) throw new Error(`unknown worker kind: ${k}. Known: ${Object.keys(REGISTRY).join(', ')}`);
|
|
81
|
+
out.push(mod);
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Runs one worker end-to-end. Returns a WorkerResult — always; subprocess /
|
|
87
|
+
// parse / schema errors become a verdict='fail' result with an error tag, so
|
|
88
|
+
// the caller can write the audit-trail row regardless.
|
|
89
|
+
//
|
|
90
|
+
// runSubagentFn is injected to avoid a circular dependency between
|
|
91
|
+
// grader-workers/* and grader.js (grader.js requires this module).
|
|
92
|
+
//
|
|
93
|
+
// opts:
|
|
94
|
+
// model the grader model for this worker (selected by caller)
|
|
95
|
+
// runOpts passed to runSubagentFn (timeout, cwd, etc.)
|
|
96
|
+
//
|
|
97
|
+
// The subagent's raw stdout + run timing + any subprocess error are surfaced
|
|
98
|
+
// onto the WorkerResult so aggregatePanel can decide pass/concerns/fail
|
|
99
|
+
// without knowing about the runSubagent internals. ("shot" is v3 multi-shot
|
|
100
|
+
// terminology; v4 calls these workers — but the subprocess plumbing is the
|
|
101
|
+
// same shape underneath.)
|
|
102
|
+
async function runWorker(worker, { task, valueSummary, diff, changedFiles, diffStats, model, runOpts, runSubagentFn, extractAssistantResultFn, deterministicFindings }) {
|
|
103
|
+
// deterministicFindings (route-rank pre-pass, #475) is forwarded to every
|
|
104
|
+
// worker's buildPrompt; only the Hacker reads it — the others ignore the
|
|
105
|
+
// extra field, so this is a no-op for narc/quality/efficiency.
|
|
106
|
+
const prompt = worker.buildPrompt({ task, valueSummary, diff, changedFiles, diffStats, deterministicFindings });
|
|
107
|
+
|
|
108
|
+
// One subagent attempt → verdict. Pulled out so #465 can re-run it once on a
|
|
109
|
+
// transient error without duplicating the spawn/parse/verdict plumbing.
|
|
110
|
+
// #467: per-worker timeout (Read-heavy workers get longer; see the map above).
|
|
111
|
+
const timeoutMs = timeoutForWorker(worker, runOpts);
|
|
112
|
+
async function attempt() {
|
|
113
|
+
let raw = null;
|
|
114
|
+
let runMs = null;
|
|
115
|
+
let costUsd = null;
|
|
116
|
+
let subprocessError = null;
|
|
117
|
+
const t0 = Date.now();
|
|
118
|
+
try {
|
|
119
|
+
const { stdout, run_ms, cost_usd } = await runSubagentFn({ prompt, opts: { ...runOpts, model, timeoutMs } });
|
|
120
|
+
runMs = run_ms;
|
|
121
|
+
// #486 (ADR 0028 path 1): runSubagent attaches the `claude -p` envelope's
|
|
122
|
+
// total_cost_usd. Carry it out so aggregatePanel can sum the panel's own
|
|
123
|
+
// API spend into panel_cost_usd → cost_log (source=grader).
|
|
124
|
+
costUsd = cost_usd ?? null;
|
|
125
|
+
raw = extractAssistantResultFn ? extractAssistantResultFn(stdout) : stdout;
|
|
126
|
+
} catch (err) {
|
|
127
|
+
runMs = err.run_ms ?? (Date.now() - t0);
|
|
128
|
+
subprocessError = err.code || 'UNKNOWN';
|
|
129
|
+
}
|
|
130
|
+
const parsed = subprocessError
|
|
131
|
+
? null
|
|
132
|
+
: (typeof raw === 'string' ? worker.extractJson(raw) : raw);
|
|
133
|
+
const verdict = worker.computeVerdict(parsed, {
|
|
134
|
+
model,
|
|
135
|
+
run_ms: runMs,
|
|
136
|
+
subprocess_error: subprocessError,
|
|
137
|
+
});
|
|
138
|
+
return { verdict, runMs, costUsd };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
let { verdict, runMs, costUsd } = await attempt();
|
|
142
|
+
// #465: retry ONCE on a transient error (the freshest attempt wins, even if it
|
|
143
|
+
// also errored — one retry only). A real verdict or a SUBAGENT_TIMEOUT is
|
|
144
|
+
// never retried. NB (#486): the freshest attempt's cost wins; a transient
|
|
145
|
+
// first attempt's spend is not added (slight, rare undercount).
|
|
146
|
+
let retried = false;
|
|
147
|
+
if (TRANSIENT_WORKER_ERRORS.has(verdict.error)) {
|
|
148
|
+
retried = true;
|
|
149
|
+
({ verdict, runMs, costUsd } = await attempt());
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
kind: worker.KIND,
|
|
154
|
+
name: worker.NAME,
|
|
155
|
+
specialty: worker.SPECIALTY,
|
|
156
|
+
verdict: verdict.verdict,
|
|
157
|
+
scores: verdict.scores || {},
|
|
158
|
+
issues: verdict.issues || [],
|
|
159
|
+
notes_md: verdict.notes_md || '',
|
|
160
|
+
confidence: verdict.confidence ?? null,
|
|
161
|
+
model,
|
|
162
|
+
run_ms: runMs,
|
|
163
|
+
cost_usd: costUsd, // #486: this worker's own subprocess API spend (USD)
|
|
164
|
+
retried,
|
|
165
|
+
error: verdict.error ?? null,
|
|
166
|
+
// Narc-specific (carried opaquely; aggregatePanel doesn't need to know):
|
|
167
|
+
...(verdict.ac_checklist ? { ac_checklist: verdict.ac_checklist } : {}),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
module.exports = {
|
|
172
|
+
REGISTRY,
|
|
173
|
+
DEFAULT_PANEL,
|
|
174
|
+
resolvePanel,
|
|
175
|
+
runWorker,
|
|
176
|
+
timeoutForWorker, // public surface; WORKER_MAX_TIMEOUT_MS stays module-internal
|
|
177
|
+
TRANSIENT_WORKER_ERRORS,
|
|
178
|
+
// re-export per-worker modules for direct access by tests
|
|
179
|
+
narc,
|
|
180
|
+
quality,
|
|
181
|
+
hacker,
|
|
182
|
+
efficiency,
|
|
183
|
+
};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// MAS Phase 2.0 (#410) — Narc worker.
|
|
2
|
+
//
|
|
3
|
+
// Specialty: semantic completion. Walks the task description's acceptance
|
|
4
|
+
// criteria line by line, verifies each in the diff or (via Read) the post-
|
|
5
|
+
// merge file state, and flags any AC that isn't satisfied. Reports a
|
|
6
|
+
// `functional_fidelity` score (0-10) + a per-AC checklist.
|
|
7
|
+
//
|
|
8
|
+
// Replaces the ff axis of the v3 generalist grader. cq + economy are
|
|
9
|
+
// handled by the Quality worker (until Phase 2.1+ specializes them).
|
|
10
|
+
|
|
11
|
+
// THRESHOLD + LOW_CONF come from the shared rubric module (task 1090, C6) — a
|
|
12
|
+
// bump to grader-rubric.json drives every per-worker verdict without code edits.
|
|
13
|
+
const { THRESHOLD, LOW_CONF } = require('./rubric');
|
|
14
|
+
|
|
15
|
+
// SR-15 / G1 (#995): wrap all builder-controlled inputs in a scrubbed, fenced
|
|
16
|
+
// block the model is told to treat as DATA, never instructions. The shared
|
|
17
|
+
// scaffold (worker-prompt) owns fenceBlock/scrubUntrusted/NOFOLLOW_PREAMBLE.
|
|
18
|
+
const { buildWorkerPrompt, LLM_PROJECT } = require('./worker-prompt');
|
|
19
|
+
const { failResult, parseCommon, finalizeVerdict } = require('./worker-verdict');
|
|
20
|
+
|
|
21
|
+
const KIND = 'narc';
|
|
22
|
+
const NAME = 'Narc';
|
|
23
|
+
const SPECIALTY = 'semantic completion (description vs diff, line-level)';
|
|
24
|
+
|
|
25
|
+
const PROMPT_HEADER = `You are the **Narc** — a specialist adversarial subagent for the ${LLM_PROJECT} project. You exist to catch the single most common form of shipped-but-broken work: the task whose acceptance criteria were not actually satisfied by the diff.
|
|
26
|
+
|
|
27
|
+
Your ONLY job is semantic completion. You do NOT score code quality, security, or economy — other specialists handle those. Your verdict is about whether the description was implemented.
|
|
28
|
+
|
|
29
|
+
**The default verdict is FAIL.** You PASS only after walking the description's acceptance criteria and finding affirmative evidence that EACH ONE is satisfied or explicitly out-of-scope per the description's own words.
|
|
30
|
+
|
|
31
|
+
## Read budget (CRITICAL)
|
|
32
|
+
|
|
33
|
+
**You have a hard budget of 5 Read calls per grade.** This is a calibration constraint — you previously deterministically timed out by Read-verifying every AC. The fix is to be selective.
|
|
34
|
+
|
|
35
|
+
**Prefer the diff over Read.** Most ACs are visible in the diff: a new function, a comment update, an ADR section, a test file added, a constant changed. If the diff text shows what the AC claims, that's evidence — you do NOT need to Read the file. Mark it \`diff-confirmed\`.
|
|
36
|
+
|
|
37
|
+
**Only spend a Read on ACs that need it.** Read is for: verifying that a deletion is unreferenced elsewhere, that a rename's call sites all updated, that behavior promised in the description (but not visible in the hunk) is actually present in the post-merge file. If an AC is plainly visible in the diff, do NOT Read.
|
|
38
|
+
|
|
39
|
+
**If you exhaust the budget,** mark remaining ACs that would have needed a Read with status \`unverified-budget\` rather than chasing each one. The verdict logic treats \`unverified-budget\` neutrally — it doesn't drag your score down unless a majority of ACs land in that bucket.
|
|
40
|
+
|
|
41
|
+
## How you work
|
|
42
|
+
|
|
43
|
+
1. Read the task description (provided below). Find every acceptance criterion. ACs typically live under "Acceptance:" or "Acceptance criteria:" headers but may be stated as bullet points anywhere in the description.
|
|
44
|
+
|
|
45
|
+
2. For each AC, build a checklist entry. Status is one of:
|
|
46
|
+
- **diff-confirmed** — the AC is plainly visible in the diff text below. You quote the diff line. No Read needed.
|
|
47
|
+
- **satisfied** — you used a Read call to verify the AC in the post-merge file state. You name the file:line.
|
|
48
|
+
- **partial** — the AC is partly implemented but a named gap remains. You describe the gap.
|
|
49
|
+
- **missing** — the AC is not implemented at all. You describe what's missing.
|
|
50
|
+
- **out-of-scope** — the description itself explicitly excludes this. Quote where it says so.
|
|
51
|
+
- **unverified-budget** — would have needed a Read but the budget is exhausted. The diff is ambiguous on this AC; you couldn't reach the file. (Use sparingly — this is a confession, not an escape hatch.)
|
|
52
|
+
|
|
53
|
+
3. Score functional_fidelity (0-10) based on the checklist. \`diff-confirmed\` counts the same as \`satisfied\` for scoring. \`unverified-budget\` is neutral (doesn't push the score up or down by itself) unless it dominates:
|
|
54
|
+
- 10 = every AC is satisfied / diff-confirmed / out-of-scope; no gaps anywhere.
|
|
55
|
+
- 8 = every AC satisfied or diff-confirmed; minor polish items remain.
|
|
56
|
+
- 6 = mostly there with ONE named partial OR a few unverified-budget items mixed with satisfied. (Threshold for passing the gate.)
|
|
57
|
+
- 4 = multiple partials OR one missing AC OR most ACs are unverified-budget.
|
|
58
|
+
- 2 = mostly missing; the diff implements a different thing.
|
|
59
|
+
- 0 = the diff does not implement the described work at all.
|
|
60
|
+
|
|
61
|
+
4. For each **partial** or **missing** AC, write an issue with severity (\`blocker\` for missing, \`major\` for partial) — file is the file the AC should have touched, summary is one line naming the gap.
|
|
62
|
+
|
|
63
|
+
5. Confidence (0-1): how sure are you of the score? If the description is too vague to grade against, or you couldn't reach key files within budget — set confidence LOW (< 0.4). The downstream system treats low confidence as fall-through.
|
|
64
|
+
|
|
65
|
+
## Sanity checks
|
|
66
|
+
|
|
67
|
+
- A PASS verdict with no \`ac_checklist\` entries is invalid — you must enumerate the ACs you verified.
|
|
68
|
+
- A FAIL verdict with no \`issues\` entries is invalid — name at least one missing AC.
|
|
69
|
+
- A score of 6+ requires no missing ACs and at most one partial.
|
|
70
|
+
- "Acceptance: tests pass" is NOT a valid AC verification on your part — you can't run tests. If the diff adds a test for the named behavior, that's \`diff-confirmed\`. If the test is in a file the diff doesn't fully show, that's worth ONE Read.
|
|
71
|
+
- If you find yourself wanting to Read every file mentioned by every AC, stop. Re-check whether the diff already shows it. The diff text is your primary evidence.
|
|
72
|
+
|
|
73
|
+
## Return ONLY JSON
|
|
74
|
+
|
|
75
|
+
No prose before or after, no markdown fences:
|
|
76
|
+
|
|
77
|
+
\`\`\`
|
|
78
|
+
{
|
|
79
|
+
"functional_fidelity": <number 0-10>,
|
|
80
|
+
"confidence": <number 0-1>,
|
|
81
|
+
"reads_used": <integer 0-5>,
|
|
82
|
+
"ac_checklist": [
|
|
83
|
+
{ "ac": "<string — the AC as written in the description>", "status": "diff-confirmed"|"satisfied"|"partial"|"missing"|"out-of-scope"|"unverified-budget", "evidence": "<diff line OR file:line OR quoted text>" }
|
|
84
|
+
],
|
|
85
|
+
"issues": [
|
|
86
|
+
{ "severity": "blocker"|"major"|"minor"|"nit", "file": "<path>", "summary": "<one line>" }
|
|
87
|
+
],
|
|
88
|
+
"notes_md": "<short markdown — what you verified, what gaps you found, what you couldn't reach within budget>"
|
|
89
|
+
}
|
|
90
|
+
\`\`\`
|
|
91
|
+
|
|
92
|
+
You have a Read tool with a hard budget of 5 calls. Do not run tests, do not edit files, do not call the network.`;
|
|
93
|
+
|
|
94
|
+
function buildPrompt({ task, valueSummary, diff, changedFiles }) {
|
|
95
|
+
const t = task || {};
|
|
96
|
+
// Narc's description fallback is uniquely "(no description — set confidence
|
|
97
|
+
// LOW)" (the others use "(no description)"); the shared scaffold defaults to
|
|
98
|
+
// "(no description)", so pre-resolve the fallback here and hand it through.
|
|
99
|
+
// Truthy descriptions pass untouched, so the scaffold's own `|| ... .trim()`
|
|
100
|
+
// stays byte-identical to the inlined version.
|
|
101
|
+
return buildWorkerPrompt({
|
|
102
|
+
header: PROMPT_HEADER,
|
|
103
|
+
task: { ...t, description: t.description || '(no description — set confidence LOW)' },
|
|
104
|
+
valueSummary,
|
|
105
|
+
diff,
|
|
106
|
+
changedFiles,
|
|
107
|
+
taskHeader: '## Task',
|
|
108
|
+
descLabel: '**Description (your source of truth for the ACs):**',
|
|
109
|
+
emptyFilesText: '(no files changed — this is suspicious; mark every AC as missing)',
|
|
110
|
+
readFilesHint: 'You can Read any of these files to see their post-merge state.',
|
|
111
|
+
finalInstruction: 'Now walk the ACs. Default-fail unless every one is satisfied or explicitly out-of-scope. Output ONLY the JSON object.',
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// #79 (#493): delegate to the shared robust extractor so the v4 panel path
|
|
116
|
+
// gets the same parse-resilience (whole-string -> fenced -> balanced-brace) as
|
|
117
|
+
// grader.js, instead of the brittle first-{-to-last-} copy that flaked.
|
|
118
|
+
const { extractJson } = require('./extract-json');
|
|
119
|
+
|
|
120
|
+
// Narc's per-worker verdict. Inputs:
|
|
121
|
+
// parsed: the JSON the subagent emitted (or null on parse failure)
|
|
122
|
+
// meta: { run_ms, model, etc. } — pass-through from runOneShot
|
|
123
|
+
// Output: a partial WorkerResult; runWorker fills in kind/name/etc.
|
|
124
|
+
function computeVerdict(parsed, meta = {}) {
|
|
125
|
+
// Errors short-circuit to 'fail' so the panel can decide what to do.
|
|
126
|
+
if (meta.subprocess_error) {
|
|
127
|
+
return failResult({ notesMd: `Narc: subagent error (${meta.subprocess_error}).`, error: meta.subprocess_error });
|
|
128
|
+
}
|
|
129
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
130
|
+
return failResult({ notesMd: 'Narc: could not parse subagent output as JSON.', error: 'parse_error' });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const ff = Number(parsed.functional_fidelity);
|
|
134
|
+
const { conf, issues, notesFromSubagent } = parseCommon(parsed);
|
|
135
|
+
const checklist = Array.isArray(parsed.ac_checklist) ? parsed.ac_checklist : [];
|
|
136
|
+
|
|
137
|
+
// Out-of-range or non-numeric ff → schema error → fail.
|
|
138
|
+
if (!Number.isFinite(ff) || ff < 0 || ff > 10) {
|
|
139
|
+
return failResult({ issues, notesMd: `Narc: functional_fidelity was non-numeric or out of range (got ${parsed.functional_fidelity}).`, error: 'schema_error' });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const ffR = Math.round(ff * 10) / 10;
|
|
143
|
+
const blockerCount = issues.filter((i) => i.severity === 'blocker').length;
|
|
144
|
+
const missingCount = checklist.filter((c) => c && c.status === 'missing').length;
|
|
145
|
+
const partialCount = checklist.filter((c) => c && c.status === 'partial').length;
|
|
146
|
+
// diff-confirmed counts as satisfied for scoring (Phase 2.0.5 #413).
|
|
147
|
+
const satisfiedCount = checklist.filter(
|
|
148
|
+
(c) => c && (c.status === 'satisfied' || c.status === 'diff-confirmed')
|
|
149
|
+
).length;
|
|
150
|
+
// unverified-budget is neutral by itself; concerns trip only if it dominates
|
|
151
|
+
// the checklist (more than half of the verifiable ACs landed there).
|
|
152
|
+
const unverifiedBudgetCount = checklist.filter(
|
|
153
|
+
(c) => c && c.status === 'unverified-budget'
|
|
154
|
+
).length;
|
|
155
|
+
const totalChecklist = checklist.length;
|
|
156
|
+
// Verifiable ACs = total minus out-of-scope (which is a positive verdict
|
|
157
|
+
// type, not a "couldn't verify" state).
|
|
158
|
+
const verifiableCount = checklist.filter(
|
|
159
|
+
(c) => c && c.status !== 'out-of-scope'
|
|
160
|
+
).length;
|
|
161
|
+
const unverifiedDominates =
|
|
162
|
+
verifiableCount > 0 && unverifiedBudgetCount * 2 > verifiableCount;
|
|
163
|
+
const lowConfidence = conf != null && conf < LOW_CONF;
|
|
164
|
+
|
|
165
|
+
let verdict;
|
|
166
|
+
let notesPrefix;
|
|
167
|
+
if (blockerCount > 0 || missingCount > 0 || ffR < THRESHOLD) {
|
|
168
|
+
verdict = 'fail';
|
|
169
|
+
notesPrefix = `Narc — FAIL (ff=${ffR}/10`
|
|
170
|
+
+ (missingCount > 0 ? `, ${missingCount} missing AC${missingCount === 1 ? '' : 's'}` : '')
|
|
171
|
+
+ (blockerCount > 0 ? `, ${blockerCount} blocker issue${blockerCount === 1 ? '' : 's'}` : '')
|
|
172
|
+
+ `)`;
|
|
173
|
+
} else if (lowConfidence || partialCount > 0 || unverifiedDominates) {
|
|
174
|
+
verdict = 'concerns';
|
|
175
|
+
notesPrefix = `Narc — CONCERNS (ff=${ffR}/10`
|
|
176
|
+
+ (lowConfidence ? `, low confidence ${conf}` : '')
|
|
177
|
+
+ (partialCount > 0 ? `, ${partialCount} partial AC${partialCount === 1 ? '' : 's'}` : '')
|
|
178
|
+
+ (unverifiedDominates ? `, ${unverifiedBudgetCount}/${verifiableCount} ACs unverified (budget)` : '')
|
|
179
|
+
+ `)`;
|
|
180
|
+
} else {
|
|
181
|
+
verdict = 'pass';
|
|
182
|
+
const verifiedStr = satisfiedCount === totalChecklist
|
|
183
|
+
? `${totalChecklist} AC${totalChecklist === 1 ? '' : 's'} verified`
|
|
184
|
+
: `${satisfiedCount} verified / ${unverifiedBudgetCount} unverified-budget / ${totalChecklist} total`;
|
|
185
|
+
notesPrefix = `Narc — PASS (ff=${ffR}/10, ${verifiedStr}, conf=${conf ?? '?'})`;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return finalizeVerdict({
|
|
189
|
+
verdict,
|
|
190
|
+
scores: { functional_fidelity: ffR },
|
|
191
|
+
issues,
|
|
192
|
+
extra: { ac_checklist: checklist },
|
|
193
|
+
notesPrefix,
|
|
194
|
+
notesFromSubagent,
|
|
195
|
+
confidence: conf,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
module.exports = {
|
|
200
|
+
KIND,
|
|
201
|
+
NAME,
|
|
202
|
+
SPECIALTY,
|
|
203
|
+
PROMPT_HEADER,
|
|
204
|
+
buildPrompt,
|
|
205
|
+
extractJson,
|
|
206
|
+
computeVerdict,
|
|
207
|
+
};
|