create-walle 0.10.2 → 0.10.3
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/README.md +3 -1
- package/lib/release-schema.json +2 -2
- package/lib/runtime-closure-policy.json +8 -7
- package/package.json +1 -1
- package/template/coding-task-manager/api-prompts.js +45 -7
- package/template/coding-task-manager/bin/claude-hook.js +55 -1
- package/template/coding-task-manager/bin/ctm-relay-client.js +35 -12
- package/template/coding-task-manager/bin/land.js +2069 -0
- package/template/coding-task-manager/bin/memory-census.js +4 -2
- package/template/coding-task-manager/bin/memory-sync-verify.js +151 -0
- package/template/coding-task-manager/bin/probe-refusal-scope.js +530 -0
- package/template/coding-task-manager/db.js +156 -32
- package/template/coding-task-manager/lib/acp/acp-client.js +383 -0
- package/template/coding-task-manager/lib/acp/dsh-context-truth.js +176 -0
- package/template/coding-task-manager/lib/acp/dsh-launch-model.js +302 -0
- package/template/coding-task-manager/lib/acp/dsh-mcp-servers.js +194 -0
- package/template/coding-task-manager/lib/acp/dsh-prompt-lane.js +616 -0
- package/template/coding-task-manager/lib/acp/dsh-route-patch.js +308 -0
- package/template/coding-task-manager/lib/acp/dsh-session-runtime.js +522 -0
- package/template/coding-task-manager/lib/acp/dsh-transcript.js +395 -0
- package/template/coding-task-manager/lib/acp/dsh-usage-log.js +162 -0
- package/template/coding-task-manager/lib/acp/ndjson-stdio-transport.js +225 -0
- package/template/coding-task-manager/lib/adopted-host-redial.js +47 -11
- package/template/coding-task-manager/lib/adopted-launch-environment.js +123 -0
- package/template/coding-task-manager/lib/agent-auto-update-runtime.js +0 -3
- package/template/coding-task-manager/lib/agent-auto-update.js +26 -10
- package/template/coding-task-manager/lib/agent-bundle/build.js +657 -0
- package/template/coding-task-manager/lib/agent-bundle/codex-install.js +558 -0
- package/template/coding-task-manager/lib/agent-bundle/drift.js +120 -0
- package/template/coding-task-manager/lib/agent-bundle/gc.js +522 -0
- package/template/coding-task-manager/lib/agent-bundle/inventory.js +346 -0
- package/template/coding-task-manager/lib/agent-bundle/push.js +717 -0
- package/template/coding-task-manager/lib/agent-bundle/skill-transfer.js +724 -0
- package/template/coding-task-manager/lib/agent-bundle/spawn.js +119 -0
- package/template/coding-task-manager/lib/agent-bundle/store.js +568 -0
- package/template/coding-task-manager/lib/agent-capabilities.js +142 -12
- package/template/coding-task-manager/lib/agent-cli-cache.js +30 -5
- package/template/coding-task-manager/lib/agent-definitions.js +19 -0
- package/template/coding-task-manager/lib/agent-hooks-codex-toml.js +28 -16
- package/template/coding-task-manager/lib/agent-hooks-codex-workspace.js +9 -1
- package/template/coding-task-manager/lib/agent-hooks-installer.js +23 -8
- package/template/coding-task-manager/lib/agent-hooks-prune.js +37 -11
- package/template/coding-task-manager/lib/agent-hooks-shim.js +105 -0
- package/template/coding-task-manager/lib/agent-presets.js +84 -1
- package/template/coding-task-manager/lib/agent-upgrade-jobs.js +12 -1
- package/template/coding-task-manager/lib/agent-version-service.js +74 -11
- package/template/coding-task-manager/lib/all-sessions-query.js +6 -2
- package/template/coding-task-manager/lib/api/agent-bundles.js +436 -0
- package/template/coding-task-manager/lib/api/backup-retention.js +83 -0
- package/template/coding-task-manager/lib/api/conversation-sync-routes.js +124 -0
- package/template/coding-task-manager/lib/api/diagnostics.js +549 -69
- package/template/coding-task-manager/lib/api/fleet.js +118 -0
- package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
- package/template/coding-task-manager/lib/api/ingress.js +9 -1
- package/template/coding-task-manager/lib/api/landing.js +403 -0
- package/template/coding-task-manager/lib/api/machines.js +691 -2
- package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +8 -3
- package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
- package/template/coding-task-manager/lib/api/session-attach.js +623 -0
- package/template/coding-task-manager/lib/api/session-messages.js +1384 -0
- package/template/coding-task-manager/lib/api/sessions.js +77 -51
- package/template/coding-task-manager/lib/api/setup-network.js +544 -16
- package/template/coding-task-manager/lib/api/setup-wizard-handlers.js +884 -0
- package/template/coding-task-manager/lib/api/setup.js +829 -10
- package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
- package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +23 -0
- package/template/coding-task-manager/lib/auth-rules.js +292 -21
- package/template/coding-task-manager/lib/background-stop.js +369 -0
- package/template/coding-task-manager/lib/best-of-attempts.js +4 -1
- package/template/coding-task-manager/lib/best-of-launch-plan.js +52 -0
- package/template/coding-task-manager/lib/box-keep-awake.js +89 -0
- package/template/coding-task-manager/lib/broadcast-reason-stats.js +152 -0
- package/template/coding-task-manager/lib/broadcast-serialize.js +5 -0
- package/template/coding-task-manager/lib/build-info.js +4 -2
- package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
- package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
- package/template/coding-task-manager/lib/client-diag-handler.js +64 -2
- package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
- package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
- package/template/coding-task-manager/lib/codex-harness-qualification.js +43 -20
- package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
- package/template/coding-task-manager/lib/coding-agent-models.js +27 -12
- package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +43 -2
- package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
- package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +23 -4
- package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
- package/template/coding-task-manager/lib/coding-session-model-state.js +7 -0
- package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
- package/template/coding-task-manager/lib/conversation-item-clock.js +261 -0
- package/template/coding-task-manager/lib/conversation-source-registry.js +5 -0
- package/template/coding-task-manager/lib/conversation-store-v2.js +44 -0
- package/template/coding-task-manager/lib/conversation-sync.js +355 -0
- package/template/coding-task-manager/lib/create/resolve-launch-params.js +96 -12
- package/template/coding-task-manager/lib/create/worker-role-profile.js +4 -4
- package/template/coding-task-manager/lib/create-intent-lease.js +51 -0
- package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
- package/template/coding-task-manager/lib/db-domain-tables.js +1 -0
- package/template/coding-task-manager/lib/db-domains.js +1 -0
- package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
- package/template/coding-task-manager/lib/db-owner-request-counts.js +178 -0
- package/template/coding-task-manager/lib/db-owner-worker-client.js +68 -14
- package/template/coding-task-manager/lib/db-schema-source-files.js +5 -0
- package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
- package/template/coding-task-manager/lib/feature-manifest.js +4 -0
- package/template/coding-task-manager/lib/fleet-conversation-route.js +97 -0
- package/template/coding-task-manager/lib/fleet-fanout.js +78 -0
- package/template/coding-task-manager/lib/fleet-hub.js +762 -0
- package/template/coding-task-manager/lib/fleet-origin-follower.js +252 -0
- package/template/coding-task-manager/lib/fleet-resolver-effects.js +147 -0
- package/template/coding-task-manager/lib/fleet-resolver-tick.js +148 -0
- package/template/coding-task-manager/lib/fleet-resolver.js +454 -0
- package/template/coding-task-manager/lib/fleet-session-list-routes.js +114 -0
- package/template/coding-task-manager/lib/fleet-session-lists.js +672 -0
- package/template/coding-task-manager/lib/fleet-update.js +798 -0
- package/template/coding-task-manager/lib/fs-watcher-root-watch.js +141 -0
- package/template/coding-task-manager/lib/fs-watcher.js +58 -42
- package/template/coding-task-manager/lib/harness-history-transition.js +50 -9
- package/template/coding-task-manager/lib/headless-term-service.js +84 -8
- package/template/coding-task-manager/lib/hermetic-agent-launch-guard.js +10 -0
- package/template/coding-task-manager/lib/history-transition-read-op.js +175 -8
- package/template/coding-task-manager/lib/host-cpu-categories.js +310 -0
- package/template/coding-task-manager/lib/host-fseventsd-sampler.js +399 -0
- package/template/coding-task-manager/lib/host-handoff.js +16 -19
- package/template/coding-task-manager/lib/host-stats.js +150 -3
- package/template/coding-task-manager/lib/hosted-sync-worker.js +43 -320
- package/template/coding-task-manager/lib/hub-bridge-access.js +798 -0
- package/template/coding-task-manager/lib/hub-bridge-box.js +409 -0
- package/template/coding-task-manager/lib/hub-bridge-mcp.js +380 -0
- package/template/coding-task-manager/lib/hub-bridge-mesh.js +313 -0
- package/template/coding-task-manager/lib/hub-bridge-ops.js +721 -0
- package/template/coding-task-manager/lib/hub-bridge.js +398 -0
- package/template/coding-task-manager/lib/idle-notify.js +491 -0
- package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +8 -0
- package/template/coding-task-manager/lib/instance-manifest.js +5 -1
- package/template/coding-task-manager/lib/instance-sync-status.js +18 -8
- package/template/coding-task-manager/lib/landing/agent-rule.txt +1 -0
- package/template/coding-task-manager/lib/landing/batch-runner.js +366 -0
- package/template/coding-task-manager/lib/landing/config.js +536 -0
- package/template/coding-task-manager/lib/landing/ctm-view.js +256 -0
- package/template/coding-task-manager/lib/landing/gate.js +360 -0
- package/template/coding-task-manager/lib/landing/git.js +344 -0
- package/template/coding-task-manager/lib/landing/lease.js +247 -0
- package/template/coding-task-manager/lib/landing/merge-delta.js +380 -0
- package/template/coding-task-manager/lib/landing/proof.js +223 -0
- package/template/coding-task-manager/lib/landing/queue.js +998 -0
- package/template/coding-task-manager/lib/landing/radar.js +489 -0
- package/template/coding-task-manager/lib/landing/resolve-cli.js +424 -0
- package/template/coding-task-manager/lib/landing/state.js +263 -0
- package/template/coding-task-manager/lib/landing/stop.js +49 -0
- package/template/coding-task-manager/lib/landing/sync-cli.js +475 -0
- package/template/coding-task-manager/lib/landing/sync.js +456 -0
- package/template/coding-task-manager/lib/landing/train.js +885 -0
- package/template/coding-task-manager/lib/landing/window.js +57 -0
- package/template/coding-task-manager/lib/launch-environment.js +121 -0
- package/template/coding-task-manager/lib/launch-model-override.js +36 -10
- package/template/coding-task-manager/lib/launch-plan-pool.js +2 -1
- package/template/coding-task-manager/lib/launch-plan-warm-cache.js +6 -0
- package/template/coding-task-manager/lib/lead-model-observer.js +57 -1
- package/template/coding-task-manager/lib/lead-model-options.js +160 -3
- package/template/coding-task-manager/lib/lead-model-restore-reconciliation.js +106 -24
- package/template/coding-task-manager/lib/lead-model-switch-runtime.js +352 -68
- package/template/coding-task-manager/lib/lead-model-switch.js +114 -10
- package/template/coding-task-manager/lib/lead-model-transition-runtime.js +14 -2
- package/template/coding-task-manager/lib/lead-model-transition-store.js +24 -6
- package/template/coding-task-manager/lib/lead-route-preflight.js +179 -0
- package/template/coding-task-manager/lib/lead-switch-history-mode.js +110 -0
- package/template/coding-task-manager/lib/lead-wire-agent.js +7 -0
- package/template/coding-task-manager/lib/lifecycle-wake-experiment.js +9 -2
- package/template/coding-task-manager/lib/live-defer-announce.js +45 -0
- package/template/coding-task-manager/lib/machine-registry.js +750 -5
- package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +433 -53
- package/template/coding-task-manager/lib/mainloop-observability.js +14 -9
- package/template/coding-task-manager/lib/media-draft-owner.js +16 -3
- package/template/coding-task-manager/lib/memory-join.js +337 -0
- package/template/coding-task-manager/lib/memory-sync-verify.js +393 -0
- package/template/coding-task-manager/lib/memory-sync.js +565 -0
- package/template/coding-task-manager/lib/migrations/v57-delegate-pref-mirror-opencode.js +68 -0
- package/template/coding-task-manager/lib/migrations/v58-subagent-launch-native-subagents.js +42 -0
- package/template/coding-task-manager/lib/migrations/v59-coding-session-model-state-dsh.js +73 -0
- package/template/coding-task-manager/lib/migrations/v60-delegate-pref-mirror-dsh.js +78 -0
- package/template/coding-task-manager/lib/migrations/v61-conversation-item-clock.js +71 -0
- package/template/coding-task-manager/lib/model-availability.js +727 -0
- package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +4 -6
- package/template/coding-task-manager/lib/model-host-receipt.js +6 -3
- package/template/coding-task-manager/lib/model-id-rule.js +19 -0
- package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
- package/template/coding-task-manager/lib/model-proxy/auto-mode-review.js +110 -23
- package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
- package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
- package/template/coding-task-manager/lib/model-proxy/historical-tool-declarations.js +37 -0
- package/template/coding-task-manager/lib/model-proxy/lead-request-validation.js +1 -0
- package/template/coding-task-manager/lib/model-proxy/lead-token-admin.js +130 -0
- package/template/coding-task-manager/lib/model-proxy/refusal-scope.js +151 -0
- package/template/coding-task-manager/lib/model-proxy/request-budget-store.js +11 -2
- package/template/coding-task-manager/lib/model-proxy/tokens.js +69 -5
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
- package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
- package/template/coding-task-manager/lib/native-history-control.js +6 -4
- package/template/coding-task-manager/lib/native-lead-settings-client.js +44 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +173 -36
- package/template/coding-task-manager/lib/online-backup-worker-client.js +2 -0
- package/template/coding-task-manager/lib/opencode-cli.js +480 -0
- package/template/coding-task-manager/lib/opencode-launch-model.js +471 -0
- package/template/coding-task-manager/lib/opencode-v1-plugin/model-carrier.mjs +35 -0
- package/template/coding-task-manager/lib/opencode-v2-plugin/server.js +118 -0
- package/template/coding-task-manager/lib/owner-action-manifest-data.json +1 -1
- package/template/coding-task-manager/lib/park-composer-draft.js +54 -0
- package/template/coding-task-manager/lib/park-fresh-relaunch.js +41 -10
- package/template/coding-task-manager/lib/perf-phase-trace.js +72 -0
- package/template/coding-task-manager/lib/perf-summary.js +7 -0
- package/template/coding-task-manager/lib/perf-tracker.js +63 -2
- package/template/coding-task-manager/lib/project-config.js +7 -0
- package/template/coding-task-manager/lib/prompt-purge-v2.js +52 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +72 -15
- package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
- package/template/coding-task-manager/lib/read-pool-client.js +89 -2
- package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
- package/template/coding-task-manager/lib/recent-catalog-query.js +15 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +67 -10
- package/template/coding-task-manager/lib/recovery-evidence.js +26 -11
- package/template/coding-task-manager/lib/relay-client.js +57 -3
- package/template/coding-task-manager/lib/relink-audit.js +34 -5
- package/template/coding-task-manager/lib/remote-machine-catalog.js +321 -26
- package/template/coding-task-manager/lib/remote-machine-create.js +576 -36
- package/template/coding-task-manager/lib/remote-machine-link.js +546 -59
- package/template/coding-task-manager/lib/remote-machine-proxy.js +143 -9
- package/template/coding-task-manager/lib/remote-session-forward.js +65 -7
- package/template/coding-task-manager/lib/remote-terminal-target.js +9 -2
- package/template/coding-task-manager/lib/restart-guard.js +18 -6
- package/template/coding-task-manager/lib/restore-seed-modes.js +87 -0
- package/template/coding-task-manager/lib/restored-scrollback-hydration-runtime.js +22 -2
- package/template/coding-task-manager/lib/resume-admission.js +17 -3
- package/template/coding-task-manager/lib/review-repo-registry.js +58 -19
- package/template/coding-task-manager/lib/root-delivery-runtime.js +2 -2
- package/template/coding-task-manager/lib/root-prompt-flow.js +1 -1
- package/template/coding-task-manager/lib/runtime-contract.js +3 -1
- package/template/coding-task-manager/lib/schema-indexes.js +1 -0
- package/template/coding-task-manager/lib/session-context-locator.js +742 -0
- package/template/coding-task-manager/lib/session-create/attachment.js +2 -2
- package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
- package/template/coding-task-manager/lib/session-create/delegate-worker.js +86 -16
- package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
- package/template/coding-task-manager/lib/session-create/lead-route-launch.js +186 -13
- package/template/coding-task-manager/lib/session-create/native-lead-lifetime.js +55 -3
- package/template/coding-task-manager/lib/session-create/opencode-lead-provider.js +50 -0
- package/template/coding-task-manager/lib/session-create/prepared.js +162 -38
- package/template/coding-task-manager/lib/session-create/provider-process.js +160 -28
- package/template/coding-task-manager/lib/session-create/response.js +7 -7
- package/template/coding-task-manager/lib/session-create/structured-session.js +27 -0
- package/template/coding-task-manager/lib/session-create/subagent-pick-table.js +3 -1
- package/template/coding-task-manager/lib/session-create/subagent-pick.js +458 -9
- package/template/coding-task-manager/lib/session-create/transcript.js +1 -1
- package/template/coding-task-manager/lib/session-create/worker-budget-setup.js +21 -2
- package/template/coding-task-manager/lib/session-create/worker-continuation.js +7 -1
- package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
- package/template/coding-task-manager/lib/session-create/worker-observability.js +2 -2
- package/template/coding-task-manager/lib/session-empty.js +13 -10
- package/template/coding-task-manager/lib/session-host-manager.js +60 -0
- package/template/coding-task-manager/lib/session-jobs.js +3 -1
- package/template/coding-task-manager/lib/session-lifecycle.js +10 -4
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +6 -2
- package/template/coding-task-manager/lib/session-model-intent-contract.js +11 -8
- package/template/coding-task-manager/lib/session-park.js +738 -0
- package/template/coding-task-manager/lib/session-path-grant.js +13 -4
- package/template/coding-task-manager/lib/session-status-ledger.js +106 -4
- package/template/coding-task-manager/lib/session-transport.js +17 -0
- package/template/coding-task-manager/lib/session-workspace-projection.js +54 -5
- package/template/coding-task-manager/lib/session-workspace-tracking-runtime.js +213 -1
- package/template/coding-task-manager/lib/skill-autocomplete-query.js +120 -3
- package/template/coding-task-manager/lib/skill-autocomplete.js +15 -1
- package/template/coding-task-manager/lib/sqlite-file-set.js +39 -0
- package/template/coding-task-manager/lib/standup-search-adapter.js +16 -2
- package/template/coding-task-manager/lib/state-sync/client-ledger.js +12 -0
- package/template/coding-task-manager/lib/state-sync/frame-emitter.js +319 -100
- package/template/coding-task-manager/lib/storage/coding-session-model-store.js +4 -1
- package/template/coding-task-manager/lib/storage/delegate-pref-mirror-store.js +32 -9
- package/template/coding-task-manager/lib/structured-session-boot-sweep.js +235 -0
- package/template/coding-task-manager/lib/submission-ack.js +90 -2
- package/template/coding-task-manager/lib/systemd-scope.js +115 -0
- package/template/coding-task-manager/lib/telemetry-receiver.js +39 -0
- package/template/coding-task-manager/lib/terminal-attach-geometry.js +985 -0
- package/template/coding-task-manager/lib/terminal-bootstrap.js +30 -0
- package/template/coding-task-manager/lib/terminal-draft-operation.js +357 -0
- package/template/coding-task-manager/lib/terminal-input-admission.js +17 -1
- package/template/coding-task-manager/lib/terminal-input-prepared.js +563 -0
- package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
- package/template/coding-task-manager/lib/transcript-frame-cache.js +8 -3
- package/template/coding-task-manager/lib/transcript-source.js +36 -4
- package/template/coding-task-manager/lib/transcript-store.js +9 -0
- package/template/coding-task-manager/lib/typing-interaction-trace.js +106 -3
- package/template/coding-task-manager/lib/usage-ledger/backfill.js +40 -5
- package/template/coding-task-manager/lib/usage-ledger/client.js +4 -1
- package/template/coding-task-manager/lib/usage-ledger/dsh-parse.js +152 -0
- package/template/coding-task-manager/lib/usage-ledger/dsh-read.js +73 -0
- package/template/coding-task-manager/lib/usage-ledger/ingest.js +34 -6
- package/template/coding-task-manager/lib/usage-ledger/live.js +35 -8
- package/template/coding-task-manager/lib/usage-ledger/read.js +29 -20
- package/template/coding-task-manager/lib/usage-ledger/schema.js +61 -1
- package/template/coding-task-manager/lib/usage-ledger/task-coordinator.js +4 -2
- package/template/coding-task-manager/lib/wake-skip-reasons.js +1 -0
- package/template/coding-task-manager/lib/walle/turn.js +1 -1
- package/template/coding-task-manager/lib/walle-history-serve.js +838 -0
- package/template/coding-task-manager/lib/walle-kill-authority.js +2 -2
- package/template/coding-task-manager/lib/walle-log-rotation.js +164 -1
- package/template/coding-task-manager/lib/walle-mcp-auto-config.js +56 -2
- package/template/coding-task-manager/lib/walle-row-history.js +495 -0
- package/template/coding-task-manager/lib/walle-supervisor.js +33 -14
- package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
- package/template/coding-task-manager/lib/worker-terminal-output.js +5 -2
- package/template/coding-task-manager/lib/ws/hub-bridge.js +35 -0
- package/template/coding-task-manager/lib/ws/lifecycle.js +6 -11
- package/template/coding-task-manager/lib/ws/misc.js +1 -1
- package/template/coding-task-manager/lib/ws/state-sync.js +106 -4
- package/template/coding-task-manager/lib/ws/terminal-attach.js +91 -0
- package/template/coding-task-manager/oauth-proxy.js +112 -115
- package/template/coding-task-manager/package-lock.json +10 -94
- package/template/coding-task-manager/package.json +4 -3
- package/template/coding-task-manager/protocol/message-table.json +10 -0
- package/template/coding-task-manager/protocol/messages.js +10 -0
- package/template/coding-task-manager/protocol/ws-schema.json +20 -0
- package/template/coding-task-manager/protocol/ws-schema.md +2 -0
- package/template/coding-task-manager/public/css/app.css +170 -0
- package/template/coding-task-manager/public/css/walle-session.css +4 -0
- package/template/coding-task-manager/public/index.html +473 -243
- package/template/coding-task-manager/public/js/agent-command.js +86 -0
- package/template/coding-task-manager/public/js/app/backups-panel.js +111 -5
- package/template/coding-task-manager/public/js/app/coding-agent-upgrade.js +103 -4
- package/template/coding-task-manager/public/js/app/machines-page.js +1328 -8
- package/template/coding-task-manager/public/js/app/models-tab.js +113 -38
- package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +184 -2
- package/template/coding-task-manager/public/js/background-work.js +196 -27
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +138 -10
- package/template/coding-task-manager/public/js/core/active-session-groups.js +179 -0
- package/template/coding-task-manager/public/js/core/pending-create.js +238 -0
- package/template/coding-task-manager/public/js/core/recent-machine-source.js +228 -0
- package/template/coding-task-manager/public/js/core/session-commands.js +180 -14
- package/template/coding-task-manager/public/js/dashboard-client-function-order.json +8 -0
- package/template/coding-task-manager/public/js/document-review-links.js +9 -1
- package/template/coding-task-manager/public/js/file-resolution-client.js +52 -1
- package/template/coding-task-manager/public/js/history-app-seam.js +22 -2
- package/template/coding-task-manager/public/js/machine-pool-shared.js +558 -3
- package/template/coding-task-manager/public/js/message-renderer.js +4 -3
- package/template/coding-task-manager/public/js/model-picker.js +3 -1
- package/template/coding-task-manager/public/js/native-subagent-review.js +15 -2
- package/template/coding-task-manager/public/js/new-session-agent-grid.js +346 -0
- package/template/coding-task-manager/public/js/pasted-content.js +236 -0
- package/template/coding-task-manager/public/js/pe-private-content-lifetime.js +39 -7
- package/template/coding-task-manager/public/js/private-model-lifetime.js +6 -2
- package/template/coding-task-manager/public/js/prompts.js +11 -10
- package/template/coding-task-manager/public/js/protocol.js +10 -0
- package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
- package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
- package/template/coding-task-manager/public/js/session-search-utils.js +18 -2
- package/template/coding-task-manager/public/js/session-usage-view.js +2 -1
- package/template/coding-task-manager/public/js/session-workspace-tracking.js +51 -1
- package/template/coding-task-manager/public/js/state-sync-client.js +10 -1
- package/template/coding-task-manager/public/js/stream-view.js +6 -5
- package/template/coding-task-manager/public/js/terminal/conv-only-session.js +287 -0
- package/template/coding-task-manager/public/js/terminal/runtime-09.js +2 -0
- package/template/coding-task-manager/public/js/terminal/runtime-10.js +5 -5
- package/template/coding-task-manager/public/js/terminal/runtime-12.js +8 -1
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +4 -0
- package/template/coding-task-manager/public/js/terminal/runtime-20.js +1 -1
- package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
- package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
- package/template/coding-task-manager/public/js/terminal-wheel.js +23 -3
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +4 -4
- package/template/coding-task-manager/public/js/walle.js +6 -0
- package/template/coding-task-manager/public/js/ws/live-dispatch.js +10 -0
- package/template/coding-task-manager/public/m/app.css +140 -0
- package/template/coding-task-manager/public/m/app.js +507 -68
- package/template/coding-task-manager/public/m/index.html +17 -0
- package/template/coding-task-manager/public/m/machines.js +838 -4
- package/template/coding-task-manager/public/m/private-api.js +31 -1
- package/template/coding-task-manager/public/usage.html +1 -0
- package/template/coding-task-manager/scripts/dev-route-fixture/synthetic-route-upstream.js +104 -0
- package/template/coding-task-manager/scripts/dev-route-fixture.js +339 -0
- package/template/coding-task-manager/scripts/opencode-lead-route-probe.js +195 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/fake-anthropic.js +168 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/probe-plugin/server.js +95 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe.js +673 -0
- package/template/coding-task-manager/server.js +1950 -11679
- package/template/coding-task-manager/session-integrity.js +64 -4
- package/template/coding-task-manager/workers/db-owner-worker.js +19 -2
- package/template/coding-task-manager/workers/online-backup-worker.js +1 -0
- package/template/coding-task-manager/workers/read-pool-model-collector.js +51 -3
- package/template/coding-task-manager/workers/read-pool-worker.js +76 -6
- package/template/coding-task-manager/workers/session-host-pool-process.js +6 -6
- package/template/coding-task-manager/workers/session-host-process.js +5 -5
- package/template/coding-task-manager/workers/watch-worker.js +105 -0
- package/template/coding-task-manager/workers/worktree-worker.js +168 -33
- package/template/ctm-relay/lib/protocol.js +14 -1
- package/template/package-lock.json +2 -2
- package/template/package.json +1 -1
- package/template/shared/backup-retention.js +82 -0
- package/template/shared/conversation-admission.js +2 -0
- package/template/shared/conversation-provenance.js +3 -7
- package/template/shared/conversation-storage-v2-contract.js +5 -0
- package/template/shared/linked-worktree.js +51 -0
- package/template/shared/macos-fda-target.js +57 -0
- package/template/shared/orphan-parents.js +55 -0
- package/template/shared/release-schema.json +2 -2
- package/template/shared/storage/contract.js +3 -0
- package/template/wall-e/adapters/imessage.js +12 -0
- package/template/wall-e/agent.js +71 -4
- package/template/wall-e/api-walle.js +21 -1
- package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +5 -5
- package/template/wall-e/brain/brain-join.js +859 -0
- package/template/wall-e/brain/brain-sync-membership.js +20 -0
- package/template/wall-e/brain/brain-sync-store.js +131 -77
- package/template/wall-e/brain/brain-sync-v2-schema.js +203 -0
- package/template/wall-e/brain/brain-sync-v2.js +578 -0
- package/template/wall-e/brain/delegate-model-prefs-store.js +13 -4
- package/template/wall-e/brain/deterministic-id.js +51 -0
- package/template/wall-e/brain/memories.js +2 -2
- package/template/wall-e/brain/migrations.js +40 -6
- package/template/wall-e/brain/model-identity-migration.js +1 -1
- package/template/wall-e/brain/owner-call-whitelist.js +23 -7
- package/template/wall-e/brain/schema.js +45 -85
- package/template/wall-e/brain.js +171 -35
- package/template/wall-e/chat.js +3 -3
- package/template/wall-e/coding/agent-shell-env.js +7 -2
- package/template/wall-e/coding/prompt-bundle.js +66 -21
- package/template/wall-e/config/main-loop-exemptions.json +2 -2
- package/template/wall-e/http/admin-api.js +37 -0
- package/template/wall-e/http/gws-api.js +4 -0
- package/template/wall-e/http/helper-rules-api.js +7 -1
- package/template/wall-e/http/model-admin.js +8 -1
- package/template/wall-e/http/model-delegate-pref-admin.js +3 -3
- package/template/wall-e/http/model-proxy-providers.js +174 -1
- package/template/wall-e/http/model-route-health.js +157 -0
- package/template/wall-e/http/sync-api.js +278 -464
- package/template/wall-e/jobs/job-runner.js +28 -1
- package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
- package/template/wall-e/lib/ctm-data-dir.js +26 -0
- package/template/wall-e/lib/derivation-home.js +147 -0
- package/template/wall-e/lib/helper-rules/evaluate.js +50 -9
- package/template/wall-e/lib/helper-rules/grade.js +51 -8
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +38 -5
- package/template/wall-e/lib/helper-rules/store.js +4 -2
- package/template/wall-e/lib/landing-mcp-tools.js +170 -0
- package/template/wall-e/lib/mcp-client-config.js +133 -14
- package/template/wall-e/lib/mcp-gateway-migrate.js +28 -64
- package/template/wall-e/lib/mcp-integration.js +58 -13
- package/template/wall-e/lib/parent-death.js +7 -1
- package/template/wall-e/lib/scheduler-worker-jobs.js +6 -4
- package/template/wall-e/llm/delegate-lead-prefs.js +16 -1
- package/template/wall-e/llm/delegate-vendor-default.js +12 -5
- package/template/wall-e/llm/model-roles.js +1 -1
- package/template/wall-e/llm/native-delegate-selection.js +56 -8
- package/template/wall-e/llm/worker-delegate-args.js +72 -7
- package/template/wall-e/llm/worker-mcp-routing.js +66 -17
- package/template/wall-e/loops/brain-custom-writes.js +19 -0
- package/template/wall-e/loops/ingest.js +17 -1
- package/template/wall-e/loops/think.js +19 -4
- package/template/wall-e/mcp-contract.js +222 -6
- package/template/wall-e/mcp-protocol-contract.js +40 -5
- package/template/wall-e/mcp-server.js +128 -29
- package/template/wall-e/mcp-worker-schemas.js +5 -5
- package/template/wall-e/memory/ctm-context-client.js +85 -0
- package/template/wall-e/memory/ctm-session-context.js +9 -3
- package/template/wall-e/memory/hub-bridge-client.js +388 -0
- package/template/wall-e/memory/replica-origin.js +56 -0
- package/template/wall-e/memory/session-pool.js +135 -0
- package/template/wall-e/runtime/live-capabilities.js +8 -3
- package/template/wall-e/server.js +4 -2
- package/template/wall-e/shared/release-schema.json +2 -2
- package/template/wall-e/shared/sqlite-file-set.js +39 -0
- package/template/wall-e/shared/storage/contract.js +3 -0
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +7 -1
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +4 -4
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +6 -6
- package/template/wall-e/skills/_templates/fleet-sync/VERSION +1 -0
- package/template/wall-e/skills/_templates/fleet-sync/released-sha256.json +16 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/claude/SKILL.md +64 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/codex/SKILL.md +64 -0
- package/template/wall-e/tools/chrome-automation.js +6 -0
- package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
- package/template/wall-e/workers/brain-owner-worker.js +18 -4
- package/template/wall-e/workers/mcp-gateway-process.js +5 -5
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// WP-0 (docs/local-landing-queue-multi-session-integration-2026-10-26.html §6.1, §5 D-1/D-6, §8
|
|
3
|
+
// WP-0): the landing queue's configuration, read from `.ctm.json#landing` through the SAME walker
|
|
4
|
+
// CTM already uses (lib/project-config.js) — one file, one walker, one schema, no flags (D-1).
|
|
5
|
+
//
|
|
6
|
+
// Validation is strict on purpose (§6.1): unknown keys are rejected, `mode` is `"serial"` only
|
|
7
|
+
// until WP-8, `cachePaths` must be git-ignored, and every `regenerate.paths` glob must match at
|
|
8
|
+
// least one tracked path. Every failure is a typed Error (`.code`).
|
|
9
|
+
//
|
|
10
|
+
// A repo without `.ctm.json` is normal (autodetect is the whole point of §6.1), so the loader
|
|
11
|
+
// works from the repository TOPLEVEL: an unconfigured repo still gets gates from autodetect, and
|
|
12
|
+
// a submit from a subdirectory behaves exactly like one from the root. A `.ctm.json` found above
|
|
13
|
+
// the toplevel (`~/ws/.ctm.json` for a repo in `~/ws/x`) is somebody else's config and is
|
|
14
|
+
// ignored, never inherited. Outside a repository there is nothing to land into: `not_a_repo`.
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const crypto = require('crypto');
|
|
19
|
+
const { findProjectConfig } = require('../project-config');
|
|
20
|
+
const { landingError, revParseOrNull, runGitRaw, toplevel } = require('./git');
|
|
21
|
+
|
|
22
|
+
const ALLOWED_KEYS = Object.freeze(['target', 'mode', 'gates', 'regenerate', 'refresh', 'registries', 'cachePaths', 'guard', 'triage', 'batch', 'publish']);
|
|
23
|
+
const DEFAULT_GATE_TIMEOUT_SECONDS = 3600;
|
|
24
|
+
// Off unless the repo asks for it (§7 E-1 / `land init --guard`).
|
|
25
|
+
const DEFAULT_GUARD = false;
|
|
26
|
+
// §5 D-7: at most this many failed test files are rerun on the base commit (WP-2).
|
|
27
|
+
const DEFAULT_TRIAGE_MAX_FILES = 8;
|
|
28
|
+
// The only key `landing.triage` understands today.
|
|
29
|
+
const TRIAGE_KEYS = Object.freeze(['maxFiles']);
|
|
30
|
+
// §5 D-3 / §6 (WP-1): the batch window's ceiling and how long a lone job waits for company. Both are
|
|
31
|
+
// defaults in code, never flags — batching is default-ON with a ceiling of 8 and no waiting, so a
|
|
32
|
+
// repository with no `landing.batch` key behaves exactly as it did before this change (`max: 1` is the
|
|
33
|
+
// serial queue; `waitSeconds: 0` means a ready train never waits).
|
|
34
|
+
const DEFAULT_BATCH_MAX = 8;
|
|
35
|
+
const DEFAULT_BATCH_WAIT_SECONDS = 0;
|
|
36
|
+
// The only keys `landing.batch` understands today.
|
|
37
|
+
const BATCH_KEYS = Object.freeze(['max', 'waitSeconds']);
|
|
38
|
+
|
|
39
|
+
// WP-0/WP-1 (docs/fleet-origin-main-sync-skill-2026-10-31.html §6.1): `landing.publish` — the origin
|
|
40
|
+
// half of the landing policy. Absent = `land sync` is off for that repository (other users' repos are
|
|
41
|
+
// unaffected, and there is no env flag). Present = on, with the §6.1 defaults below.
|
|
42
|
+
const PUBLISH_KEYS = Object.freeze([
|
|
43
|
+
'remote', 'branch', 'auto', 'follow', 'followIntervalMs', 'maxRetrains',
|
|
44
|
+
// WP-6 (docs/fleet-origin-main-sync-skill-2026-10-31.html §13.4 R-R3/R-R4, §13.7): the resolver
|
|
45
|
+
// half of the publish policy. `resolve` says whether CTM opens a resolver session at all, the
|
|
46
|
+
// three others describe that session and the FAST gate its resolution runs.
|
|
47
|
+
'resolve', 'resolveAgent', 'resolveMaxMinutes', 'resolveFastGate',
|
|
48
|
+
]);
|
|
49
|
+
const DEFAULT_PUBLISH_REMOTE = 'origin';
|
|
50
|
+
const DEFAULT_PUBLISH_BRANCH = 'main';
|
|
51
|
+
// §5 R-9 (auto-publish after a landing) and R-8 (the CTM follower) are both default-ON.
|
|
52
|
+
const DEFAULT_PUBLISH_AUTO = true;
|
|
53
|
+
const DEFAULT_PUBLISH_FOLLOW = true;
|
|
54
|
+
// §5 R-8: fetch origin every 15 minutes.
|
|
55
|
+
const DEFAULT_PUBLISH_FOLLOW_INTERVAL_MS = 900000;
|
|
56
|
+
// §5 R-4: at most this many extra trains on a rejected push.
|
|
57
|
+
const DEFAULT_PUBLISH_MAX_RETRAINS = 3;
|
|
58
|
+
// §13.4 R-R1/R-R2: `session` = a blocked conflict (or a failed gate) becomes a visible resolver
|
|
59
|
+
// session; `off` = rev-2 behaviour (the follower keeps `--pull-only`).
|
|
60
|
+
const DEFAULT_PUBLISH_RESOLVE = 'session';
|
|
61
|
+
// §13.4 D-R2: which agent harness the resolver session runs on.
|
|
62
|
+
const DEFAULT_PUBLISH_RESOLVE_AGENT = 'claude';
|
|
63
|
+
// §13.4 R-R8: the resolver's wall-clock budget, in minutes (10 min .. 24 h).
|
|
64
|
+
const DEFAULT_PUBLISH_RESOLVE_MAX_MINUTES = 120;
|
|
65
|
+
const RESOLVE_MODES = Object.freeze(['session', 'off']);
|
|
66
|
+
const RESOLVE_AGENTS = Object.freeze(['claude', 'codex']);
|
|
67
|
+
const RESOLVE_MAX_MINUTES_MIN = 10;
|
|
68
|
+
const RESOLVE_MAX_MINUTES_MAX = 1440;
|
|
69
|
+
// §13.4 R-R4: the FAST gate a `kind:"resolve"` job runs instead of `landing.gates`. It is a gate
|
|
70
|
+
// entry in every respect (`{name, run, timeoutSeconds}`, run in the train worktree), so it is
|
|
71
|
+
// validated by the very same `normalizeGate`.
|
|
72
|
+
const DEFAULT_PUBLISH_RESOLVE_FAST_GATE = Object.freeze({
|
|
73
|
+
name: 'resolve-fast-gate',
|
|
74
|
+
run: 'bash bin/resolve-fast-gate.sh',
|
|
75
|
+
timeoutSeconds: 2400,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
function isPlainObject(value) {
|
|
79
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isNonEmptyString(value) {
|
|
83
|
+
return typeof value === 'string' && value.trim() !== '';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function realpathOr(dir) {
|
|
87
|
+
try {
|
|
88
|
+
return fs.realpathSync(dir);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
/* expected: the directory vanished between the walk and this call; the resolved-path form is
|
|
91
|
+
still a usable answer for the containment test */
|
|
92
|
+
return path.resolve(dir);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// True when `child` is `parent` itself or lies underneath it. Both sides must be resolved paths.
|
|
97
|
+
function isInside(parent, child) {
|
|
98
|
+
const rel = path.relative(parent, child);
|
|
99
|
+
return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// §6.1: `landing.target` defaults to the repo's main branch. This mirrors
|
|
103
|
+
// coding-task-manager/git-utils.js `resolveMainBranch` (origin/HEAD -> main -> master) for the
|
|
104
|
+
// local-branch part only; the local form is used because git-utils.js is async and pulls two
|
|
105
|
+
// extra modules (../shared/git-remote-key, ./lib/async-semaphore) into a library that must stay
|
|
106
|
+
// dependency-free and synchronous.
|
|
107
|
+
function resolveMainBranch(cwd) {
|
|
108
|
+
if (revParseOrNull(cwd, 'refs/heads/main')) return 'main';
|
|
109
|
+
if (revParseOrNull(cwd, 'refs/heads/master')) return 'master';
|
|
110
|
+
return 'main';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function readFileSafe(file) {
|
|
114
|
+
try {
|
|
115
|
+
return fs.readFileSync(file, 'utf8');
|
|
116
|
+
} catch (error) {
|
|
117
|
+
/* expected: the ecosystem probe file is absent or unreadable -> not this ecosystem */
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// §6.1 autodetect, first match in the documented order. A repo that matches nothing gates
|
|
123
|
+
// nothing, which is a refusal at `land submit` time (config_gates_missing), never a silent pass.
|
|
124
|
+
// `readRel(rel)` returns a file's text or null; it defaults to the working tree at `cwd`, and the
|
|
125
|
+
// target-policy loader passes a reader over the target commit instead.
|
|
126
|
+
function autodetectGates(cwd, readRel = (rel) => readFileSafe(path.join(cwd, rel))) {
|
|
127
|
+
const gate = (name, run) => [{ name, run, timeoutSeconds: DEFAULT_GATE_TIMEOUT_SECONDS }];
|
|
128
|
+
const pkgRaw = readRel('package.json');
|
|
129
|
+
if (pkgRaw !== null) {
|
|
130
|
+
try {
|
|
131
|
+
const pkg = JSON.parse(pkgRaw);
|
|
132
|
+
if (pkg && isPlainObject(pkg.scripts) && isNonEmptyString(pkg.scripts.test)) {
|
|
133
|
+
return { gates: gate('npm-test', 'npm test'), gatesSource: 'autodetect' };
|
|
134
|
+
}
|
|
135
|
+
} catch (error) {
|
|
136
|
+
/* expected: an unparseable package.json is not a test command; fall through to the next
|
|
137
|
+
ecosystem probe (and `land doctor` reports the parse failure separately) */
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const makefile = readRel('Makefile');
|
|
141
|
+
if (makefile !== null && /^test\s*:/m.test(makefile)) {
|
|
142
|
+
return { gates: gate('make-test', 'make test'), gatesSource: 'autodetect' };
|
|
143
|
+
}
|
|
144
|
+
if (readRel('pyproject.toml') !== null) {
|
|
145
|
+
return { gates: gate('pytest', 'python -m pytest'), gatesSource: 'autodetect' };
|
|
146
|
+
}
|
|
147
|
+
if (readRel('Cargo.toml') !== null) {
|
|
148
|
+
return { gates: gate('cargo-test', 'cargo test'), gatesSource: 'autodetect' };
|
|
149
|
+
}
|
|
150
|
+
if (readRel('go.mod') !== null) {
|
|
151
|
+
return { gates: gate('go-test', 'go test ./...'), gatesSource: 'autodetect' };
|
|
152
|
+
}
|
|
153
|
+
return { gates: [], gatesSource: 'none' };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function normalizeGate(cwd, entry, index, label) {
|
|
157
|
+
const where = label || `landing.gates[${index}]`;
|
|
158
|
+
if (!isPlainObject(entry)) {
|
|
159
|
+
throw landingError('config_invalid', `${where} must be an object`, { index, configDir: cwd });
|
|
160
|
+
}
|
|
161
|
+
if (!isNonEmptyString(entry.name)) {
|
|
162
|
+
throw landingError('config_invalid', `${where}.name must be a non-empty string`, { index, configDir: cwd });
|
|
163
|
+
}
|
|
164
|
+
if (!isNonEmptyString(entry.run)) {
|
|
165
|
+
throw landingError('config_invalid', `${where}.run must be a non-empty string`, { index, configDir: cwd });
|
|
166
|
+
}
|
|
167
|
+
const timeoutSeconds = entry.timeoutSeconds === undefined ? DEFAULT_GATE_TIMEOUT_SECONDS : entry.timeoutSeconds;
|
|
168
|
+
if (!Number.isFinite(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
169
|
+
throw landingError('config_invalid', `${where}.timeoutSeconds must be a positive number`, { index, configDir: cwd });
|
|
170
|
+
}
|
|
171
|
+
return { name: entry.name, run: entry.run, timeoutSeconds };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function isIgnoredByGit(cwd, relPath) {
|
|
175
|
+
const res = runGitRaw(cwd, ['check-ignore', '-q', '--', relPath]);
|
|
176
|
+
if (res.status === 0) return true;
|
|
177
|
+
if (res.status === 1) return false;
|
|
178
|
+
throw landingError('git_failed', `git check-ignore failed for ${relPath}`, { path: relPath, cwd, status: res.status, stderr: res.stderr });
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// §6.1 calls the entry a glob, so it is matched with git's `:(glob)` magic: `**` then means
|
|
182
|
+
// "zero or more directories" (`src/**/*.js` matches `src/index.js` as well as `src/a/b.js`),
|
|
183
|
+
// whereas a bare pathspec would exclude the zero-directory case. A literal path is unaffected.
|
|
184
|
+
function matchesTrackedFile(cwd, pattern) {
|
|
185
|
+
const res = runGitRaw(cwd, ['ls-files', '--', `:(glob)${pattern}`]);
|
|
186
|
+
if (res.status !== 0) {
|
|
187
|
+
throw landingError('git_failed', `git ls-files failed for ${pattern}`, { path: pattern, cwd, status: res.status, stderr: res.stderr });
|
|
188
|
+
}
|
|
189
|
+
return res.stdout.trim() !== '';
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// sha256 of the gate array — the second half of the verdict cache key (D-4).
|
|
193
|
+
function gatesHash(gates) {
|
|
194
|
+
return crypto.createHash('sha256').update(JSON.stringify(gates)).digest('hex');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// The validated landing config for `cwd` (which may be any directory inside the repo, including
|
|
198
|
+
// a subdirectory or a linked worktree). `configDir` is the directory the answers are relative to:
|
|
199
|
+
// the `.ctm.json` directory when the repo is configured, otherwise the repository toplevel.
|
|
200
|
+
function loadLandingConfig(cwd) {
|
|
201
|
+
const top = toplevel(cwd);
|
|
202
|
+
const found = findProjectConfig(cwd);
|
|
203
|
+
const foundDir = found ? realpathOr(found.dir) : null;
|
|
204
|
+
// A config above the repo is not this repo's config.
|
|
205
|
+
const usable = foundDir && isInside(top, foundDir) ? { dir: foundDir, data: found.data } : null;
|
|
206
|
+
const configDir = usable ? usable.dir : top;
|
|
207
|
+
const raw = usable && usable.data ? usable.data.landing : undefined;
|
|
208
|
+
return validateLanding(raw, {
|
|
209
|
+
configDir,
|
|
210
|
+
readRel: (rel) => readFileSafe(path.join(configDir, rel)),
|
|
211
|
+
matchesTracked: (pattern) => matchesTrackedFile(configDir, pattern),
|
|
212
|
+
targetDefault: () => resolveMainBranch(configDir),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// The landing policy the queue enforces: the `landing` object of the `.ctm.json` COMMITTED at the
|
|
217
|
+
// tip of the target branch (repository root), with gate autodetect read from that same commit. A
|
|
218
|
+
// branch can therefore never weaken the gate it is landed under by editing its own `.ctm.json`;
|
|
219
|
+
// a policy change takes effect only once it has itself landed. The submitter's working tree
|
|
220
|
+
// supplies only the target branch name. `cwd` is any directory inside the repository.
|
|
221
|
+
function loadTargetLandingConfig(cwd) {
|
|
222
|
+
const local = loadLandingConfig(cwd);
|
|
223
|
+
const top = toplevel(cwd);
|
|
224
|
+
const rev = `refs/heads/${local.target}`;
|
|
225
|
+
if (!revParseOrNull(top, rev)) {
|
|
226
|
+
throw landingError('target_missing', `target branch ${JSON.stringify(local.target)} does not exist`, { target: local.target });
|
|
227
|
+
}
|
|
228
|
+
const readRel = (rel) => {
|
|
229
|
+
const res = runGitRaw(top, ['show', `${rev}:${rel}`]);
|
|
230
|
+
return res.status === 0 ? res.stdout : null;
|
|
231
|
+
};
|
|
232
|
+
let data = null;
|
|
233
|
+
const text = readRel('.ctm.json');
|
|
234
|
+
if (text !== null) {
|
|
235
|
+
try {
|
|
236
|
+
data = JSON.parse(text);
|
|
237
|
+
} catch (error) {
|
|
238
|
+
throw landingError('config_invalid', `.ctm.json on ${local.target} is not valid JSON: ${error.message}`, { target: local.target, cause: error });
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const raw = data && typeof data === 'object' ? data.landing : undefined;
|
|
242
|
+
const config = validateLanding(raw, {
|
|
243
|
+
configDir: top,
|
|
244
|
+
readRel,
|
|
245
|
+
// Authoring-time check only (land init / doctor validate the working tree); a committed policy
|
|
246
|
+
// is not re-validated against the tree it was committed with.
|
|
247
|
+
matchesTracked: () => true,
|
|
248
|
+
targetDefault: () => local.target,
|
|
249
|
+
});
|
|
250
|
+
// The target named by the committed policy wins only when it agrees; a disagreement means the
|
|
251
|
+
// submitter and the target disagree about where work lands, which is a refusal, not a guess.
|
|
252
|
+
if (config.target !== local.target) {
|
|
253
|
+
throw landingError('config_target_mismatch', `.ctm.json on ${local.target} names target ${JSON.stringify(config.target)}`, {
|
|
254
|
+
local: local.target, committed: config.target,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return { ...config, policySource: rev };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function validateLanding(raw, { configDir, readRel, matchesTracked, targetDefault }) {
|
|
261
|
+
if (raw !== undefined && raw !== null && !isPlainObject(raw)) {
|
|
262
|
+
throw landingError('config_invalid', `landing must be a JSON object in ${configDir}/.ctm.json`, { configDir });
|
|
263
|
+
}
|
|
264
|
+
const landing = raw || {};
|
|
265
|
+
for (const key of Object.keys(landing)) {
|
|
266
|
+
if (!ALLOWED_KEYS.includes(key)) {
|
|
267
|
+
throw landingError('config_unknown_key', `unknown landing key ${JSON.stringify(key)}`, {
|
|
268
|
+
key, configDir, allowed: [...ALLOWED_KEYS],
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const mode = landing.mode === undefined ? 'serial' : landing.mode;
|
|
273
|
+
if (mode !== 'serial') {
|
|
274
|
+
throw landingError('config_mode_unsupported', `landing.mode ${JSON.stringify(mode)} is not supported (only "serial" until WP-8)`, {
|
|
275
|
+
mode, configDir,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
let gates;
|
|
279
|
+
let gatesSource;
|
|
280
|
+
if (landing.gates === undefined) {
|
|
281
|
+
const detected = autodetectGates(configDir, readRel);
|
|
282
|
+
gates = detected.gates;
|
|
283
|
+
gatesSource = detected.gatesSource;
|
|
284
|
+
} else {
|
|
285
|
+
if (!Array.isArray(landing.gates)) {
|
|
286
|
+
throw landingError('config_invalid', 'landing.gates must be an array', { configDir });
|
|
287
|
+
}
|
|
288
|
+
gates = landing.gates.map((entry, index) => normalizeGate(configDir, entry, index));
|
|
289
|
+
gatesSource = 'config';
|
|
290
|
+
}
|
|
291
|
+
const regenerate = normalizePathEntries(landing.regenerate, 'regenerate', { configDir, matchesTracked });
|
|
292
|
+
// WP-0 (design §5 D-2, §9 S-4): `refresh` runs like `regenerate` but on EVERY train — it is how a
|
|
293
|
+
// tree-derived pin (the closure policy's digests) is rebuilt from the merged tree rather than
|
|
294
|
+
// merged as a scalar. Validated identically, so a glob that owns nothing is a config error.
|
|
295
|
+
const refresh = normalizePathEntries(landing.refresh, 'refresh', { configDir, matchesTracked });
|
|
296
|
+
const registries = [];
|
|
297
|
+
if (landing.registries !== undefined) {
|
|
298
|
+
if (!Array.isArray(landing.registries) || !landing.registries.every(isNonEmptyString)) {
|
|
299
|
+
throw landingError('config_invalid', 'landing.registries must be an array of strings', { configDir });
|
|
300
|
+
}
|
|
301
|
+
registries.push(...landing.registries);
|
|
302
|
+
}
|
|
303
|
+
const cachePaths = [];
|
|
304
|
+
if (landing.cachePaths !== undefined) {
|
|
305
|
+
if (!Array.isArray(landing.cachePaths) || !landing.cachePaths.every(isNonEmptyString)) {
|
|
306
|
+
throw landingError('config_invalid', 'landing.cachePaths must be an array of strings', { configDir });
|
|
307
|
+
}
|
|
308
|
+
for (const cachePath of landing.cachePaths) {
|
|
309
|
+
if (!isIgnoredByGit(configDir, cachePath)) {
|
|
310
|
+
throw landingError('config_cache_path_not_ignored', `landing.cachePaths entry ${JSON.stringify(cachePath)} is not git-ignored`, {
|
|
311
|
+
path: cachePath, configDir,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
cachePaths.push(cachePath);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
let guard = DEFAULT_GUARD;
|
|
318
|
+
if (landing.guard !== undefined) {
|
|
319
|
+
if (typeof landing.guard !== 'boolean') {
|
|
320
|
+
throw landingError('config_invalid', 'landing.guard must be a boolean', { configDir });
|
|
321
|
+
}
|
|
322
|
+
guard = landing.guard;
|
|
323
|
+
}
|
|
324
|
+
const triage = normalizeTriage(landing.triage, configDir);
|
|
325
|
+
const batch = normalizeBatch(landing.batch, configDir);
|
|
326
|
+
const publish = normalizePublish(landing.publish, configDir);
|
|
327
|
+
let target;
|
|
328
|
+
if (landing.target !== undefined) {
|
|
329
|
+
if (!isNonEmptyString(landing.target)) {
|
|
330
|
+
throw landingError('config_invalid', 'landing.target must be a non-empty branch name', { configDir });
|
|
331
|
+
}
|
|
332
|
+
target = landing.target;
|
|
333
|
+
} else {
|
|
334
|
+
target = targetDefault();
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
target,
|
|
338
|
+
mode,
|
|
339
|
+
gates,
|
|
340
|
+
gatesSource,
|
|
341
|
+
regenerate,
|
|
342
|
+
refresh,
|
|
343
|
+
registries,
|
|
344
|
+
cachePaths,
|
|
345
|
+
guard,
|
|
346
|
+
triage,
|
|
347
|
+
batch,
|
|
348
|
+
publish,
|
|
349
|
+
configDir,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// §6.1: `landing.publish = { remote: str, branch: str, auto: bool, follow: bool, followIntervalMs:
|
|
354
|
+
// int > 0, maxRetrains: int ≥ 0 }`. Absent means "off" and the normalized form is then `null`, which
|
|
355
|
+
// is the one truth every caller (land sync, land doctor, land status, the runner's R-9 hook) reads —
|
|
356
|
+
// there is no second `publishEnabled` boolean to keep in sync. A bad shape is `config_invalid` with
|
|
357
|
+
// the offending `field`, like every other landing field, never a silent clamp.
|
|
358
|
+
//
|
|
359
|
+
// §13.4 R-R1/R-R4 (§13.7 WP-6) adds the resolver half: `resolve` ∈ {session, off}, `resolveAgent` ∈
|
|
360
|
+
// {claude, codex}, `resolveMaxMinutes` ∈ [10, 1440] and `resolveFastGate` — one `landing.gates`
|
|
361
|
+
// entry (`{name, run, timeoutSeconds}`) validated by the very same normalizer. All four have SOURCE
|
|
362
|
+
// defaults (this file), so the normalized form is ALWAYS complete and no caller has to re-derive one.
|
|
363
|
+
function normalizePublish(raw, configDir) {
|
|
364
|
+
if (raw === undefined || raw === null) return null;
|
|
365
|
+
if (!isPlainObject(raw)) {
|
|
366
|
+
throw landingError('config_invalid', 'landing.publish must be an object', { configDir, field: 'publish' });
|
|
367
|
+
}
|
|
368
|
+
for (const key of Object.keys(raw)) {
|
|
369
|
+
if (!PUBLISH_KEYS.includes(key)) {
|
|
370
|
+
throw landingError('config_unknown_key', `unknown landing.publish key ${JSON.stringify(key)}`, {
|
|
371
|
+
key, configDir, field: `publish.${key}`, allowed: [...PUBLISH_KEYS],
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const remote = raw.remote === undefined ? DEFAULT_PUBLISH_REMOTE : raw.remote;
|
|
376
|
+
if (!isNonEmptyString(remote)) {
|
|
377
|
+
throw landingError('config_invalid', 'landing.publish.remote must be a non-empty string', { configDir, field: 'publish.remote', remote });
|
|
378
|
+
}
|
|
379
|
+
const branch = raw.branch === undefined ? DEFAULT_PUBLISH_BRANCH : raw.branch;
|
|
380
|
+
if (!isNonEmptyString(branch)) {
|
|
381
|
+
throw landingError('config_invalid', 'landing.publish.branch must be a non-empty string', { configDir, field: 'publish.branch', branch });
|
|
382
|
+
}
|
|
383
|
+
const bool = (key, fallback) => {
|
|
384
|
+
const value = raw[key] === undefined ? fallback : raw[key];
|
|
385
|
+
if (typeof value !== 'boolean') {
|
|
386
|
+
throw landingError('config_invalid', `landing.publish.${key} must be a boolean`, { configDir, field: `publish.${key}`, value });
|
|
387
|
+
}
|
|
388
|
+
return value;
|
|
389
|
+
};
|
|
390
|
+
const followIntervalMs = raw.followIntervalMs === undefined ? DEFAULT_PUBLISH_FOLLOW_INTERVAL_MS : raw.followIntervalMs;
|
|
391
|
+
if (!Number.isInteger(followIntervalMs) || followIntervalMs <= 0) {
|
|
392
|
+
throw landingError('config_invalid', 'landing.publish.followIntervalMs must be an integer > 0', { configDir, field: 'publish.followIntervalMs', followIntervalMs });
|
|
393
|
+
}
|
|
394
|
+
const maxRetrains = raw.maxRetrains === undefined ? DEFAULT_PUBLISH_MAX_RETRAINS : raw.maxRetrains;
|
|
395
|
+
if (!Number.isInteger(maxRetrains) || maxRetrains < 0) {
|
|
396
|
+
throw landingError('config_invalid', 'landing.publish.maxRetrains must be an integer ≥ 0', { configDir, field: 'publish.maxRetrains', maxRetrains });
|
|
397
|
+
}
|
|
398
|
+
// WP-6 §13.4 R-R1/R-R2 (§13.7 WP-6): the resolver policy. `resolve` and `resolveAgent` are closed
|
|
399
|
+
// enums, `resolveMaxMinutes` is bounded on both sides, and `resolveFastGate` is a gate entry —
|
|
400
|
+
// every default lives in SOURCE (here), so a repository that never mentions them gets the §13
|
|
401
|
+
// behaviour with no `.ctm.json` edit at all.
|
|
402
|
+
const resolveMode = raw.resolve === undefined ? DEFAULT_PUBLISH_RESOLVE : raw.resolve;
|
|
403
|
+
if (!RESOLVE_MODES.includes(resolveMode)) {
|
|
404
|
+
throw landingError('config_invalid', `landing.publish.resolve must be one of ${RESOLVE_MODES.join(', ')}`, { configDir, field: 'publish.resolve', resolve: resolveMode });
|
|
405
|
+
}
|
|
406
|
+
const resolveAgent = raw.resolveAgent === undefined ? DEFAULT_PUBLISH_RESOLVE_AGENT : raw.resolveAgent;
|
|
407
|
+
if (!RESOLVE_AGENTS.includes(resolveAgent)) {
|
|
408
|
+
throw landingError('config_invalid', `landing.publish.resolveAgent must be one of ${RESOLVE_AGENTS.join(', ')}`, { configDir, field: 'publish.resolveAgent', resolveAgent });
|
|
409
|
+
}
|
|
410
|
+
const resolveMaxMinutes = raw.resolveMaxMinutes === undefined ? DEFAULT_PUBLISH_RESOLVE_MAX_MINUTES : raw.resolveMaxMinutes;
|
|
411
|
+
if (!Number.isInteger(resolveMaxMinutes) || resolveMaxMinutes < RESOLVE_MAX_MINUTES_MIN || resolveMaxMinutes > RESOLVE_MAX_MINUTES_MAX) {
|
|
412
|
+
throw landingError('config_invalid', `landing.publish.resolveMaxMinutes must be an integer between ${RESOLVE_MAX_MINUTES_MIN} and ${RESOLVE_MAX_MINUTES_MAX}`, { configDir, field: 'publish.resolveMaxMinutes', resolveMaxMinutes });
|
|
413
|
+
}
|
|
414
|
+
const resolveFastGate = raw.resolveFastGate === undefined
|
|
415
|
+
? { ...DEFAULT_PUBLISH_RESOLVE_FAST_GATE }
|
|
416
|
+
: normalizeGate(configDir, raw.resolveFastGate, null, 'landing.publish.resolveFastGate');
|
|
417
|
+
return {
|
|
418
|
+
remote,
|
|
419
|
+
branch,
|
|
420
|
+
auto: bool('auto', DEFAULT_PUBLISH_AUTO),
|
|
421
|
+
follow: bool('follow', DEFAULT_PUBLISH_FOLLOW),
|
|
422
|
+
followIntervalMs,
|
|
423
|
+
maxRetrains,
|
|
424
|
+
resolve: resolveMode,
|
|
425
|
+
resolveAgent,
|
|
426
|
+
resolveMaxMinutes,
|
|
427
|
+
resolveFastGate,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// §5 D-3 / §6 (WP-1): `landing.batch = { max: int ≥ 1 (8), waitSeconds: int ≥ 0 (0) }`. Absent means
|
|
432
|
+
// the defaults; the normalized form is ALWAYS an object, so the runner never has to ask whether
|
|
433
|
+
// batching is configured. A bad shape is `config_invalid` with the offending `field`, like every other
|
|
434
|
+
// landing field — never a silent clamp, because a window the operator did not ask for is worse than a
|
|
435
|
+
// refusal they can read.
|
|
436
|
+
function normalizeBatch(raw, configDir) {
|
|
437
|
+
if (raw === undefined) return { max: DEFAULT_BATCH_MAX, waitSeconds: DEFAULT_BATCH_WAIT_SECONDS };
|
|
438
|
+
if (!isPlainObject(raw)) {
|
|
439
|
+
throw landingError('config_invalid', 'landing.batch must be an object', { configDir, field: 'batch' });
|
|
440
|
+
}
|
|
441
|
+
for (const key of Object.keys(raw)) {
|
|
442
|
+
if (!BATCH_KEYS.includes(key)) {
|
|
443
|
+
throw landingError('config_unknown_key', `unknown landing.batch key ${JSON.stringify(key)}`, {
|
|
444
|
+
key, configDir, field: `batch.${key}`, allowed: [...BATCH_KEYS],
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
const max = raw.max === undefined ? DEFAULT_BATCH_MAX : raw.max;
|
|
449
|
+
if (!Number.isInteger(max) || max < 1) {
|
|
450
|
+
throw landingError('config_invalid', 'landing.batch.max must be an integer ≥ 1', { configDir, field: 'batch.max', max });
|
|
451
|
+
}
|
|
452
|
+
const waitSeconds = raw.waitSeconds === undefined ? DEFAULT_BATCH_WAIT_SECONDS : raw.waitSeconds;
|
|
453
|
+
if (!Number.isInteger(waitSeconds) || waitSeconds < 0) {
|
|
454
|
+
throw landingError('config_invalid', 'landing.batch.waitSeconds must be an integer ≥ 0', { configDir, field: 'batch.waitSeconds', waitSeconds });
|
|
455
|
+
}
|
|
456
|
+
return { max, waitSeconds };
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// §5 D-7 / §9 S-4 (WP-2): the base-rerun budget. Absent means the default; `false` is the documented
|
|
460
|
+
// way to turn the pass off entirely (`maxFiles: 0`, which the runner reads as "never rerun"), so a
|
|
461
|
+
// repository can opt out without knowing the default. The normalized form is ALWAYS an object, so
|
|
462
|
+
// the runner never has to ask whether triage is configured.
|
|
463
|
+
function normalizeTriage(raw, configDir) {
|
|
464
|
+
if (raw === undefined) return { maxFiles: DEFAULT_TRIAGE_MAX_FILES };
|
|
465
|
+
if (raw === false) return { maxFiles: 0 };
|
|
466
|
+
if (!isPlainObject(raw)) {
|
|
467
|
+
throw landingError('config_invalid', 'landing.triage must be an object or false', { configDir });
|
|
468
|
+
}
|
|
469
|
+
for (const key of Object.keys(raw)) {
|
|
470
|
+
if (!TRIAGE_KEYS.includes(key)) {
|
|
471
|
+
throw landingError('config_unknown_key', `unknown landing.triage key ${JSON.stringify(key)}`, {
|
|
472
|
+
key, configDir, allowed: [...TRIAGE_KEYS],
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
const maxFiles = raw.maxFiles === undefined ? DEFAULT_TRIAGE_MAX_FILES : raw.maxFiles;
|
|
477
|
+
if (!Number.isInteger(maxFiles) || maxFiles < 0) {
|
|
478
|
+
throw landingError('config_invalid', 'landing.triage.maxFiles must be an integer ≥ 0', { configDir, maxFiles });
|
|
479
|
+
}
|
|
480
|
+
return { maxFiles };
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// `landing.regenerate` and `landing.refresh` share one shape — an array of { paths, run } entries in
|
|
484
|
+
// which every glob must match at least one tracked path. `label` names the key in the error, so a
|
|
485
|
+
// refusal says exactly which block is wrong.
|
|
486
|
+
function normalizePathEntries(raw, label, { configDir, matchesTracked }) {
|
|
487
|
+
const entries = [];
|
|
488
|
+
if (raw === undefined) return entries;
|
|
489
|
+
if (!Array.isArray(raw)) {
|
|
490
|
+
throw landingError('config_invalid', `landing.${label} must be an array`, { configDir });
|
|
491
|
+
}
|
|
492
|
+
raw.forEach((entry, index) => {
|
|
493
|
+
if (!isPlainObject(entry) || !Array.isArray(entry.paths) || !entry.paths.length || !entry.paths.every(isNonEmptyString)) {
|
|
494
|
+
throw landingError('config_invalid', `landing.${label}[${index}].paths must be a non-empty array of strings`, { index, configDir });
|
|
495
|
+
}
|
|
496
|
+
if (!isNonEmptyString(entry.run)) {
|
|
497
|
+
throw landingError('config_invalid', `landing.${label}[${index}].run must be a non-empty string`, { index, configDir });
|
|
498
|
+
}
|
|
499
|
+
for (const pattern of entry.paths) {
|
|
500
|
+
if (!matchesTracked(pattern)) {
|
|
501
|
+
throw landingError(`config_${label}_unmatched`, `landing.${label}[${index}].paths entry ${JSON.stringify(pattern)} matches no tracked file`, {
|
|
502
|
+
path: pattern, index, configDir,
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
entries.push({ paths: entry.paths.slice(), run: entry.run });
|
|
507
|
+
});
|
|
508
|
+
return entries;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
module.exports = {
|
|
512
|
+
ALLOWED_KEYS,
|
|
513
|
+
DEFAULT_GATE_TIMEOUT_SECONDS,
|
|
514
|
+
DEFAULT_GUARD,
|
|
515
|
+
DEFAULT_TRIAGE_MAX_FILES,
|
|
516
|
+
DEFAULT_BATCH_MAX,
|
|
517
|
+
DEFAULT_BATCH_WAIT_SECONDS,
|
|
518
|
+
PUBLISH_KEYS,
|
|
519
|
+
DEFAULT_PUBLISH_REMOTE,
|
|
520
|
+
DEFAULT_PUBLISH_BRANCH,
|
|
521
|
+
DEFAULT_PUBLISH_AUTO,
|
|
522
|
+
DEFAULT_PUBLISH_FOLLOW,
|
|
523
|
+
DEFAULT_PUBLISH_FOLLOW_INTERVAL_MS,
|
|
524
|
+
DEFAULT_PUBLISH_MAX_RETRAINS,
|
|
525
|
+
DEFAULT_PUBLISH_RESOLVE,
|
|
526
|
+
DEFAULT_PUBLISH_RESOLVE_AGENT,
|
|
527
|
+
DEFAULT_PUBLISH_RESOLVE_MAX_MINUTES,
|
|
528
|
+
DEFAULT_PUBLISH_RESOLVE_FAST_GATE,
|
|
529
|
+
RESOLVE_MODES,
|
|
530
|
+
RESOLVE_AGENTS,
|
|
531
|
+
loadLandingConfig,
|
|
532
|
+
loadTargetLandingConfig,
|
|
533
|
+
gatesHash,
|
|
534
|
+
autodetectGates,
|
|
535
|
+
resolveMainBranch,
|
|
536
|
+
};
|