@bongos/core 1.19.715 → 1.19.725
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 +491 -421
- package/.claude/skills/backlog-review/SKILL.md +3 -3
- package/.claude/skills/blocker-review/SKILL.md +1 -1
- package/.claude/skills/blocker-solve/SKILL.md +2 -2
- package/.claude/skills/builder-reauth/SKILL.md +1 -1
- package/.claude/skills/builder-redteam/SKILL.md +1 -1
- package/.claude/skills/builder-ship/SKILL.md +1 -1
- package/.claude/skills/builder-start/SKILL.md +1 -1
- package/.claude/skills/design/SKILL.md +2 -2
- package/.claude/skills/feedback/SKILL.md +1 -1
- package/.claude/skills/goal-create/SKILL.md +1 -1
- package/.claude/skills/goal-review/SKILL.md +2 -2
- package/.claude/skills/idea-triage/SKILL.md +5 -5
- package/.claude/skills/merge-mode/SKILL.md +4 -4
- package/.claude/skills/new-project/SKILL.md +17 -17
- package/.claude/skills/planning-session/SKILL.md +11 -11
- package/.claude/skills/recall/SKILL.md +2 -2
- package/.claude/skills/strand-fix/SKILL.md +1 -1
- package/.devcontainer/README.md +2 -2
- package/CONTRIBUTING.md +2 -2
- package/GOVERNANCE.md +4 -4
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +4 -0
- package/clients/bongos-client/index.cjs +4 -0
- package/clients/bongos-client/index.d.ts +5 -0
- package/clients/bongos-client/index.mjs +4 -0
- package/config/branding.neutral.json +4 -2
- package/docs/adr/0001-stack-choice-single-vps.md +2 -2
- package/docs/adr/0002-digitalocean-over-hetzner.md +1 -1
- package/docs/adr/0008-google-chat-oauth-user-auth.md +1 -1
- package/docs/adr/0009-autotile-architecture.md +1 -1
- package/docs/adr/0011-terrain-id-rendering-model.md +3 -3
- package/docs/adr/0013-paths-as-object-overlays-with-autotile-dispatch.md +1 -1
- package/docs/adr/0014-families-canonical-over-vocabulary.md +1 -1
- package/docs/adr/0015-task-dependencies-and-auto-promotion.md +1 -1
- package/docs/adr/0016-trust-boundary-server-enforced-permissions.md +1 -1
- package/docs/adr/0018-three-rank-model-goes-live.md +3 -3
- package/docs/adr/0020-security-model-public-stub.md +9 -9
- package/docs/adr/0021-per-builder-skill-model-preferences.md +2 -2
- package/docs/adr/0022-secrets-policy.md +5 -5
- package/docs/adr/0024-cloneable-repo-local-first-memory.md +3 -3
- package/docs/adr/0024-multi-agent-system-architecture.md +10 -10
- package/docs/adr/0025-offsite-backup-vendor-digitalocean-spaces.md +1 -1
- package/docs/adr/0025-structured-criterion-task-link.md +1 -1
- package/docs/adr/0026-bfg-memory-hygiene-and-cross-builder-learning.md +13 -13
- package/docs/adr/0027-bfg-session-inefficiency-evaluator.md +14 -14
- package/docs/adr/0029-status-page-outage-resilience.md +1 -1
- package/docs/adr/0030-builders-hall-live-updates.md +1 -1
- package/docs/adr/0031-cloud-dev-environments-for-builders.md +7 -7
- package/docs/adr/0032-discord-mirror-of-gds.md +3 -3
- package/docs/adr/0033-discord-bot-service-principal.md +4 -4
- package/docs/adr/0034-thetes-graduated-newcomer-rank.md +1 -1
- package/docs/adr/0035-builder-onboarding-three-paths.md +4 -4
- package/docs/adr/0036-builders-subdomain-and-ui-reorg.md +1 -1
- package/docs/adr/0037-discord-channel-management.md +1 -1
- package/docs/adr/0038-chromebook-ttyd-cloudflare-tunnel.md +5 -5
- package/docs/adr/0039-setup-first-onboarding-ux.md +6 -6
- package/docs/adr/0040-remote-control-default-browser-onramp.md +3 -3
- package/docs/adr/0041-temporary-grader-bypass-killswitch.md +2 -2
- package/docs/adr/0042-builder-self-deploy-ci-auto-merge.md +5 -5
- package/docs/adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md +2 -2
- package/docs/adr/0044-mediterranean-palette-replacement.md +1 -1
- package/docs/adr/0044-per-box-live-game-preview.md +1 -1
- package/docs/adr/0046-sandbox-first-review-gate.md +1 -1
- package/docs/adr/0047-discord-bugs-intake-anti-abuse.md +1 -1
- package/docs/adr/0049-split-parallel-safety-contract.md +1 -1
- package/docs/adr/0050-device-flow-admission-invite-gated-by-default.md +2 -2
- package/docs/adr/0051-full-session-transcript-corpus.md +2 -2
- package/docs/adr/0052-sandbox-for-everyone-game-only-preview.md +1 -1
- package/docs/adr/0053-scoped-dev-box-session.md +1 -1
- package/docs/adr/0054-session-token-reward-cost-plus.md +7 -7
- package/docs/adr/0055-server-mediated-branch-publish.md +2 -2
- package/docs/adr/0056-prod-deploy-script-mirror-and-healthcheck-retry.md +3 -3
- package/docs/adr/0057-container-cost-ledger.md +1 -1
- package/docs/adr/0057-discord-archon-approval-channels.md +2 -2
- package/docs/adr/0058-automatic-gate-surface-gatekeeper.md +6 -6
- package/docs/adr/0059-single-approval-remove-devbox-approval-gate.md +11 -11
- package/docs/adr/0060-gds-retrieval-layer.md +3 -3
- package/docs/adr/0061-context-layer-decomposition.md +2 -2
- package/docs/adr/0062-medusa-instance-model-decoupling.md +5 -5
- package/docs/adr/0063-generated-repo-map-symbol-skeleton.md +2 -2
- package/docs/adr/0064-rename-medusa-to-cloud-bongos.md +3 -3
- package/docs/adr/0065-agpl-nonprofit-ai-first-governance.md +5 -5
- package/docs/adr/0066-generated-file-map-sections.md +2 -2
- package/docs/adr/0067-session-start-fast-forward-pull.md +1 -1
- package/docs/adr/0068-shared-art-key-for-newcomers.md +1 -1
- package/docs/adr/0069-hall-live-channel-sse-decouple.md +3 -3
- package/docs/adr/0070-deterministic-session-card-delivery.md +1 -1
- package/docs/adr/0071-box-confirm-before-destroyed-and-drift-reconcile.md +2 -2
- package/docs/adr/0072-bongos-app-mac-signed-first-windows-deferred.md +2 -2
- package/docs/adr/0072-dev-box-code-staleness-visibility.md +2 -2
- package/docs/adr/0073-builder-needs-signal-and-byok-gemini-key.md +3 -3
- package/docs/adr/0073-secrets-scan-exclude-uri-detector.md +2 -2
- package/docs/adr/0076-in-session-deterministic-compaction.md +2 -2
- package/docs/adr/0077-content-addressed-llm-cache.md +2 -2
- package/docs/adr/0078-deterministic-first-cron.md +3 -3
- package/docs/adr/0079-value-gated-autonomous-engagement.md +2 -2
- package/docs/adr/0080-llm-cache-api-transport-and-trust-model.md +3 -3
- package/docs/adr/0081-tool-agnostic-design-layer.md +3 -3
- package/docs/adr/0082-server-side-merge-conflict-auto-resolution.md +2 -2
- package/docs/adr/0083-modular-architecture-strangler-build-plan.md +3 -3
- package/docs/adr/0085-remove-default-per-builder-spend-cap.md +2 -2
- package/docs/adr/0086-goal-scoped-work-hierarchy.md +15 -15
- package/docs/adr/0087-bongos-app-architecture-and-handoff-contract.md +5 -5
- package/docs/adr/0087-compete-on-governance-not-tooling-cursor.md +1 -1
- package/docs/adr/0088-consistent-character-generative-animation.md +5 -5
- package/docs/adr/0089-modular-multi-model-adversarial-grader.md +15 -15
- package/docs/adr/0090-metic-task-authoring.md +8 -8
- package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +3 -3
- package/docs/adr/0092-hosting-module-and-on-prem-target.md +11 -11
- package/docs/adr/0093-tranche-2-core-carve-sequence.md +5 -5
- package/docs/adr/0094-repo-atlas-self-drawing-codebase-map.md +1 -1
- package/docs/adr/0095-borrowed-memory-and-retrieval-concepts.md +6 -6
- package/docs/adr/0095-cross-agent-context-management.md +5 -5
- package/docs/adr/0096-require-reward-before-workable.md +5 -5
- package/docs/adr/0097-one-active-claim-per-session-and-worktree-binding.md +2 -2
- package/docs/adr/0097-retroactive-reward-backfill.md +4 -4
- package/docs/adr/0098-public-mirror-publish-manifest.md +3 -3
- package/docs/adr/0099-delayed-redacted-mirror-export.md +1 -1
- package/docs/adr/0100-two-repo-instance-model.md +6 -6
- package/docs/adr/0101-goal-hierarchy-phase-5-judge-membership-reward.md +9 -9
- package/docs/adr/0102-finish-bounding-the-kernel.md +1 -1
- package/docs/adr/0103-core-first-extraction-cloud-bongos-trunk.md +6 -6
- package/docs/adr/0103-gdsv4-bongos-consolidation.md +3 -3
- package/docs/adr/0104-trust-gds-api-channel-in-auto-mode.md +3 -3
- package/docs/adr/0105-instance-seed-migrations-out-of-core.md +2 -2
- package/docs/adr/0106-goal-owner-manager-authority.md +2 -2
- package/docs/adr/0107-module-upstreaming-contribution-to-core-catalog.md +6 -6
- package/docs/adr/0108-instance-composition-configurable-root.md +6 -6
- package/docs/adr/0109-self-describing-openapi-and-hosted-docs.md +3 -3
- package/docs/adr/0110-untrack-whole-file-generated-nav-docs.md +1 -1
- package/docs/adr/0111-instance-hosting-provisioning-module.md +18 -18
- package/docs/adr/0112-private-goals-invitations-join-requests.md +7 -7
- package/docs/adr/0113-sandbox-studio-descope-superseded-by-0044-0052.md +1 -1
- package/docs/adr/0114-instance-docs-discovery-contract.md +4 -4
- package/docs/adr/0115-scheduled-routines-portability.md +1 -1
- package/docs/adr/0117-api-versioning-and-deprecation-policy.md +1 -1
- package/docs/adr/0118-api-contract-source-of-truth-code-first.md +1 -1
- package/docs/adr/0120-pay-on-land-and-builder-owned-rebase-gate.md +2 -2
- package/docs/adr/0121-greenfield-vs-brownfield-onboarding-adopt-existing-repo.md +1 -1
- package/docs/adr/0122-onboarding-diagram-renders-deploy-rendered-off-git.md +3 -3
- package/docs/adr/0123-box-idle-sweep-autosave-before-destroy.md +1 -1
- package/docs/adr/0124-typed-api-response-bodies.md +2 -2
- package/docs/adr/0125-control-plane-scaffolds-standalone-instance-repo.md +2 -2
- package/docs/adr/0126-dedicated-cloudbongos-control-plane-droplet.md +3 -3
- package/docs/adr/0127-cross-box-fleet-observability.md +1 -1
- package/docs/adr/0128-provisioning-runner-privilege-and-db-auth-model.md +3 -3
- package/docs/adr/0129-cloudbongos-control-plane-pull-deploy.md +4 -4
- package/docs/adr/0130-provision-remote-exec-over-ssh.md +4 -4
- package/docs/adr/0131-rank-scoped-skill-visibility.md +2 -2
- package/docs/adr/0132-cohost-fleet-control-plane-migration.md +2 -2
- package/docs/adr/0133-github-app-manifest-onboarding-signin.md +1 -1
- package/docs/adr/0134-private-first-npm-distribution.md +3 -3
- package/docs/adr/0135-module-upstream-submission-interim-queue.md +1 -1
- package/docs/adr/0136-update-channel-subscription-policy.md +2 -2
- package/docs/adr/0137-upstream-publish-policy-manual-owner-gated.md +6 -6
- package/docs/adr/0138-bundled-module-deps-declared-per-module.md +4 -4
- package/docs/adr/0142-project-context-is-prose-only.md +2 -2
- package/docs/adr/0143-onboarding-repo-picker-oauth-scope.md +2 -2
- package/docs/adr/0144-devbox-rehome-onto-cloudbongos-plane.md +2 -2
- package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +2 -2
- package/docs/adr/0146-configurable-reward-mode-cost-plus-only.md +4 -4
- package/docs/adr/0147-standalone-live-docs-regen.md +1 -1
- package/docs/adr/0149-bongos-dev-local-launcher.md +1 -1
- package/docs/adr/0150-box-first-boot-bringup-vendored-instances.md +3 -3
- package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +20 -20
- package/docs/adr/0152-landing-gate-served-by-the-core-app.md +2 -2
- package/docs/adr/0152-metic-task-abandonment.md +7 -7
- package/docs/adr/0153-sequential-chain-runner.md +1 -1
- package/docs/adr/0154-goal-owner-criterion-authoring.md +7 -7
- package/docs/adr/0155-adopt-private-repo-widen-oauth-scope.md +2 -2
- package/docs/adr/0156-user-set-display-name-wins.md +1 -1
- package/docs/adr/0157-archon-is-rank-and-identity-only.md +10 -10
- package/docs/adr/0158-choke-point-verdict-taxonomy.md +1 -1
- package/docs/adr/0159-merge-gate-reconciliation.md +1 -1
- package/docs/adr/0160-main-audit-repo-verifiable-caller.md +1 -1
- package/docs/adr/0161-publish-on-merge.md +2 -2
- package/docs/adr/0163-legacy-display-name-resolution.md +1 -1
- package/docs/adr/0165-instances-hookless-by-default.md +1 -1
- package/docs/adr/0166-module-maintenance-and-deprecation-policy.md +3 -3
- package/docs/adr/0167-gate-trust-link-agpl-default.md +2 -2
- package/docs/adr/0167-module-catalog-source-vs-provenance.md +3 -3
- package/docs/adr/0169-bongos-serve-server-bring-up.md +1 -1
- package/docs/adr/0171-profile-rollup-join-and-consent.md +1 -1
- package/docs/adr/0172-editable-rank-roles-substrate-axis.md +2 -2
- package/docs/adr/0172-per-craft-compensation-ideator-credit-lane.md +4 -4
- package/docs/adr/0173-legacy-multi-ship-shortfall-not-backfilled.md +1 -1
- package/docs/adr/0174-government-terminology-ranks-not-roles.md +1 -1
- package/docs/adr/0177-goal-membership-kind.md +3 -3
- package/docs/adr/0178-the-copy-desk-flag-and-queue.md +1 -1
- package/docs/adr/0179-board-membership-predicate-grammar.md +1 -1
- package/docs/adr/0181-teardown-state-gate-and-address-retention.md +1 -1
- package/docs/adr/0182-project-visibility-two-axes.md +1 -1
- package/docs/adr/0183-criteria-close-themselves.md +1 -1
- package/docs/adr/0184-ship-requires-an-assurance.md +1 -1
- package/docs/adr/0185-spark-handoff-credit-split.md +1 -1
- package/docs/adr/0186-per-project-idea-templates.md +1 -1
- package/docs/adr/0187-collab-four-decisions.md +1 -1
- package/docs/adr/0187-oauth-handshake-cookie-lifetime.md +1 -1
- package/docs/adr/0188-patrol-runs-on-ci-not-the-server.md +2 -2
- package/docs/adr/0189-baseline-floors-and-the-freeze-detector.md +2 -2
- package/docs/adr/0191-majority-and-the-author-who-may-not-decide-alone.md +1 -1
- package/docs/adr/0192-a-category-orients-and-authorises-nothing.md +2 -2
- package/docs/adr/0193-pause-task-scoped-box-slices.md +1 -1
- package/docs/adr/0195-adr-numbers-are-checked-like-migration-numbers.md +2 -2
- package/docs/adr/0196-chrome-world-token-contract-and-the-landing-sheets.md +2 -2
- package/docs/adr/0197-the-ui-design-module.md +1 -1
- package/docs/adr/0198-third-party-skill-vendoring-policy.md +1 -1
- package/docs/adr/0203-doorway-changelog-out-of-module-api.md +2 -2
- package/docs/adr/0204-the-apex-is-dark-only.md +2 -2
- package/docs/adr/0205-federated-checkin-needs-the-hubs-own-signin-witness.md +1 -1
- package/docs/adr/0206-own-scoped-session-revocation-no-absolute-ceiling.md +1 -1
- package/docs/adr/0207-connections-implementation-departures-and-honest-limits.md +1 -1
- package/docs/adr/0208-application-lifecycle-the-handle-waits-and-the-vouch-has-no-minter.md +2 -2
- package/docs/adr/0209-one-budget-for-the-account-existence-oracle.md +1 -1
- package/docs/adr/0210-scouting-graduates-on-an-instance-asserted-owner-claim.md +1 -1
- package/docs/adr/0212-connections-on-the-profile-surface-and-addressing.md +1 -1
- package/docs/adr/0213-platform-terms-acceptance-is-the-hubs-own-witness.md +2 -2
- package/docs/adr/0215-the-recruiter-sliver-is-a-ceiling-not-a-step.md +6 -6
- package/docs/adr/0216-a-fake-pool-interpreter-must-fail-loudly-not-silently-ignore.md +2 -2
- package/docs/adr/0217-rank-gates-inviting-not-viewing.md +1 -1
- package/docs/adr/0218-the-apex-root-web-surface.md +2 -2
- package/docs/adr/0219-a-look-is-a-branding-pack-the-style-library.md +1 -1
- package/docs/adr/0220-an-in-house-rebuilt-skill-is-a-first-party-skill.md +1 -1
- package/docs/adr/0221-the-impeccable-method-is-one-skill-with-sub-command-playbooks.md +2 -2
- package/docs/adr/0222-the-image-family-under-the-hero-only-rule.md +2 -2
- package/docs/adr/0223-the-detector-is-two-tiers-in-the-kit.md +3 -3
- package/docs/adr/0224-module-skills-reach-the-core-checkout-as-untracked-self-ignored-copies.md +1 -1
- package/docs/adr/0225-privacy-suppresses-cross-project-surfaces-only.md +1 -1
- package/docs/adr/0226-one-stale-timer-reporting-degrades-enforcement-refuses.md +1 -1
- package/docs/adr/0227-a-task-network-map-is-refused-the-goal-graph-is-the-map.md +1 -1
- package/docs/adr/0230-a-look-skill-is-a-composition-grammar-the-palette-is-the-pack.md +1 -1
- package/docs/adr/0231-the-style-session-an-owner-authors-a-look-inside-the-contract.md +2 -2
- package/docs/adr/0232-rot-is-derived-not-swept-and-water-is-the-only-new-verb.md +2 -2
- package/docs/adr/0233-a-copy-proposal-is-a-task-carrying-a-patch.md +2 -2
- package/docs/adr/0234-idea-routing-capture-time-promotion-landing-matrix-homeless-inbox.md +2 -2
- package/docs/adr/0235-a-fix-category-is-kindbug-under-a-goal-no-column-required.md +11 -11
- package/docs/adr/0236-many-ideas-one-task-the-lineage-key-is-the-pair.md +5 -5
- package/docs/adr/0237-a-starter-bundle-is-a-preset-over-the-always-on-core-keyed-by-declared-type.md +5 -5
- package/docs/adr/0238-the-join-door-is-a-provisioning-settings-policy-key.md +1 -1
- package/docs/adr/0239-a-recommendation-is-a-table-that-carries-its-own-reason.md +4 -4
- package/docs/adr/0240-a-skipped-module-picker-stores-nothing-and-resolves-the-bundle-on-read.md +4 -4
- package/docs/adr/0241-the-artist-gate-is-a-per-project-deploy-gate-that-reads-a-state.md +1 -1
- package/docs/adr/0242-a-cascade-is-a-declaration-table-on-the-event-that-already-exists.md +2 -2
- package/docs/adr/0243-a-bundle-adjustment-belongs-to-the-bundle-not-the-advice-about-it.md +4 -4
- package/docs/adr/0244-a-catalog-search-is-a-view-over-the-rows-never-an-edit-to-the-selection.md +3 -3
- package/docs/adr/0245-the-way-back-into-an-optional-step-is-that-step-s-own-answer-route.md +7 -7
- package/docs/adr/0246-catalog-membership-is-a-projection-not-a-federation-side-effect.md +1 -1
- package/docs/adr/0247-the-join-door-is-one-composed-answer-and-dark-matter-has-no-live-verdict-yet.md +2 -2
- package/docs/adr/0248-a-hub-project-s-owner-is-the-provisioning-row-carried-on-a-port.md +3 -3
- package/docs/adr/0249-the-invite-step-is-the-done-panel-s-first-act-not-a-rail-step.md +3 -3
- package/docs/adr/0250-strict-versioning-the-version-boundary-is-the-scope-gate.md +6 -6
- package/docs/adr/0251-a-suggestion-of-who-to-invite-is-a-recruiting-surface-and-owes-the-opt-out.md +5 -5
- package/docs/adr/0252-the-self-hosted-visibility-report-is-a-pull-and-auto-appear-buys-a-retraction-lever.md +19 -19
- package/docs/adr/0253-the-takedown-lever-has-two-writers-and-provenance-is-a-column.md +2 -2
- package/docs/adr/0254-a-relayed-link-is-contained-downward-or-it-is-not-published.md +6 -6
- package/docs/adr/0255-a-public-lists-ordering-is-part-of-its-payload.md +2 -2
- package/docs/adr/0256-the-visibility-ceiling-is-the-sign-in-gate-too-and-the-reader-moves-to-the-composer.md +3 -3
- package/docs/adr/0257-auth-resolves-before-the-hall-mounts-anything.md +1 -1
- package/docs/adr/0258-the-public-cli-is-a-generated-client-package-not-the-published-core.md +1 -1
- package/docs/adr/0259-a-projects-departure-from-the-public-list-is-public.md +7 -7
- package/docs/adr/0260-the-application-is-the-consent-and-the-echo-is-the-gate.md +4 -4
- package/docs/adr/0261-a-preselect-always-carries-a-reason-the-bundle-summary-is-the-floor.md +1 -1
- package/docs/adr/0262-a-bug-never-lands-in-the-inbox.md +1 -1
- package/docs/adr/0263-how-a-version-closes.md +3 -3
- package/docs/adr/0264-the-ten-working-areas.md +3 -3
- package/docs/adr/0265-work-with-no-goal-and-the-order-the-cut-needs.md +5 -5
- package/docs/adr/0266-the-board-room-is-its-own-surface-reachable-by-whoever-may-vote.md +2 -2
- package/docs/adr/0267-unanimity-and-the-revise-and-re-sit-loop.md +1 -1
- package/docs/adr/0268-the-constitution-comes-from-two-roots.md +3 -3
- package/docs/adr/0269-the-cli-session-store-is-host-keyed-at-a-fixed-anchor.md +1 -1
- package/docs/adr/0270-rank-floor-derives-without-a-prediction.md +2 -2
- package/docs/adr/0271-the-ideator-surface-is-two-halves.md +3 -3
- package/docs/adr/0272-a-craft-is-an-identity-not-a-toolchain.md +4 -4
- package/docs/adr/0273-hall-nav-can-gate-on-a-permission.md +1 -1
- package/docs/adr/0274-one-kernel-three-role-packs.md +1 -1
- package/docs/adr/0275-one-source-for-a-written-role-responsibility.md +1 -1
- package/docs/adr/0276-the-skill-listing-budget-cannot-hold-every-trigger.md +1 -1
- package/docs/adr/0277-a-box-is-in-use-only-while-a-human-is-attached.md +1 -1
- package/docs/adr/0278-a-gated-project-still-takes-applications.md +2 -2
- package/docs/adr/0279-an-upgrade-is-proven-by-the-served-version-not-the-health-check.md +1 -1
- package/docs/adr/0280-the-unattended-lane-may-drive-a-co-tenant-because-the-roster-is-the-decision.md +1 -1
- package/docs/adr/0281-an-instance-identity-is-its-own-unix-account-and-pg-role.md +2 -2
- package/docs/adr/README.md +294 -294
- package/docs/api/openapi.json +72 -5
- package/docs/api-reference.md +8 -2
- package/docs/architecture.md +22 -22
- package/docs/branding-contract.md +5 -5
- package/docs/canonical-permissions.md +22 -22
- package/docs/design/hall-direction-v2.md +3 -3
- package/docs/design/landing-page-direction-v2.md +1 -1
- package/docs/design/projects-hub-direction-v2.md +1 -1
- package/docs/file-map.md +3 -1
- package/docs/module-api-changelog.md +36 -1
- package/docs/modules-contract.md +25 -25
- package/docs/onboarding/browser-terminal-guide.md +1 -1
- package/docs/onboarding/diagrams/README.md +3 -3
- package/docs/onboarding/drachmae-and-karma.md +13 -13
- package/docs/onboarding/primer.md +7 -7
- package/docs/packs/artist.md +1 -1
- package/docs/packs/ideator.md +1 -1
- package/docs/project-context.template.md +3 -3
- package/docs/recipes/builder-box-lifecycle.md +5 -5
- package/docs/recipes/claude-design-loop.md +1 -1
- package/docs/recipes/core-release-pipeline.md +55 -14
- package/docs/recipes/figma-design-loop.md +1 -1
- package/docs/recipes/gds-db-backup.md +2 -2
- package/docs/recipes/instance-deploy.md +2 -2
- package/docs/recipes/instance-service-restart.md +3 -3
- package/docs/recipes/local-dev.md +2 -2
- package/docs/recipes/managed-settings-remote-control.md +3 -3
- package/docs/recipes/memory-backup.md +4 -4
- package/docs/recipes/memory-sync-conflicts.md +2 -2
- package/docs/recipes/multi-builder-merge.md +2 -2
- package/docs/recipes/ops-gotchas.md +4 -4
- package/docs/recipes/overnight-builder.md +1 -1
- package/docs/recipes/packaging-the-core.md +6 -6
- package/docs/recipes/private-npm-distribution.md +5 -5
- package/docs/recipes/search-index-ingestion.md +3 -3
- package/docs/recipes/self-host.md +5 -5
- package/docs/recipes/server-bring-up.md +1 -1
- package/docs/recipes/ship-and-regrade.md +2 -2
- package/docs/recipes/standalone-live-docs.md +1 -1
- package/docs/recipes/ui-look-before-you-ship.md +1 -1
- package/docs/recipes/upgrading-the-core.md +2 -2
- package/docs/recipes/work-on-a-task-from-your-dev-box.md +6 -6
- package/docs/research/cursor-competitive-analysis.md +3 -3
- package/docs/research/llm-model-agnostic-and-cheaper-grader.md +7 -7
- package/migrations/core_240_artist_gate_indexes.sql +48 -0
- package/migrations/core_240_goal_members_drop_legacy_role.sql +79 -0
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +4 -0
- package/modules/lifecycle/cascade.js +37 -9
- package/modules/lifecycle/db-claims.js +5 -2
- package/modules/lifecycle/db-goals.js +4 -3
- package/modules/lifecycle/db-overrides.js +117 -4
- package/modules/lifecycle/db-tasks.js +63 -0
- package/modules/lifecycle/migrations/lifecycle_001_goal_first_leads.sql +12 -4
- package/modules/lifecycle/module.json +2 -1
- package/modules/lifecycle/pg-constraint-fail.js +49 -0
- package/modules/lifecycle/routes/artist-gate.js +101 -0
- package/modules/lifecycle/routes/claims.js +13 -1
- package/modules/lifecycle/routes/lifecycle.js +6 -0
- package/modules/lifecycle/routes/task-write-routes.js +7 -0
- package/modules/lifecycle/routes/tasks.js +24 -0
- package/modules/lifecycle/task-classifier.js +10 -1
- package/modules/lifecycle/tests/cascade.mjs +43 -0
- package/modules/onboarding/approval-broadcast.js +27 -0
- package/modules/provisioning/provisioning.js +79 -3
- package/modules/provisioning/routes/provisioning.js +6 -1
- package/modules/provisioning/tests/provisioning.mjs +8 -8
- package/modules/security/secret-scrub.js +40 -4
- package/modules/status-ui/public/README.md +1 -1
- package/modules/ui-design/docs/design-contract.md +2 -2
- package/modules/ui-design/kit/README.md +1 -1
- package/modules/ui-design/kit/serve.js +1 -0
- package/modules/ui-design/skills/README.md +6 -6
- package/modules/ui-design/skills/brandkit/SKILL.md +1 -1
- package/modules/ui-design/skills/design-taste-frontend/SKILL.md +1 -1
- package/modules/ui-design/skills/design-taste-frontend-v1/SKILL.md +1 -1
- package/modules/ui-design/skills/gpt-taste/SKILL.md +1 -1
- package/modules/ui-design/skills/high-end-visual-design/SKILL.md +1 -1
- package/modules/ui-design/skills/image-to-code/SKILL.md +1 -1
- package/modules/ui-design/skills/imagegen-frontend-mobile/SKILL.md +1 -1
- package/modules/ui-design/skills/imagegen-frontend-web/SKILL.md +1 -1
- package/modules/ui-design/skills/impeccable/SKILL.md +1 -1
- package/modules/ui-design/skills/industrial-brutalist-ui/SKILL.md +1 -1
- package/modules/ui-design/skills/minimalist-ui/SKILL.md +1 -1
- package/modules/ui-design/skills/redesign-existing-projects/SKILL.md +1 -1
- package/modules/ui-design/skills/stitch-design-taste/SKILL.md +1 -1
- package/modules/ui-design/skills/style/SKILL.md +2 -2
- package/modules/ui-design/styles/README.md +3 -3
- package/modules/ui-design/styles/blueprint/DESIGN.md +1 -1
- package/modules/ui-design/styles/chrome-world/DESIGN.md +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/adopt-preflight.js +68 -2
- package/scripts/gds/audit-rank-roles.js +172 -0
- package/scripts/gds/build-cli-package.js +2 -0
- package/scripts/gds/claim.js +94 -9
- package/scripts/gds/claude-md-template.js +18 -0
- package/scripts/gds/device-flow-help.js +72 -0
- package/scripts/gds/fitness.js +8 -8
- package/scripts/gds/go-live.js +139 -5
- package/scripts/gds/init.js +64 -8
- package/scripts/gds/land-watch.js +13 -5
- package/scripts/gds/login.js +18 -0
- package/scripts/gds/mirror-redact.js +13 -2
- package/scripts/gds/package-core.js +11 -3
- package/scripts/gds/release.js +55 -0
- package/scripts/gds/setup.js +5 -39
- package/scripts/gds/ship-land.js +10 -2
- package/scripts/gds/ship-regen.js +41 -8
- package/scripts/gds/start.js +7 -4
- package/scripts/gds/worktree-claim-guard.js +27 -1
- package/scripts/public-mirror-export.js +17 -4
- package/src/bongos/api-errors.js +9 -0
- package/src/bongos/artist-gate.js +204 -0
- package/src/bongos/repo-info.js +37 -6
- package/src/branding.js +15 -0
- package/src/module-api.js +41 -1
- package/tests/adopt_preflight.mjs +72 -0
- package/tests/api_path_404.mjs +28 -0
- package/tests/artist_gate.mjs +234 -0
- package/tests/artist_gate_release.mjs +283 -0
- package/tests/artist_gate_route.mjs +174 -0
- package/tests/bongos_login.mjs +69 -2
- package/tests/box_scope_predicate.mjs +117 -0
- package/tests/claim_error_surface.mjs +163 -1
- package/tests/claude_materialize.mjs +9 -0
- package/tests/cli_exit_no_abort.mjs +256 -3
- package/tests/currency_label.mjs +11 -4
- package/tests/discord_approvals.mjs +45 -0
- package/tests/go_live.mjs +144 -0
- package/tests/init.mjs +52 -2
- package/tests/main_worktree_busy_reason.mjs +167 -0
- package/tests/membership_kind_lockstep.mjs +88 -0
- package/tests/mirror_redact.mjs +14 -0
- package/tests/module_api.mjs +7 -0
- package/tests/provision_settings_apply.mjs +13 -5
- package/tests/provisioning_settings.mjs +11 -7
- package/tests/provisioning_settings_apply.mjs +4 -4
- package/tests/provisioning_settings_env.mjs +59 -7
- package/tests/public_mirror_export.mjs +12 -0
- package/tests/rank_roles_audit.mjs +114 -0
- package/tests/repo_info_binding.mjs +82 -0
- package/tests/scrubber_corpus.mjs +70 -2
- package/tests/setup_device_flow_fallback.mjs +16 -0
- package/tests/start_rebase_warning.mjs +50 -0
- package/tests/task_field_bounds_match_db.mjs +140 -0
|
@@ -23,7 +23,7 @@ description: >-
|
|
|
23
23
|
|
|
24
24
|
## Rebuilt from
|
|
25
25
|
|
|
26
|
-
This skill is an **in-house rebuild**, not a vendored copy. Its documented functionality comes from `Leonxlnx/taste-skill` @ `<redacted>` (MIT; the `stitch-skill` entry and its `DESIGN.md`), which `/scan-before-install` reduced to `dangerous` at the default tier on 2026-08-28, so under [ADR 0198](../../../../docs/adr
|
|
26
|
+
This skill is an **in-house rebuild**, not a vendored copy. Its documented functionality comes from `Leonxlnx/taste-skill` @ `<redacted>` (MIT; the `stitch-skill` entry and its `DESIGN.md`), which `/scan-before-install` reduced to `dangerous` at the default tier on 2026-08-28, so under [ADR 0198](../../../../docs/adr/0198-third-party-skill-vendoring-policy.md) it could land only as a REBUILD-SPEC. The spec is the body of [task 1003325](https://cloudbongos.com/builders#/task/1003325) — the `[stitch-design-taste]` requirement group — and this file is its port under [task 1003327](https://cloudbongos.com/builders#/task/1003327); it implements those requirements from scratch, **no upstream bytes consulted or copied**. The landing shape is [ADR 0220](../../../../docs/adr/0220-an-in-house-rebuilt-skill-is-a-first-party-skill.md); what a *look* skill is allowed to be is [ADR 0230](../../../../docs/adr/0230-a-look-skill-is-a-composition-grammar-the-palette-is-the-pack.md).
|
|
27
27
|
|
|
28
28
|
What changed in translation, on purpose: the upstream **authored a palette** for the downstream tool — a descriptive name, a hex and a role per token, invented to taste. Here the colour contract is **transcribed, not invented**: it is the instance's thirteen with their real hex values and the roles the instance's `DESIGN.md` already gives them, so the external tool and the built surface cannot diverge. The document it writes uses the platform's own frontmatter shape — the one every look in `modules/ui-design/styles/` carries — rather than a shape of its own, so a document produced here can be read back as a style. Its universal bans (no pure black, no serif in a dashboard, the default UI sans banned) become **defaults the instance's `DESIGN.md` overrules**: Cloud Bongos's own world is a black void, and a document that told the tool otherwise would describe a different product. Its "signature move" of small contextual images set inline between headline words survives as a **hero object** under the owner's rule: a text-free cutout with its provenance sidecar, never a photograph of a screen. Its motion section stays what it always was, an intent brief for whoever writes the code afterwards, and every parameter in it is written to live inside the Kill Switch.
|
|
29
29
|
|
|
@@ -23,9 +23,9 @@ description: >-
|
|
|
23
23
|
|
|
24
24
|
## First party
|
|
25
25
|
|
|
26
|
-
This skill has **no upstream**. It was authored for the platform by [task 1003475](https://cloudbongos.com/builders#/task/1003475) from the owner's idea on the style-library sheet: the library ships looks an instance can adopt, and the next step is letting an owner *make* one with Claude beside them. It is not a rebuild, carries no vendored bytes and claims no origin; the two-origin rule for the module's skills is [ADR 0231](../../../../docs/adr
|
|
26
|
+
This skill has **no upstream**. It was authored for the platform by [task 1003475](https://cloudbongos.com/builders#/task/1003475) from the owner's idea on the style-library sheet: the library ships looks an instance can adopt, and the next step is letting an owner *make* one with Claude beside them. It is not a rebuild, carries no vendored bytes and claims no origin; the two-origin rule for the module's skills is [ADR 0231](../../../../docs/adr/0231-the-style-session-an-owner-authors-a-look-inside-the-contract.md).
|
|
27
27
|
|
|
28
|
-
Why it exists: a look in this library is a **branding pack** ([ADR 0219](../../../../docs/adr
|
|
28
|
+
Why it exists: a look in this library is a **branding pack** ([ADR 0219](../../../../docs/adr/0219-a-look-is-a-branding-pack-the-style-library.md)) — thirteen colours, two font stacks, a `DESIGN.md` of derived recipes and one specimen. That is a small enough object for an owner to have opinions about and a strict enough one that a wrong guess fails a measurement rather than shipping. What was missing was the loop between the two: the search that shows what already exists, the draft that stays inside the contract, the retune that is arithmetic rather than taste, and the one-line adoption at the end. This skill is that loop, bounded.
|
|
29
29
|
|
|
30
30
|
## What this session is, and is not
|
|
31
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `modules/ui-design/styles/` — the style library: looks as branding packs
|
|
2
2
|
|
|
3
|
-
A **look** is something a builder or an instance owner picks for a new surface or a whole instance. The library ships looks as **branding packs** ([task 1003323](https://cloudbongos.com/builders#/task/1003323), [ADR 0219](../../../docs/adr
|
|
3
|
+
A **look** is something a builder or an instance owner picks for a new surface or a whole instance. The library ships looks as **branding packs** ([task 1003323](https://cloudbongos.com/builders#/task/1003323), [ADR 0219](../../../docs/adr/0219-a-look-is-a-branding-pack-the-style-library.md)): the thirteen colours and the two font stacks of `theme.ui` (the fifteen host-overridable tokens, [ADR 0062 §3](../../../docs/adr/0062-medusa-instance-model-decoupling.md) / [ADR 0196](../../../docs/adr/0196-chrome-world-token-contract-and-the-landing-sheets.md)), a `DESIGN.md` of the look's derived recipes in the frontmatter shape the chrome world uses, and one specimen mock. **Never a fork of a sheet.** The drift tests already prove every served sheet reads only the contract, so a look that needs a sixteenth token is a contract change and an ADR, not a style.
|
|
4
4
|
|
|
5
5
|
## The catalogue
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ A **look** is something a builder or an instance owner picks for a new surface o
|
|
|
8
8
|
|---|---|---|---|
|
|
9
9
|
| `chrome-world` | the neutral pack, byte for byte | The canonical entry: one iridescent chrome sculpture in a black void, pale grey paper in light, one warm salmon that lights only the pressable and the live. Its recipes are the repo-root [`DESIGN.md`](../../../DESIGN.md); [`chrome-world/DESIGN.md`](chrome-world/DESIGN.md) points there. | the world round's pick (task 1003296 → 1003298) |
|
|
10
10
|
| `expedition` | warm paper, lamp yellow, Archivo | A printed field journal: a halftone screen over the paper, hairline frames instead of a grid, big heavy uppercase headlines, the yellow as a fill only. [`expedition/DESIGN.md`](expedition/DESIGN.md) | `docs/design/mocks/world/natgeo-editorial` (kept in round 1) |
|
|
11
|
-
| `blueprint` | cool grey-blue paper, cyanotype blue, slate green, IBM Plex Sans | A drafting table under north light: a faint graph lattice on the ground, compartments registered to the board with a crosshair tick at a 2px cut edge, the display voice in sentence case, every figure mono and tabular, one cyanotype blue on what is pressable, a slate green for what was measured and a rust pencil for what went wrong. The library's first cool look. [`blueprint/DESIGN.md`](blueprint/DESIGN.md) | authored through the `/style` session ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../docs/adr
|
|
11
|
+
| `blueprint` | cool grey-blue paper, cyanotype blue, slate green, IBM Plex Sans | A drafting table under north light: a faint graph lattice on the ground, compartments registered to the board with a crosshair tick at a 2px cut edge, the display voice in sentence case, every figure mono and tabular, one cyanotype blue on what is pressable, a slate green for what was measured and a rust pencil for what went wrong. The library's first cool look. [`blueprint/DESIGN.md`](blueprint/DESIGN.md) | authored through the `/style` session ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../docs/adr/0231-the-style-session-an-owner-authors-a-look-inside-the-contract.md)) |
|
|
12
12
|
| `grove` | pale sage, tan, sea green, Nunito | A sculpted paper garden: soft corners on everything that holds content, tinted shadows, the sea as a slab a whole band sits on, the tan as the one lit thing. [`grove/DESIGN.md`](grove/DESIGN.md) | `docs/design/mocks/world/organic-cards` (kept in round 1) |
|
|
13
13
|
|
|
14
14
|
The owner looked at both alternates on the sheet on 2026-09-01 and kept them ("styles look good for a start"). Both alternates were **retuned against the contract**, which is a measurement and not a taste: a pack's thirteen are laid through three sheets that already exist (the landing's `world.css`, the hub's `cosmos.css`, the hall's `style.css`) and every pair those sheets paint must clear AA under it. The grove's sage ground lifted and its inks deepened until the hub's fixed status vocabulary and the hall's chips cleared; the expedition's `ink-faint` deepened one step. What a pack cannot carry is **dark**: the contract is light values only, and every sheet's dark tier is its own black, which a look reaches through its accent and its faces. So the grove's green dark ground stays in the world round's mock and does not travel.
|
|
@@ -51,7 +51,7 @@ SURFACE=modules/ui-design/styles/expedition STYLE=expedition node modules/ui-des
|
|
|
51
51
|
|
|
52
52
|
## Adding a look
|
|
53
53
|
|
|
54
|
-
The steps below are the manual path. The **`/style` session** ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../docs/adr
|
|
54
|
+
The steps below are the manual path. The **`/style` session** ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../docs/adr/0231-the-style-session-an-owner-authors-a-look-inside-the-contract.md)) walks them with an owner instead: it renders the nearest entries before it asks anything, drafts inside the contract, retunes against the same measurements below with a failure-to-fix table, and hands over the one-step adoption without taking it. `blueprint` was authored that way.
|
|
55
55
|
|
|
56
56
|
1. Make the dir with the three files; start from the alternate nearest to it.
|
|
57
57
|
2. `node modules/ui-design/kit/contrast.js --pack <name>` until the floor is clean; then `node --test tests/ui_design_styles.mjs`, which runs the world / cosmos / hall suites under the pack and tells you the exact pair that fails. Tune the thirteen, never the sheets.
|
|
@@ -75,7 +75,7 @@ components:
|
|
|
75
75
|
|
|
76
76
|
# Style: The Blueprint
|
|
77
77
|
|
|
78
|
-
**Origin.** Authored through the `/style` session ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../../docs/adr
|
|
78
|
+
**Origin.** Authored through the `/style` session ([task 1003475](https://cloudbongos.com/builders#/task/1003475), [ADR 0231](../../../../docs/adr/0231-the-style-session-an-owner-authors-a-look-inside-the-contract.md)) from a two-line brief: *"a drafting table under north light, cool paper and graphite; one cyanotype blue on what is pressable, a rust pencil for what went wrong."* The library's three existing looks are all warm and all carry a warm accent (salmon, lamp yellow, tan), so the search step found no near neighbour and the session drafted rather than adapted. The retune against the contract took one pass: the pack floor and all three token suites cleared on the first measurement, which is what a cool ground and a deep graphite ink buy you. The candidate's own dark ground does not travel, as with every look: a pack carries light values only.
|
|
79
79
|
|
|
80
80
|
## Overview
|
|
81
81
|
|
|
@@ -30,7 +30,7 @@ rounded:
|
|
|
30
30
|
|
|
31
31
|
# Style: The Chrome World (the canonical look)
|
|
32
32
|
|
|
33
|
-
This is the look Cloud Bongos itself runs on and the **first entry** of the style library ([task 1003323](https://cloudbongos.com/builders#/task/1003323)). It is the canonical one in a precise sense: its `pack.json` is byte-for-byte the `theme.ui` block of [`config/branding.neutral.json`](../../../../config/branding.neutral.json), the neutral pack every instance resolves over, and its recipes are **not restated here**. The world's derived tiers, faces, materials, motion grammar, components, Do's and Don'ts and accessibility floors are the repo-root [`DESIGN.md`](../../../../DESIGN.md), recorded from the built landing ([ADR 0196](../../../../docs/adr
|
|
33
|
+
This is the look Cloud Bongos itself runs on and the **first entry** of the style library ([task 1003323](https://cloudbongos.com/builders#/task/1003323)). It is the canonical one in a precise sense: its `pack.json` is byte-for-byte the `theme.ui` block of [`config/branding.neutral.json`](../../../../config/branding.neutral.json), the neutral pack every instance resolves over, and its recipes are **not restated here**. The world's derived tiers, faces, materials, motion grammar, components, Do's and Don'ts and accessibility floors are the repo-root [`DESIGN.md`](../../../../DESIGN.md), recorded from the built landing ([ADR 0196](../../../../docs/adr/0196-chrome-world-token-contract-and-the-landing-sheets.md)). Read that file; this one only holds the thirteen so the catalogue's lockstep test has something to hold.
|
|
34
34
|
|
|
35
35
|
## What this entry is for
|
|
36
36
|
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.725",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.725",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.725",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
|
@@ -11,11 +11,20 @@
|
|
|
11
11
|
// floor (ADR 0043, via gate-review.js's canonical matchesHardFloor).
|
|
12
12
|
// • CI collisions — the repo's workflows vs core's expected unit/secret-scan/
|
|
13
13
|
// gate-review checks.
|
|
14
|
+
// • IGNORED incoming files — a pre-existing .gitignore rule that would swallow what
|
|
15
|
+
// adopt is about to commit (task 1003400). This is the check that was missing when
|
|
16
|
+
// Cloud Bongos was adopted onto a repo whose .gitignore already carried `.claude/`:
|
|
17
|
+
// the skills, hooks and settings.json were materialized onto disk and then dropped
|
|
18
|
+
// by `git add`, so the adopt commit landed 8 files with no methodology surface at
|
|
19
|
+
// all. Nothing failed, nothing was logged, and every clone of that repo has been
|
|
20
|
+
// missing its /builder-* commands since. BLOCKING, because the result is a
|
|
21
|
+
// non-functional instance that looks fine.
|
|
14
22
|
// READ-ONLY: it computes findings; the accept-gate that decides whether to proceed
|
|
15
23
|
// lives in init.js runAdopt. Pure check functions + a thin fs-reading orchestrator.
|
|
16
24
|
|
|
17
25
|
const nodeFs = require('node:fs');
|
|
18
26
|
const nodePath = require('node:path');
|
|
27
|
+
const { execFileSync: nodeExecFileSync } = require('node:child_process');
|
|
19
28
|
const { filenameViolation, INSTANCE_NS } = require('./migration-namespace');
|
|
20
29
|
const { matchesHardFloor } = require('./gate-review');
|
|
21
30
|
|
|
@@ -79,10 +88,66 @@ function checkCiCollisions(workflows = []) {
|
|
|
79
88
|
return [{ category: 'ci', severity: SEV.INFO, message: `${workflows.length} existing CI workflow(s); core will ADD its own unit/secret-scan/gate-review checks alongside them — confirm no required-check conflict.` }];
|
|
80
89
|
}
|
|
81
90
|
|
|
91
|
+
// PURE — [{ path, rule }] of incoming files a .gitignore rule would swallow → findings.
|
|
92
|
+
// BLOCKING: an ignored incoming file is not a style problem, it is silent data loss at
|
|
93
|
+
// `git add` time, and the instance that results is broken in a way nothing reports.
|
|
94
|
+
function checkIgnoredIncoming(ignored = [], { checked = true } = {}) {
|
|
95
|
+
if (!checked) {
|
|
96
|
+
return [{ category: 'ignored-incoming', severity: SEV.INFO, message: 'could not run `git check-ignore` here (no git, or not a repo yet) — cannot confirm the incoming files are committable. Re-check after `git init` if adopt lands nothing under .claude/.' }];
|
|
97
|
+
}
|
|
98
|
+
if (!ignored.length) {
|
|
99
|
+
return [{ category: 'ignored-incoming', severity: SEV.INFO, message: 'no existing ignore rule swallows the files adopt writes — they will all reach the commit.' }];
|
|
100
|
+
}
|
|
101
|
+
const lines = ignored.map((i) => (i.rule ? `${i.path} (ignored by ${i.rule})` : i.path));
|
|
102
|
+
return [{
|
|
103
|
+
category: 'ignored-incoming',
|
|
104
|
+
severity: SEV.BLOCK,
|
|
105
|
+
message: `${ignored.length} file(s) adopt writes are IGNORED by this repo and would be silently dropped from the commit: ${lines.join('; ')}. `
|
|
106
|
+
+ 'Adopt would appear to succeed and produce an instance missing that surface — a repo ignoring `.claude/` gets no /builder-* commands on any clone. '
|
|
107
|
+
+ 'Fix the rule (delete it, or add a negation such as `!.claude/` after it), then re-run.',
|
|
108
|
+
}];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Which of `incoming` does this repo's ignore rules match? Uses `git check-ignore -v`,
|
|
112
|
+
// which reports the SOURCE RULE for each match, so the finding can name the exact line
|
|
113
|
+
// the owner has to change rather than leaving them to hunt for it.
|
|
114
|
+
//
|
|
115
|
+
// Returns { ignored:[{path, rule}], checked:boolean }. `checked:false` means the probe
|
|
116
|
+
// could not run at all (no git, not a repo) — deliberately distinct from "nothing is
|
|
117
|
+
// ignored", because the two warrant different advice. execFileSync is injectable for
|
|
118
|
+
// tests; git exits 1 when nothing matches, which is a normal answer and not an error.
|
|
119
|
+
function probeIgnoredIncoming({ dir, incoming = INCOMING_PATHS, execFileSync = nodeExecFileSync } = {}) {
|
|
120
|
+
// Trailing slashes are ours (they mark dirs in the list); git wants plain pathnames.
|
|
121
|
+
const paths = incoming.map((p) => String(p).replace(/\/+$/, ''));
|
|
122
|
+
let out = '';
|
|
123
|
+
try {
|
|
124
|
+
out = execFileSync('git', ['check-ignore', '-v', '--stdin'], {
|
|
125
|
+
cwd: dir, input: paths.join('\n'), encoding: 'utf8', timeout: 5000,
|
|
126
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
127
|
+
}) || '';
|
|
128
|
+
} catch (err) {
|
|
129
|
+
// Exit 1 = "no path is ignored" (a real answer, stdout empty). Anything else means
|
|
130
|
+
// the probe itself could not run.
|
|
131
|
+
if (err && err.status === 1) return { ignored: [], checked: true };
|
|
132
|
+
return { ignored: [], checked: false };
|
|
133
|
+
}
|
|
134
|
+
const ignored = [];
|
|
135
|
+
for (const line of out.split('\n')) {
|
|
136
|
+
if (!line.trim()) continue;
|
|
137
|
+
// `<source>:<line>:<pattern>\t<pathname>`
|
|
138
|
+
const tab = line.lastIndexOf('\t');
|
|
139
|
+
if (tab === -1) continue;
|
|
140
|
+
const rule = line.slice(0, tab).trim();
|
|
141
|
+
const pathname = line.slice(tab + 1).trim();
|
|
142
|
+
ignored.push({ path: pathname, rule });
|
|
143
|
+
}
|
|
144
|
+
return { ignored, checked: true };
|
|
145
|
+
}
|
|
146
|
+
|
|
82
147
|
// Read the repo (migrations, src/bongos, workflows) and run every check. `stack` is the
|
|
83
148
|
// adopt-detect summary (task 2043); we re-read only what the checks need. Returns
|
|
84
149
|
// { findings, counts:{blocking,warning,info}, hasBlocking }.
|
|
85
|
-
function preflightAdopt({ dir, stack = {}, fs = nodeFs, path = nodePath } = {}) {
|
|
150
|
+
function preflightAdopt({ dir, stack = {}, fs = nodeFs, path = nodePath, execFileSync = nodeExecFileSync } = {}) {
|
|
86
151
|
const listFiles = (rel) => { try { return fs.readdirSync(path.join(dir, rel)).filter((f) => { try { return fs.statSync(path.join(dir, rel, f)).isFile(); } catch { return false; } }); } catch { return []; } };
|
|
87
152
|
const exists = (rel) => { try { return fs.existsSync(path.join(dir, rel)); } catch { return false; } };
|
|
88
153
|
|
|
@@ -105,6 +170,7 @@ function preflightAdopt({ dir, stack = {}, fs = nodeFs, path = nodePath } = {})
|
|
|
105
170
|
...checkFitnessBoundary({ topLevelDirs: stack.topLevelDirs || [], hasSrcBongos: exists('src/bongos') }),
|
|
106
171
|
...checkProtectedPaths(INCOMING_PATHS),
|
|
107
172
|
...checkCiCollisions(workflows),
|
|
173
|
+
...(() => { const { ignored, checked } = probeIgnoredIncoming({ dir, execFileSync }); return checkIgnoredIncoming(ignored, { checked }); })(),
|
|
108
174
|
];
|
|
109
175
|
const counts = { blocking: 0, warning: 0, info: 0 };
|
|
110
176
|
for (const f of findings) counts[f.severity === SEV.BLOCK ? 'blocking' : f.severity === SEV.WARN ? 'warning' : 'info']++;
|
|
@@ -118,4 +184,4 @@ function formatPreflight(report) {
|
|
|
118
184
|
return report.findings.map((f) => ` ${mark[f.severity] || '·'} [${f.category}] ${f.message}`);
|
|
119
185
|
}
|
|
120
186
|
|
|
121
|
-
module.exports = { preflightAdopt, formatPreflight, checkMigrationNamespace, checkFitnessBoundary, checkProtectedPaths, checkCiCollisions, INCOMING_PATHS, CORE_EXPECTED_CHECKS, SEV };
|
|
187
|
+
module.exports = { preflightAdopt, formatPreflight, checkMigrationNamespace, checkFitnessBoundary, checkProtectedPaths, checkCiCollisions, checkIgnoredIncoming, probeIgnoredIncoming, INCOMING_PATHS, CORE_EXPECTED_CHECKS, SEV };
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// scripts/gds/audit-rank-roles.js — does the live builder roster hold ONLY the
|
|
3
|
+
// four live ranks? (task 1002873)
|
|
4
|
+
//
|
|
5
|
+
// WHY. `migrations/023`'s CHECK on `builders.rank` still admits twelve legacy
|
|
6
|
+
// values beyond the four live ranks. `governance_002_seed_and_backfill.sql`
|
|
7
|
+
// backfills roles with an INNER JOIN from `builders.rank` to the four seeded
|
|
8
|
+
// `governance_roles`, so a builder sitting on a legacy rank gets NO role row and
|
|
9
|
+
// resolves to ZERO permissions: admitted by threshold under `requireRank`, locked
|
|
10
|
+
// out of everything under the resolver. They are not told why, and nothing about
|
|
11
|
+
// their account looks wrong.
|
|
12
|
+
//
|
|
13
|
+
// That divergence is deliberate — ADR 0151 chose fail-closed, and
|
|
14
|
+
// `tests/governance_parity.mjs` asserts it is strictly a tightening. What was
|
|
15
|
+
// missing is the VERIFICATION. governance_002's comment says "none exist today —
|
|
16
|
+
// verified", a point-in-time manual check that nothing re-runs; the parity test
|
|
17
|
+
// is DB-free by necessity (the unit gate has no Postgres) and says so in the
|
|
18
|
+
// repo; and R114's live proof ran on a scratch DB holding only the four seeded
|
|
19
|
+
// rank-roles, so the production roster was never queried.
|
|
20
|
+
//
|
|
21
|
+
// THIS IS THE RE-RUNNABLE HALF, and it is deliberately NOT fatal at boot. Idea
|
|
22
|
+
// 1000622 records that trap: an assertion that throws on startup turns a data
|
|
23
|
+
// problem on one instance into an outage. This is a standalone read-only script
|
|
24
|
+
// for a nightly/deploy-time caller — it exits 1 so a caller can act, and nothing
|
|
25
|
+
// in the server's boot path requires it.
|
|
26
|
+
//
|
|
27
|
+
// It reports rather than repairs, and that is a decision, not an omission:
|
|
28
|
+
// rewriting somebody's rank is an authority change, and it belongs to an operator
|
|
29
|
+
// who can see who the account is — not to a sweep.
|
|
30
|
+
//
|
|
31
|
+
// node scripts/gds/audit-rank-roles.js [--json] [--file-idea]
|
|
32
|
+
//
|
|
33
|
+
// Exit codes:
|
|
34
|
+
// 0 every builder holds a live rank
|
|
35
|
+
// 1 at least one builder holds a rank the governance backfill cannot match
|
|
36
|
+
// 2 could not read the roster (no session / network / route absent)
|
|
37
|
+
//
|
|
38
|
+
// `--file-idea` is what makes this a SURFACE rather than another thing nobody
|
|
39
|
+
// runs — the same shape diagram-drift/check.js uses, spawning capture.js so idea
|
|
40
|
+
// filing has one implementation. Without it a nightly deterministic run that exits
|
|
41
|
+
// 1 reports into a log nobody reads, which is the exact criticism this task makes
|
|
42
|
+
// of the status quo.
|
|
43
|
+
|
|
44
|
+
const path = require('node:path');
|
|
45
|
+
const { spawnSync } = require('node:child_process');
|
|
46
|
+
const fs = require('node:fs');
|
|
47
|
+
const os = require('node:os');
|
|
48
|
+
const { cliClient, requireSession, cliExit } = require('./cli-lib');
|
|
49
|
+
const { LIVE_RANK_LADDER } = require('../../src/bongos/db-kernel.js');
|
|
50
|
+
|
|
51
|
+
// findRanksWithoutRoles — the PURE half. Given roster rows and the live ladder,
|
|
52
|
+
// which builders hold a rank that `governance_002`'s INNER JOIN cannot match?
|
|
53
|
+
//
|
|
54
|
+
// Pure + exported because this is the only altitude the repo can test: the unit
|
|
55
|
+
// gate has no Postgres, which is exactly why the gap this script closes went
|
|
56
|
+
// unverified for so long. A DB-free test of the decision is not a consolation
|
|
57
|
+
// prize here — it is the thing that can actually run in CI.
|
|
58
|
+
//
|
|
59
|
+
// A row with NO rank at all counts: NULL fails the INNER JOIN the same way a
|
|
60
|
+
// legacy value does, and reads as "fine" in every UI that renders a blank.
|
|
61
|
+
function findRanksWithoutRoles(rows, liveRanks = LIVE_RANK_LADDER) {
|
|
62
|
+
const live = new Set(liveRanks);
|
|
63
|
+
return (Array.isArray(rows) ? rows : [])
|
|
64
|
+
.filter((b) => b && !live.has(b.rank))
|
|
65
|
+
.map((b) => ({
|
|
66
|
+
id: b.id != null ? String(b.id) : null,
|
|
67
|
+
// The login is what an operator needs to act; it is already visible to any
|
|
68
|
+
// caller authorised to read the roster, so this adds no exposure.
|
|
69
|
+
github_login: b.github_login || null,
|
|
70
|
+
rank: b.rank === undefined ? null : b.rank,
|
|
71
|
+
status: b.status || null,
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// summarize — the rank histogram, so a CLEAN run still says what it looked at.
|
|
76
|
+
// A green check that prints nothing is indistinguishable from one that read
|
|
77
|
+
// nothing, which is the failure mode this whole task is about.
|
|
78
|
+
function summarize(rows) {
|
|
79
|
+
const counts = new Map();
|
|
80
|
+
for (const b of Array.isArray(rows) ? rows : []) {
|
|
81
|
+
const key = b && b.rank ? b.rank : '(none)';
|
|
82
|
+
counts.set(key, (counts.get(key) || 0) + 1);
|
|
83
|
+
}
|
|
84
|
+
return [...counts.entries()].sort((a, b) => b[1] - a[1]);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Spawn capture.js rather than POSTing here, so idea filing keeps one
|
|
88
|
+
// implementation (the diagram-drift/check.js precedent). Best-effort: a failure to
|
|
89
|
+
// file must not turn a successful audit into a crash — the exit code and stdout
|
|
90
|
+
// still carry the finding.
|
|
91
|
+
function fileIdea(offenders) {
|
|
92
|
+
const body = [
|
|
93
|
+
`${offenders.length} builder(s) hold a rank with no matching governance_roles row.`,
|
|
94
|
+
'',
|
|
95
|
+
'They resolve to ZERO permissions — admitted by rank threshold under requireRank,',
|
|
96
|
+
'refused by the permission resolver, and given no reason (ADR 0151 fail-closed).',
|
|
97
|
+
'',
|
|
98
|
+
...offenders.map((o) => `- builder ${o.id}${o.github_login ? ` (${o.github_login})` : ''} rank=${o.rank === null ? '(none)' : o.rank} status=${o.status || '?'}`),
|
|
99
|
+
'',
|
|
100
|
+
'Fix: move each to a live rank through the normal rank-change path, which rotates',
|
|
101
|
+
'the governance role in the same transaction. Not auto-repaired: changing a rank is',
|
|
102
|
+
'an authority decision, and a sweep is the wrong actor for it.',
|
|
103
|
+
'',
|
|
104
|
+
'Filed by scripts/gds/audit-rank-roles.js (task 1002873).',
|
|
105
|
+
].join('\n');
|
|
106
|
+
const tmp = path.join(os.tmpdir(), `rank-roles-audit-${process.pid}.md`);
|
|
107
|
+
try {
|
|
108
|
+
fs.writeFileSync(tmp, body, 'utf8');
|
|
109
|
+
const r = spawnSync(
|
|
110
|
+
process.execPath,
|
|
111
|
+
[path.join(__dirname, 'capture.js'),
|
|
112
|
+
`[rank-roles] ${offenders.length} builder(s) on a rank with no governance role`,
|
|
113
|
+
'--kind', 'bug', '--body-file', tmp],
|
|
114
|
+
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], timeout: 60_000 }
|
|
115
|
+
);
|
|
116
|
+
if (r.status !== 0) console.error('audit-rank-roles: capture.js failed to file the idea — the exit code above still carries the finding.');
|
|
117
|
+
} catch (e) {
|
|
118
|
+
console.error(`audit-rank-roles: could not file the idea (${(e && e.message) || e}) — the exit code above still carries the finding.`);
|
|
119
|
+
} finally {
|
|
120
|
+
try { fs.rmSync(tmp, { force: true }); } catch (_) { /* best-effort */ }
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function main() {
|
|
125
|
+
const json = process.argv.includes('--json');
|
|
126
|
+
await requireSession();
|
|
127
|
+
const api = await cliClient();
|
|
128
|
+
const r = await api.request('GET', '/builders/roster');
|
|
129
|
+
if (!r.ok) {
|
|
130
|
+
console.error(`audit-rank-roles: could not read the roster (HTTP ${r.status}).`);
|
|
131
|
+
console.error(' Needs a session with builder.roster.read. Nothing was checked — do NOT read this as a pass.');
|
|
132
|
+
return cliExit(2);
|
|
133
|
+
}
|
|
134
|
+
// The roster query has no WHERE on `builders`, so this covers every row,
|
|
135
|
+
// INACTIVE ONES INCLUDED. That matters: a deactivated builder on a legacy rank
|
|
136
|
+
// is exactly the row a future CHECK-narrowing migration would fail to apply over.
|
|
137
|
+
const rows = (r.data && (r.data.builders || r.data.roster || r.data)) || [];
|
|
138
|
+
const offenders = findRanksWithoutRoles(rows);
|
|
139
|
+
const histogram = summarize(rows);
|
|
140
|
+
|
|
141
|
+
if (json) {
|
|
142
|
+
console.log(JSON.stringify({ checked: rows.length, live_ranks: LIVE_RANK_LADDER, histogram, offenders }, null, 2));
|
|
143
|
+
return cliExit(offenders.length ? 1 : 0);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log(`audit-rank-roles: ${rows.length} builder row(s) checked against the live ladder [${LIVE_RANK_LADDER.join(', ')}]`);
|
|
147
|
+
for (const [rank, n] of histogram) console.log(` ${String(rank).padEnd(12)} ${n}`);
|
|
148
|
+
if (!offenders.length) {
|
|
149
|
+
console.log('\n✓ every builder holds a live rank — the governance backfill can match all of them.');
|
|
150
|
+
return cliExit(0);
|
|
151
|
+
}
|
|
152
|
+
console.log(`\n✗ ${offenders.length} builder(s) hold a rank with no matching governance role.`);
|
|
153
|
+
console.log(' They resolve to ZERO permissions: admitted by rank threshold, refused by the resolver,');
|
|
154
|
+
console.log(' and nothing tells them why (ADR 0151 fail-closed).');
|
|
155
|
+
for (const o of offenders) {
|
|
156
|
+
console.log(` - builder ${o.id}${o.github_login ? ` (${o.github_login})` : ''} rank=${o.rank === null ? '(none)' : o.rank} status=${o.status || '?'}`);
|
|
157
|
+
}
|
|
158
|
+
console.log('\n This is a BUILDER NEED, not an outage: move each to a live rank with the normal');
|
|
159
|
+
console.log(' rank-change path so the governance role rotates in the same transaction.');
|
|
160
|
+
console.log(' Deliberately not repaired here — changing a rank is an authority decision.');
|
|
161
|
+
if (process.argv.includes('--file-idea')) fileIdea(offenders);
|
|
162
|
+
return cliExit(1);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (require.main === module) {
|
|
166
|
+
main().catch((err) => {
|
|
167
|
+
console.error('audit-rank-roles:', (err && err.message) || err);
|
|
168
|
+
cliExit(2);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
module.exports = { findRanksWithoutRoles, summarize };
|
|
@@ -51,6 +51,7 @@ const FILES = [
|
|
|
51
51
|
'scripts/gds/login.js',
|
|
52
52
|
'scripts/gds/reauth.js',
|
|
53
53
|
'scripts/gds/setup.js',
|
|
54
|
+
'scripts/gds/device-flow-help.js', // shared leaf: login.js + setup.js both require it (task 1003881)
|
|
54
55
|
'scripts/gds/onboarding-config.js', // lazy dep of setup.js
|
|
55
56
|
'scripts/gds/install-git-hooks.js', // lazy dep of setup.js
|
|
56
57
|
'scripts/gds/preflight.js',
|
|
@@ -64,6 +65,7 @@ const FILES = [
|
|
|
64
65
|
'scripts/gds/recall.js',
|
|
65
66
|
'scripts/gds/cost.js',
|
|
66
67
|
'scripts/gds/release.js',
|
|
68
|
+
'scripts/gds/worktree-claim-guard.js', // release.js warns through it; pure, zero requires
|
|
67
69
|
|
|
68
70
|
// Get onto a real environment without installing one: the cloud dev box.
|
|
69
71
|
'scripts/gds/shell.js',
|
package/scripts/gds/claim.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
const { execSync } = require('node:child_process');
|
|
11
11
|
const fs = require('node:fs');
|
|
12
12
|
const path = require('node:path');
|
|
13
|
-
const { cliClient, requireSession, fmtTouches, printOnboardingNudge, rewardPolicy, costPlusOnlyNote, detectWorktreeName } = require('./cli-lib');
|
|
13
|
+
const { cliClient, requireSession, fmtTouches, printOnboardingNudge, rewardPolicy, costPlusOnlyNote, detectWorktreeName, cliExit } = require('./cli-lib');
|
|
14
14
|
const { nextNumbers, padAdr, padMig } = require('./next-number');
|
|
15
15
|
const { CORE_NS } = require('./migration-namespace');
|
|
16
16
|
const { contextPack, formatContextPack, resolveWorktreeRoot } = require('./context-pack');
|
|
@@ -147,10 +147,44 @@ function enforceWorktreeClaim(taskId, { allowMainCheckout }) {
|
|
|
147
147
|
allowMainCheckout,
|
|
148
148
|
taskId,
|
|
149
149
|
});
|
|
150
|
-
if (d.verdict === 'allow') return;
|
|
150
|
+
if (d.verdict === 'allow') return tree;
|
|
151
151
|
for (const line of d.lines) console.error(line);
|
|
152
152
|
if (d.verdict === 'refuse') process.exit(2);
|
|
153
153
|
console.error('');
|
|
154
|
+
return tree;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// task 1002592 — a failed worktree DETECTION reaches the builder disguised as a
|
|
158
|
+
// claim CONFLICT, and that disguise is the whole of the original bug report.
|
|
159
|
+
// When detectWorktreeName() yields nothing the claim goes up with
|
|
160
|
+
// worktree_name: null; the server's one-active-claim guard keys on the WORKING
|
|
161
|
+
// TREE, so an unnamed claim falls back to the per-session compare and a
|
|
162
|
+
// genuinely-parallel worktree is refused as a duplicate. The builder then hunts
|
|
163
|
+
// for a claim conflict that does not exist.
|
|
164
|
+
//
|
|
165
|
+
// Only speak when null is WRONG. In the main checkout null is the documented
|
|
166
|
+
// correct answer and the refusal is genuine, so a note there would send the next
|
|
167
|
+
// reader down precisely the wrong path — that distinction is the fix, not a
|
|
168
|
+
// detail of it.
|
|
169
|
+
function worktreeDetectionNote(ctx, taskId) {
|
|
170
|
+
// The caller must have actually PROBED the tree. Without that this cannot tell
|
|
171
|
+
// "detection failed" from "nobody looked", and guessing would hang a worktree
|
|
172
|
+
// warning on every refusal rendered by a caller that never had tree info —
|
|
173
|
+
// including every pre-existing one. Absence of knowledge is not evidence.
|
|
174
|
+
if (!ctx || !('worktree' in ctx)) return [];
|
|
175
|
+
const { worktree, isMainCheckout } = ctx;
|
|
176
|
+
if (worktree) return []; // named fine — the refusal is genuine
|
|
177
|
+
if (isMainCheckout === true) return []; // null is correct here
|
|
178
|
+
const why = isMainCheckout === false
|
|
179
|
+
? 'this IS a linked worktree, so a name was expected'
|
|
180
|
+
: 'this tree is not recognisable as the main checkout either';
|
|
181
|
+
return [
|
|
182
|
+
` ⚠ This session could not name its worktree — auto-detect returned nothing, and ${why}.`,
|
|
183
|
+
' An unnamed claim is compared per-SESSION instead of per-worktree, so a real parallel',
|
|
184
|
+
' worktree is refused as a duplicate. That is very likely what you are looking at, and',
|
|
185
|
+
' it is a path-detection problem, not a claim conflict. Name it explicitly to rule it out:',
|
|
186
|
+
` node scripts/gds/claim.js ${taskId} --worktree <name>`,
|
|
187
|
+
];
|
|
154
188
|
}
|
|
155
189
|
|
|
156
190
|
function captureHeadSha() {
|
|
@@ -247,7 +281,25 @@ function claimErrorInfo(r) {
|
|
|
247
281
|
// string), so every branch below silently missed and the refusal printed as
|
|
248
282
|
// `[object Object]`. Pure (no console / no process.exit) + exported so it can be
|
|
249
283
|
// unit-tested against the real envelope shapes. Returns { lines, exit }.
|
|
250
|
-
|
|
284
|
+
//
|
|
285
|
+
// task 1002592: server-supplied prose (a task title, a flag reason, a hint) is
|
|
286
|
+
// echoed to the operator's terminal by the branches below. It is our own API, so
|
|
287
|
+
// this is hygiene rather than a live threat — but an unbounded string can carry
|
|
288
|
+
// control characters that repaint a terminal, and a runaway one can bury the
|
|
289
|
+
// guidance it was meant to add. Clip to one line, strip C0/C1 controls, cap length.
|
|
290
|
+
const MAX_LISTED_TASKS = 20;
|
|
291
|
+
function clip(s, max = 160) {
|
|
292
|
+
if (s == null) return '';
|
|
293
|
+
// eslint-disable-next-line no-control-regex
|
|
294
|
+
const flat = String(s).replace(/[--]+/g, ' ').trim();
|
|
295
|
+
return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// task 1002592: `ctx` carries what the CALLER knows about the tree
|
|
299
|
+
// ({ worktree, isMainCheckout }) so the session-claim branch can tell a real
|
|
300
|
+
// conflict apart from a failed worktree detection. Optional and defaulted — the
|
|
301
|
+
// function stays pure and every existing caller/test keeps working.
|
|
302
|
+
function formatClaimFailure(r, taskId, ctx) {
|
|
251
303
|
const lines = [];
|
|
252
304
|
const { code, message, d } = claimErrorInfo(r);
|
|
253
305
|
|
|
@@ -271,6 +323,7 @@ function formatClaimFailure(r, taskId) {
|
|
|
271
323
|
? `Run /builder-ship ${n} (or /builder-release ${n}) first, or open a fresh worktree/session for this task.`
|
|
272
324
|
: 'Ship or release the in-flight claim, or start a fresh worktree/session.')}`);
|
|
273
325
|
lines.push(' One claim per session keeps each ship isolated (task 1642). To work tasks in PARALLEL, open a separate worktree/session per task — each holds its own single claim — or use the hall work board’s multi-select bulk-claim.');
|
|
326
|
+
lines.push(...worktreeDetectionNote(ctx, taskId));
|
|
274
327
|
return { lines, exit: 1 };
|
|
275
328
|
}
|
|
276
329
|
if (code === 'newcomer_must_ship_first') {
|
|
@@ -294,6 +347,26 @@ function formatClaimFailure(r, taskId) {
|
|
|
294
347
|
lines.push(` ${d.what_to_do || `Run /builder-ship ${n || '<task>'} (or /builder-release ${n || '<task>'}) first, claim from a separate worktree, or claim with {"bind_session":false} (an unbound claim always coexists).`}`);
|
|
295
348
|
return { lines, exit: 1 };
|
|
296
349
|
}
|
|
350
|
+
// task 1002592: ADR 0120 part 3's owed-rebase gate refuses EVERY new claim, so
|
|
351
|
+
// it is the refusal a builder is most stuck behind — and it was the only one
|
|
352
|
+
// with no branch here, printing as a bare `[REBASE_REQUIRED]: REBASE_REQUIRED`
|
|
353
|
+
// code echo. The server builds a full way-forward menu for it
|
|
354
|
+
// (rebaseRequiredHint, task 1003768 — /strand-fix leads because it is the one
|
|
355
|
+
// exit that works with no GitHub push credential, the DOCUMENTED default
|
|
356
|
+
// posture) and this surface dropped it on the floor. Name the owed tasks, then
|
|
357
|
+
// print the server's menu.
|
|
358
|
+
if (code === 'REBASE_REQUIRED') {
|
|
359
|
+
const owed = (d.rebaseTasks || d.rebase_tasks || []).slice(0, MAX_LISTED_TASKS);
|
|
360
|
+
lines.push(owed.length
|
|
361
|
+
? `Your queue is gated — ${owed.length} confirmed task(s) are waiting on your rebase:`
|
|
362
|
+
: 'Your queue is gated — a confirmed task is waiting on your rebase.');
|
|
363
|
+
for (const t of owed) {
|
|
364
|
+
lines.push(` - task ${t.id}${t.title ? ` ${clip(t.title)}` : ''}`);
|
|
365
|
+
if (t.reason) lines.push(` flagged: ${clip(t.reason)}`);
|
|
366
|
+
}
|
|
367
|
+
lines.push(` ${clip(d.hint, 600) || 'Clear it with /strand-fix N, or rebase the branch and re-ship — or /builder-release it to give up on one.'}`);
|
|
368
|
+
return { lines, exit: 1 };
|
|
369
|
+
}
|
|
297
370
|
if (code === 'ALREADY_CLAIMED') {
|
|
298
371
|
lines.push(`Task #${taskId} was just claimed by another session. Try a different task.`);
|
|
299
372
|
return { lines, exit: 1 };
|
|
@@ -356,6 +429,11 @@ function formatClaimFailure(r, taskId) {
|
|
|
356
429
|
}
|
|
357
430
|
// Fallback — still readable: the message + code, never a raw [object Object].
|
|
358
431
|
lines.push(`Claim failed (${r ? r.status : '?'})${code ? ` [${code}]` : ''}${message ? `: ${message}` : ''}.`);
|
|
432
|
+
// task 1002592: whatever the code, if the server sent a way forward, PRINT it.
|
|
433
|
+
// REBASE_REQUIRED sat in this fallback with a fully-formed hint in its body and
|
|
434
|
+
// nothing rendered it. The branches above stay the curated wording; this is the
|
|
435
|
+
// floor, so the next unmapped code can never be mute the same way.
|
|
436
|
+
if (d && d.hint) lines.push(` ${clip(d.hint, 600)}`);
|
|
359
437
|
return { lines, exit: 1 };
|
|
360
438
|
}
|
|
361
439
|
|
|
@@ -488,7 +566,7 @@ async function main() {
|
|
|
488
566
|
// task 1002579: worktree-per-claim, enforced BEFORE anything happens — before
|
|
489
567
|
// the session check, before the POST. The whole point is that the builder
|
|
490
568
|
// learns at claim time, not from a stranded ship hours later.
|
|
491
|
-
enforceWorktreeClaim(taskId, { allowMainCheckout: args.includes(ESCAPE_FLAG) });
|
|
569
|
+
const tree = enforceWorktreeClaim(taskId, { allowMainCheckout: args.includes(ESCAPE_FLAG) });
|
|
492
570
|
await requireSession();
|
|
493
571
|
const wIdx = args.indexOf('--worktree');
|
|
494
572
|
// Explicit --worktree always wins; otherwise auto-detect a linked worktree so
|
|
@@ -527,7 +605,7 @@ async function main() {
|
|
|
527
605
|
if (outcome === 'retry') {
|
|
528
606
|
r = await postClaim();
|
|
529
607
|
} else if (outcome === 'stop') {
|
|
530
|
-
|
|
608
|
+
return cliExit(1); // everything already printed; no claim landed
|
|
531
609
|
}
|
|
532
610
|
}
|
|
533
611
|
if (r.status === 201) {
|
|
@@ -651,9 +729,16 @@ async function main() {
|
|
|
651
729
|
}
|
|
652
730
|
// Any non-201 comes here. formatClaimFailure normalizes the R01 error envelope
|
|
653
731
|
// and renders the refusal as guidance (task 1476) — one place, unit-tested.
|
|
654
|
-
const failure = formatClaimFailure(r, taskId
|
|
732
|
+
const failure = formatClaimFailure(r, taskId, {
|
|
733
|
+
worktree,
|
|
734
|
+
isMainCheckout: tree ? tree.isMainCheckout : null,
|
|
735
|
+
});
|
|
655
736
|
for (const line of failure.lines) console.error(line);
|
|
656
|
-
|
|
737
|
+
// task 1002592: this exit runs immediately after the claim request, which is
|
|
738
|
+
// exactly where Windows aborts teardown — "Assertion failed: !(handle->flags &
|
|
739
|
+
// UV_HANDLE_CLOSING)" — turning a refusal's intended exit 1 into 127. Measured
|
|
740
|
+
// 3/3 aborting before this change. Set the code, let the loop drain (1002734).
|
|
741
|
+
cliExit(failure.exit);
|
|
657
742
|
}
|
|
658
743
|
|
|
659
744
|
// Only auto-run when invoked directly (`node claim.js …`); a `require()` (the
|
|
@@ -661,8 +746,8 @@ async function main() {
|
|
|
661
746
|
if (require.main === module) {
|
|
662
747
|
main().catch((err) => {
|
|
663
748
|
console.error('fatal:', err);
|
|
664
|
-
|
|
749
|
+
cliExit(1);
|
|
665
750
|
});
|
|
666
751
|
}
|
|
667
752
|
|
|
668
|
-
module.exports = { formatClaimFailure, claimErrorInfo, goalMembershipOfferPlan, materializeModeSkills };
|
|
753
|
+
module.exports = { formatClaimFailure, claimErrorInfo, goalMembershipOfferPlan, materializeModeSkills, worktreeDetectionNote };
|
|
@@ -12,6 +12,14 @@
|
|
|
12
12
|
// of a mature instance's CLAUDE.md — the instance grows its own. Coordinates with
|
|
13
13
|
// task 1963 (neutralizing the core's own CLAUDE.md into the portable template).
|
|
14
14
|
//
|
|
15
|
+
// FIRST-RUN SECTION. The template used to open by instructing the agent to run
|
|
16
|
+
// `bongos start` without ever saying the CLI ships inside an uninstalled dependency,
|
|
17
|
+
// so an agent opening a fresh clone followed its first instruction straight into
|
|
18
|
+
// `command not found`. The root README carries the same signpost for humans — but only
|
|
19
|
+
// when the repo had no README to begin with, which an ADOPTED repo always does. This
|
|
20
|
+
// file lands on BOTH paths and loads in full every session, so it is the one place the
|
|
21
|
+
// bootstrap is guaranteed to be read.
|
|
22
|
+
//
|
|
15
23
|
// PURE (branding in → markdown out), so it unit-tests standalone and carries no
|
|
16
24
|
// hardcoded host identity (everything comes from the branding object — R76-safe).
|
|
17
25
|
|
|
@@ -48,6 +56,16 @@ function renderInstanceClaudeMd(branding = {}) {
|
|
|
48
56
|
|
|
49
57
|
Read this at the start of every session. Keep it lean — it loads in full every time.
|
|
50
58
|
|
|
59
|
+
## First run — before any \`bongos\` command
|
|
60
|
+
|
|
61
|
+
**If \`node_modules/@bongos/core\` is missing, run \`npm install\` first.** The \`bongos\` CLI ships *inside* that dependency, so until the install completes there is no \`bongos\` command and every instruction below fails with \`command not found\`:
|
|
62
|
+
|
|
63
|
+
\`\`\`bash
|
|
64
|
+
npm install
|
|
65
|
+
\`\`\`
|
|
66
|
+
|
|
67
|
+
Once per machine, per clone — it is not committed (\`node_modules/\` is ignored on purpose), so a fresh \`git clone\` always needs it. If a \`bongos\` command then still misbehaves, \`bongos doctor\` checks the toolchain and session and prints the fix.
|
|
68
|
+
|
|
51
69
|
## What this is
|
|
52
70
|
|
|
53
71
|
${ident}
|