@the-open-engine/zeroshot 6.38.0 → 6.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/event-copy.js +8 -7
- package/cli/event-copy.ts +12 -0
- package/cli/index.js +7 -31
- package/cli/json-export.js +61 -64
- package/cli/json-export.ts +112 -0
- package/cli/message-formatter-utils.js +68 -56
- package/cli/message-formatter-utils.ts +121 -0
- package/cli/message-formatters-normal.js +124 -259
- package/cli/message-formatters-normal.ts +250 -0
- package/cli/message-formatters-watch.js +81 -84
- package/cli/message-formatters-watch.ts +189 -0
- package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.js +3 -1
- package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
- package/lib/cluster/generated/protocol-schema.cjs +1 -1
- package/lib/cluster/generated/protocol-schema.mjs +1 -1
- package/lib/cluster/generated/protocol.d.cts +8 -0
- package/lib/cluster/generated/protocol.d.mts +8 -0
- package/lib/cluster/generated/protocol.d.ts +8 -0
- package/lib/clusters-registry.d.ts +23 -0
- package/lib/clusters-registry.js +17 -29
- package/lib/completion.d.ts +12 -0
- package/lib/completion.js +84 -94
- package/lib/compose-utils.d.ts +32 -0
- package/lib/compose-utils.js +57 -72
- package/lib/detached-startup.d.ts +83 -0
- package/lib/detached-startup.js +231 -302
- package/lib/docker-config.d.ts +43 -0
- package/lib/docker-config.js +150 -325
- package/lib/docker-env-auth.d.ts +17 -0
- package/lib/docker-env-auth.js +75 -0
- package/lib/git-remote-utils.d.ts +48 -0
- package/lib/git-remote-utils.js +147 -213
- package/lib/id-detector.d.ts +15 -0
- package/lib/id-detector.js +37 -41
- package/lib/path-check.d.ts +30 -0
- package/lib/path-check.js +42 -45
- package/lib/process-liveness.d.ts +16 -0
- package/lib/process-liveness.js +19 -12
- package/lib/provider-credential-path.d.ts +16 -0
- package/lib/provider-credential-path.js +31 -29
- package/lib/provider-defaults.d.ts +30 -0
- package/lib/provider-defaults.js +47 -42
- package/lib/provider-detection.d.ts +11 -0
- package/lib/provider-detection.js +91 -54
- package/lib/provider-names.d.ts +38 -0
- package/lib/provider-names.js +56 -64
- package/lib/repo-settings.d.ts +28 -0
- package/lib/repo-settings.js +83 -59
- package/lib/run-mode.d.ts +21 -0
- package/lib/run-mode.js +21 -20
- package/lib/run-plan.d.ts +28 -0
- package/lib/run-plan.js +17 -16
- package/lib/settings/claude-auth.d.ts +35 -0
- package/lib/settings/claude-auth.js +30 -47
- package/lib/settings-defaults.d.ts +20 -0
- package/lib/settings-defaults.js +149 -0
- package/lib/settings-error.d.ts +7 -0
- package/lib/settings-error.js +8 -0
- package/lib/settings-issue-providers.d.ts +10 -0
- package/lib/settings-issue-providers.js +12 -0
- package/lib/settings-models.d.ts +22 -0
- package/lib/settings-models.js +93 -0
- package/lib/settings-storage.d.ts +23 -0
- package/lib/settings-storage.js +205 -0
- package/lib/settings-validation.d.ts +7 -0
- package/lib/settings-validation.js +182 -0
- package/lib/settings.d.ts +29 -0
- package/lib/settings.js +41 -736
- package/lib/setup-apply-types.d.ts +66 -0
- package/lib/setup-apply-types.js +2 -0
- package/lib/setup-apply.d.ts +39 -0
- package/lib/setup-apply.js +267 -264
- package/lib/setup-journal.d.ts +41 -0
- package/lib/setup-journal.js +119 -76
- package/lib/setup-plan-types.d.ts +102 -0
- package/lib/setup-plan-types.js +2 -0
- package/lib/setup-plan.d.ts +30 -0
- package/lib/setup-plan.js +300 -324
- package/lib/setup-undo.d.ts +44 -0
- package/lib/setup-undo.js +61 -74
- package/lib/start-cluster-config.d.ts +26 -0
- package/lib/start-cluster-config.js +56 -0
- package/lib/start-cluster-environment.d.ts +40 -0
- package/lib/start-cluster-environment.js +134 -0
- package/lib/start-cluster-run-options.d.ts +53 -0
- package/lib/start-cluster-run-options.js +147 -0
- package/lib/start-cluster.d.ts +64 -0
- package/lib/start-cluster.js +98 -454
- package/lib/stream-json-parser.d.ts +17 -0
- package/lib/stream-json-parser.js +51 -52
- package/npm-shrinkwrap.json +2 -2
- package/package.json +12 -6
- package/scripts/postinstall.js +27 -0
- package/scripts/rust-distribution.js +23 -14
- package/src/agent/agent-command-proofs-context.js +35 -45
- package/src/agent/agent-command-proofs-context.ts +87 -0
- package/src/agent/agent-config-settings.js +19 -0
- package/src/agent/agent-config-settings.ts +41 -0
- package/src/agent/agent-config.js +122 -231
- package/src/agent/agent-config.ts +285 -0
- package/src/agent/agent-context-builder.js +38 -273
- package/src/agent/agent-context-builder.ts +51 -0
- package/src/agent/agent-context-environment-sections.js +105 -0
- package/src/agent/agent-context-environment-sections.ts +134 -0
- package/src/agent/agent-context-packs.js +165 -0
- package/src/agent/agent-context-packs.ts +296 -0
- package/src/agent/agent-context-prompt-sections.js +100 -0
- package/src/agent/agent-context-prompt-sections.ts +148 -0
- package/src/agent/agent-context-sections.js +25 -334
- package/src/agent/agent-context-sections.ts +36 -0
- package/src/agent/agent-context-sources.js +96 -149
- package/src/agent/agent-context-sources.ts +253 -0
- package/src/agent/agent-context-types.js +2 -0
- package/src/agent/agent-context-types.ts +132 -0
- package/src/agent/agent-context-validation-sections.js +73 -0
- package/src/agent/agent-context-validation-sections.ts +129 -0
- package/src/agent/agent-input-injector.js +99 -118
- package/src/agent/agent-input-injector.ts +195 -0
- package/src/agent/agent-liveness-poll.js +74 -78
- package/src/agent/agent-liveness-poll.ts +163 -0
- package/src/agent/agent-quality-gate-schema.js +77 -86
- package/src/agent/agent-quality-gate-schema.ts +135 -0
- package/src/agent/agent-quality-gates-context.js +44 -50
- package/src/agent/agent-quality-gates-context.ts +91 -0
- package/src/agent/agent-stuck-detector.js +171 -239
- package/src/agent/agent-stuck-detector.ts +288 -0
- package/src/agent/agent-trigger-evaluator.js +29 -46
- package/src/agent/agent-trigger-evaluator.ts +98 -0
- package/src/agent/context-metrics.js +110 -141
- package/src/agent/context-metrics.ts +261 -0
- package/src/agent/context-pack-builder.js +72 -358
- package/src/agent/context-pack-builder.ts +105 -0
- package/src/agent/context-pack-core.js +70 -0
- package/src/agent/context-pack-core.ts +96 -0
- package/src/agent/context-pack-selection.js +119 -0
- package/src/agent/context-pack-selection.ts +187 -0
- package/src/agent/context-pack-truncation.js +139 -0
- package/src/agent/context-pack-truncation.ts +208 -0
- package/src/agent/context-pack-types.js +2 -0
- package/src/agent/context-pack-types.ts +98 -0
- package/src/agent/context-replay-policy.js +30 -39
- package/src/agent/context-replay-policy.ts +71 -0
- package/src/agent/critical-agent-policy.js +6 -10
- package/src/agent/critical-agent-policy.ts +20 -0
- package/src/agent/guidance-queue.js +74 -87
- package/src/agent/guidance-queue.ts +166 -0
- package/src/agent/output-extraction-error-detail.js +45 -0
- package/src/agent/output-extraction-error-detail.ts +49 -0
- package/src/agent/output-extraction-failures.js +125 -0
- package/src/agent/output-extraction-failures.ts +149 -0
- package/src/agent/output-extraction-json.js +234 -0
- package/src/agent/output-extraction-json.ts +235 -0
- package/src/agent/output-extraction-pi.js +124 -0
- package/src/agent/output-extraction-pi.ts +137 -0
- package/src/agent/output-extraction-types.js +2 -0
- package/src/agent/output-extraction-types.ts +49 -0
- package/src/agent/output-extraction.js +17 -617
- package/src/agent/output-extraction.ts +30 -0
- package/src/agent/output-reformatter-errors.js +83 -0
- package/src/agent/output-reformatter-errors.ts +106 -0
- package/src/agent/output-reformatter-types.js +2 -0
- package/src/agent/output-reformatter-types.ts +86 -0
- package/src/agent/output-reformatter.js +140 -185
- package/src/agent/output-reformatter.ts +238 -0
- package/src/agent/pi-terminal-lifecycle-types.js +2 -0
- package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
- package/src/agent/pi-terminal-lifecycle.js +186 -206
- package/src/agent/pi-terminal-lifecycle.ts +297 -0
- package/src/agent/provider-control-plane.js +22 -21
- package/src/agent/provider-control-plane.ts +52 -0
- package/src/agent/provider-terminal-failure-types.js +2 -0
- package/src/agent/provider-terminal-failure-types.ts +60 -0
- package/src/agent/provider-terminal-failure.js +194 -191
- package/src/agent/provider-terminal-failure.ts +262 -0
- package/src/agent/rate-limit-backoff.js +31 -74
- package/src/agent/rate-limit-backoff.ts +71 -0
- package/src/agent/schema-utils.js +85 -125
- package/src/agent/schema-utils.ts +148 -0
- package/src/agent/structured-output-error.js +34 -33
- package/src/agent/structured-output-error.ts +105 -0
- package/src/agent/validation-platform.js +27 -27
- package/src/agent/validation-platform.ts +49 -0
- package/src/agent-cli-provider/adapters/codex.ts +3 -1
- package/src/attach/attach-client.js +232 -405
- package/src/attach/attach-client.ts +300 -0
- package/src/attach/attach-server-cleanup.js +43 -0
- package/src/attach/attach-server-cleanup.ts +39 -0
- package/src/attach/attach-server-clients.js +117 -0
- package/src/attach/attach-server-clients.ts +122 -0
- package/src/attach/attach-server-events.js +38 -0
- package/src/attach/attach-server-events.ts +36 -0
- package/src/attach/attach-server-pty.js +45 -0
- package/src/attach/attach-server-pty.ts +64 -0
- package/src/attach/attach-server-runtime.js +73 -0
- package/src/attach/attach-server-runtime.ts +62 -0
- package/src/attach/attach-server-socket.js +28 -0
- package/src/attach/attach-server-socket.ts +23 -0
- package/src/attach/attach-server-types.js +2 -0
- package/src/attach/attach-server-types.ts +82 -0
- package/src/attach/attach-server.js +106 -523
- package/src/attach/attach-server.ts +158 -0
- package/src/attach/index.js +18 -35
- package/src/attach/index.ts +18 -0
- package/src/attach/protocol.js +95 -184
- package/src/attach/protocol.ts +181 -0
- package/src/attach/ring-buffer.js +76 -102
- package/src/attach/ring-buffer.ts +109 -0
- package/src/attach/send-input.js +64 -75
- package/src/attach/send-input.ts +94 -0
- package/src/attach/socket-discovery.js +164 -218
- package/src/attach/socket-discovery.ts +230 -0
- package/src/attach/socket-paths.js +42 -61
- package/src/attach/socket-paths.ts +81 -0
- package/src/claude-credentials.js +51 -54
- package/src/claude-credentials.ts +89 -0
- package/src/cluster/generated/protocol-schema.ts +1 -1
- package/src/cluster/generated/protocol.ts +2 -1
- package/src/command-proofs.js +110 -141
- package/src/command-proofs.ts +216 -0
- package/src/config-router.js +81 -73
- package/src/config-router.ts +131 -0
- package/src/copy-worker.js +53 -29
- package/src/copy-worker.ts +75 -0
- package/src/darwin-keychain-boundary.js +80 -111
- package/src/darwin-keychain-boundary.ts +148 -0
- package/src/guidance-topics.js +4 -5
- package/src/guidance-topics.ts +10 -0
- package/src/input-helpers.js +33 -54
- package/src/input-helpers.ts +58 -0
- package/src/ledger-sequence.js +45 -48
- package/src/ledger-sequence.ts +63 -0
- package/src/legacy-lib/clusters-registry.ts +40 -0
- package/src/legacy-lib/completion.ts +148 -0
- package/src/legacy-lib/compose-utils.ts +102 -0
- package/src/legacy-lib/detached-startup.ts +449 -0
- package/src/legacy-lib/docker-config.ts +282 -0
- package/src/legacy-lib/docker-env-auth.ts +116 -0
- package/src/legacy-lib/git-remote-utils.ts +244 -0
- package/src/legacy-lib/id-detector.ts +57 -0
- package/src/legacy-lib/js-yaml.d.ts +3 -0
- package/src/legacy-lib/omelette.d.ts +15 -0
- package/src/legacy-lib/path-check.ts +89 -0
- package/src/legacy-lib/process-liveness.ts +36 -0
- package/src/legacy-lib/provider-credential-path.ts +57 -0
- package/src/legacy-lib/provider-defaults.ts +114 -0
- package/src/legacy-lib/provider-detection.ts +67 -0
- package/src/legacy-lib/provider-names.ts +126 -0
- package/src/legacy-lib/repo-settings.ts +88 -0
- package/src/legacy-lib/run-mode.ts +58 -0
- package/src/legacy-lib/run-plan.ts +49 -0
- package/src/legacy-lib/settings/claude-auth.ts +80 -0
- package/src/legacy-lib/settings-defaults.ts +212 -0
- package/src/legacy-lib/settings-error.ts +8 -0
- package/src/legacy-lib/settings-issue-providers.ts +18 -0
- package/src/legacy-lib/settings-models.ts +124 -0
- package/src/legacy-lib/settings-storage.ts +277 -0
- package/src/legacy-lib/settings-validation.ts +220 -0
- package/src/legacy-lib/settings.ts +87 -0
- package/src/legacy-lib/setup-apply-types.ts +70 -0
- package/src/legacy-lib/setup-apply.ts +456 -0
- package/src/legacy-lib/setup-journal.ts +185 -0
- package/src/legacy-lib/setup-plan-types.ts +96 -0
- package/src/legacy-lib/setup-plan.ts +500 -0
- package/src/legacy-lib/setup-undo.ts +142 -0
- package/src/legacy-lib/start-cluster-config.ts +124 -0
- package/src/legacy-lib/start-cluster-environment.ts +165 -0
- package/src/legacy-lib/start-cluster-run-options.ts +279 -0
- package/src/legacy-lib/start-cluster.ts +237 -0
- package/src/legacy-lib/stream-json-parser.ts +88 -0
- package/src/message-buffer.js +55 -71
- package/src/message-buffer.ts +107 -0
- package/src/message-bus-bridge.js +92 -133
- package/src/message-bus-bridge.ts +149 -0
- package/src/name-generator-shared.js +220 -0
- package/src/name-generator-shared.ts +231 -0
- package/src/name-generator.js +8 -217
- package/src/name-generator.ts +27 -0
- package/src/omp-blob-root.js +83 -64
- package/src/omp-blob-root.ts +116 -0
- package/src/omp-config-overlay.js +65 -38
- package/src/omp-config-overlay.ts +110 -0
- package/src/omp-execution-fingerprint.js +38 -43
- package/src/omp-execution-fingerprint.ts +92 -0
- package/src/omp-session-limits.js +10 -15
- package/src/omp-session-limits.ts +53 -0
- package/src/omp-session-partition.js +2 -2
- package/src/omp-session-verifier.js +1 -1
- package/src/orchestrator.js +19 -4
- package/src/providers/anthropic/index.js +3 -1
- package/src/providers/anthropic/index.ts +13 -0
- package/src/providers/capabilities.js +19 -27
- package/src/providers/capabilities.ts +44 -0
- package/src/providers/google/index.js +3 -1
- package/src/providers/google/index.ts +13 -0
- package/src/providers/openai/index.js +3 -1
- package/src/providers/openai/index.ts +13 -0
- package/src/providers/opencode/index.js +3 -1
- package/src/providers/opencode/index.ts +13 -0
- package/src/quality-gates.js +67 -127
- package/src/quality-gates.ts +149 -0
- package/src/repo-settings-access.js +40 -0
- package/src/repo-settings-access.ts +64 -0
- package/src/schemas/sub-cluster.js +127 -183
- package/src/schemas/sub-cluster.ts +238 -0
- package/src/state-snapshot-normalization.js +224 -0
- package/src/state-snapshot-normalization.ts +222 -0
- package/src/state-snapshot.js +192 -359
- package/src/state-snapshot.ts +291 -0
- package/src/state-snapshotter.js +118 -130
- package/src/state-snapshotter.ts +167 -0
- package/src/sub-cluster-wrapper.js +4 -13
- package/src/task-run-model-args.js +87 -124
- package/src/task-run-model-args.ts +204 -0
- package/src/task-runner.js +5 -25
- package/src/task-runner.ts +28 -0
- package/src/task-startup-error.js +73 -58
- package/src/task-startup-error.ts +126 -0
- package/src/template-validation/consensus-gate-contracts.js +2 -0
- package/src/template-validation/consensus-gate-contracts.ts +70 -0
- package/src/template-validation/consensus-gate-scenarios.js +76 -0
- package/src/template-validation/consensus-gate-scenarios.ts +130 -0
- package/src/template-validation/consensus-gate-stage.js +34 -0
- package/src/template-validation/consensus-gate-stage.ts +56 -0
- package/src/template-validation/random-topology-contracts.js +2 -0
- package/src/template-validation/random-topology-contracts.ts +54 -0
- package/src/template-validation/random-topology-dispatch.js +25 -0
- package/src/template-validation/random-topology-dispatch.ts +33 -0
- package/src/template-validation/random-topology-message-loop.js +53 -0
- package/src/template-validation/random-topology-message-loop.ts +73 -0
- package/src/template-validation/random-topology-operations.js +79 -0
- package/src/template-validation/random-topology-operations.ts +101 -0
- package/src/template-validation/random-topology-runtime.js +25 -0
- package/src/template-validation/random-topology-runtime.ts +43 -0
- package/src/template-validation/random-topology-scenario.js +52 -0
- package/src/template-validation/random-topology-scenario.ts +57 -0
- package/src/template-validation/random-topology-schema.js +159 -0
- package/src/template-validation/random-topology-schema.ts +190 -0
- package/src/template-validation/random-topology-state.js +28 -0
- package/src/template-validation/random-topology-state.ts +30 -0
- package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
- package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
- package/src/template-validation/random-topology-trigger.js +75 -0
- package/src/template-validation/random-topology-trigger.ts +88 -0
- package/src/template-validation/report-formatter.js +40 -46
- package/src/template-validation/report-formatter.ts +101 -0
- package/src/template-validation/simulate-consensus-gates.js +111 -302
- package/src/template-validation/simulate-consensus-gates.ts +196 -0
- package/src/template-validation/simulate-random-topology.js +26 -519
- package/src/template-validation/simulate-random-topology.ts +57 -0
- package/src/template-validation/simulate-two-stage-validation.js +41 -265
- package/src/template-validation/simulate-two-stage-validation.ts +55 -0
- package/src/template-validation/simulation-agent-runtime.js +25 -0
- package/src/template-validation/simulation-agent-runtime.ts +40 -0
- package/src/template-validation/simulation-agent.js +29 -0
- package/src/template-validation/simulation-agent.ts +73 -0
- package/src/template-validation/simulation-runtime.js +34 -0
- package/src/template-validation/simulation-runtime.ts +72 -0
- package/src/template-validation/two-stage-contracts.js +2 -0
- package/src/template-validation/two-stage-contracts.ts +41 -0
- package/src/template-validation/two-stage-inputs.js +21 -0
- package/src/template-validation/two-stage-inputs.ts +29 -0
- package/src/template-validation/two-stage-results.js +30 -0
- package/src/template-validation/two-stage-results.ts +40 -0
- package/src/template-validation/two-stage-scenario.js +86 -0
- package/src/template-validation/two-stage-scenario.ts +120 -0
- package/src/worktree-claude-config.js +182 -220
- package/src/worktree-claude-config.ts +272 -0
- package/src/worktree-tooling-env.js +103 -125
- package/src/worktree-tooling-env.ts +142 -0
- package/task-lib/completion.js +2 -3
- package/task-lib/completion.ts +9 -0
- package/task-lib/config.js +1 -4
- package/task-lib/config.ts +11 -0
- package/task-lib/name-generator.js +4 -226
- package/task-lib/name-generator.ts +11 -0
- package/task-lib/omp-session-cleanup.js +1 -1
- package/task-lib/omp-storage-root.js +8 -12
- package/task-lib/omp-storage-root.ts +62 -0
- package/task-lib/process-termination.js +143 -166
- package/task-lib/process-termination.ts +268 -0
package/lib/setup-apply.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* `zeroshot setup apply` — writes decisions from #A's plan/decision contract
|
|
3
4
|
* (lib/setup-plan.js) to global settings, repo-local settings, and the undo
|
|
@@ -10,311 +11,313 @@
|
|
|
10
11
|
* — a settings key nobody reads is dead config, the exact drift the
|
|
11
12
|
* canonical-path rule (issue #605) forbids.
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
+
// These CommonJS paths intentionally resolve beside the emitted module in lib/.
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
14
16
|
const { resolveDecisionPath, domainFor, isConsumedPath, CONSUMED_PATHS } = require('./setup-plan');
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
15
18
|
const { validateMountConfig, validateEnvPassthrough } = require('./docker-config');
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
16
20
|
const { VALID_PROVIDERS } = require('./provider-names');
|
|
17
21
|
const VALID_LEVELS = Object.freeze(['level1', 'level2', 'level3']);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
getNestedValue,
|
|
23
|
-
setNestedValue,
|
|
24
|
-
deepEqual,
|
|
25
|
-
} = require('./setup-journal');
|
|
26
|
-
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
23
|
+
const setupJournal = require('./setup-journal');
|
|
24
|
+
const { loadJournal, saveJournal, upsertJournalEntry } = setupJournal;
|
|
25
|
+
const { getNestedValue, setNestedValue, deepEqual } = setupJournal;
|
|
27
26
|
const SECRET_PATTERN = /token|secret|password|api[_-]?key|credential/i;
|
|
28
|
-
|
|
27
|
+
function includesValue(values, value) {
|
|
28
|
+
return values.includes(value);
|
|
29
|
+
}
|
|
29
30
|
function assertSecretSafePath(targetPath) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
if (SECRET_PATTERN.test(targetPath)) {
|
|
32
|
+
throw new Error(`Refusing to write secret-shaped settings path: ${targetPath}`);
|
|
33
|
+
}
|
|
33
34
|
}
|
|
34
|
-
|
|
35
35
|
function domainError(decisionId, value) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const expected = domainFor(decisionId);
|
|
37
|
+
const received = JSON.stringify(value);
|
|
38
|
+
return new Error(`Invalid value for decision "${decisionId}": expected ${expected}, got ${received}`);
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// settings path, validating its decision domain before any write occurs.
|
|
43
|
-
function convertDecisionValue({ decisionId, value, globalSettings, deps }) {
|
|
44
|
-
switch (decisionId) {
|
|
45
|
-
case 'defaultProvider':
|
|
46
|
-
if (typeof value !== 'string' || !deps.VALID_PROVIDERS.includes(value)) {
|
|
47
|
-
throw domainError(decisionId, value);
|
|
48
|
-
}
|
|
49
|
-
return value;
|
|
50
|
-
|
|
51
|
-
case 'defaultIsolation':
|
|
52
|
-
if (!['worktree', 'docker', 'none'].includes(value)) throw domainError(decisionId, value);
|
|
53
|
-
return value;
|
|
54
|
-
|
|
55
|
-
case 'allowLocalNoIsolation':
|
|
56
|
-
if (typeof value !== 'boolean') throw domainError(decisionId, value);
|
|
57
|
-
return value;
|
|
58
|
-
|
|
59
|
-
case 'defaultDelivery':
|
|
60
|
-
if (!['none', 'pr', 'ship'].includes(value)) throw domainError(decisionId, value);
|
|
61
|
-
return value;
|
|
62
|
-
|
|
63
|
-
case 'defaultIssueSource':
|
|
64
|
-
if (typeof value !== 'string' || !deps.listIssueProviders().includes(value)) {
|
|
65
|
-
throw domainError(decisionId, value);
|
|
66
|
-
}
|
|
67
|
-
return value;
|
|
68
|
-
|
|
69
|
-
case 'prBase':
|
|
70
|
-
if (typeof value !== 'string' || value.trim() === '') throw domainError(decisionId, value);
|
|
71
|
-
return value;
|
|
72
|
-
|
|
73
|
-
case 'dockerMounts': {
|
|
74
|
-
const err = validateMountConfig(value);
|
|
75
|
-
if (err) throw new Error(`Invalid value for decision "${decisionId}": ${err}`);
|
|
76
|
-
return value;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
case 'dockerEnvPassthrough': {
|
|
80
|
-
const err = validateEnvPassthrough(value);
|
|
81
|
-
if (err) throw new Error(`Invalid value for decision "${decisionId}": ${err}`);
|
|
82
|
-
return value;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
case 'updatePolicy':
|
|
86
|
-
if (!['off', 'notify', 'auto'].includes(value)) throw domainError(decisionId, value);
|
|
87
|
-
return value;
|
|
88
|
-
|
|
89
|
-
default: {
|
|
90
|
-
if (!decisionId.startsWith('providerLevel.')) {
|
|
40
|
+
function convertProviderLevelDecision({ decisionId, value, globalSettings, deps, }) {
|
|
41
|
+
if (!decisionId.startsWith('providerLevel.')) {
|
|
91
42
|
throw new Error(`Unknown decision ID: ${decisionId}`);
|
|
92
|
-
|
|
93
|
-
|
|
43
|
+
}
|
|
44
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
94
45
|
throw domainError(decisionId, value);
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
46
|
+
}
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
48
|
+
const decisionValue = value;
|
|
49
|
+
// Preserve Array.prototype.sort's default UTF-16 ordering.
|
|
50
|
+
// eslint-disable-next-line sonarjs/no-alphabetical-sort
|
|
51
|
+
const keys = Object.keys(decisionValue).sort();
|
|
52
|
+
const expectedKeys = ['defaultLevel', 'maxLevel', 'minLevel'];
|
|
53
|
+
if (keys.length !== expectedKeys.length ||
|
|
100
54
|
keys.some((key, index) => key !== expectedKeys[index]) ||
|
|
101
|
-
expectedKeys.some((key) => !VALID_LEVELS
|
|
102
|
-
|
|
55
|
+
expectedKeys.some((key) => !includesValue(VALID_LEVELS, decisionValue[key]))) {
|
|
56
|
+
throw domainError(decisionId, value);
|
|
57
|
+
}
|
|
58
|
+
const providerName = decisionId.slice('providerLevel.'.length);
|
|
59
|
+
if (!deps.VALID_PROVIDERS.includes(providerName))
|
|
103
60
|
throw domainError(decisionId, value);
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const rank = (level) => VALID_LEVELS.indexOf(level);
|
|
108
|
-
if (
|
|
109
|
-
rank(value.minLevel) > rank(value.defaultLevel) ||
|
|
110
|
-
rank(value.defaultLevel) > rank(value.maxLevel)
|
|
111
|
-
) {
|
|
61
|
+
const rank = (level) => VALID_LEVELS.findIndex((item) => item === level);
|
|
62
|
+
if (rank(decisionValue.minLevel) > rank(decisionValue.defaultLevel) ||
|
|
63
|
+
rank(decisionValue.defaultLevel) > rank(decisionValue.maxLevel)) {
|
|
112
64
|
throw domainError(decisionId, value);
|
|
113
|
-
}
|
|
114
|
-
const existing = getNestedValue(globalSettings, `providerSettings.${providerName}`) || {};
|
|
115
|
-
return { ...existing, ...value };
|
|
116
65
|
}
|
|
117
|
-
|
|
66
|
+
const existingValue = getNestedValue(globalSettings, `providerSettings.${providerName}`) || {};
|
|
67
|
+
// Both operands have passed the same object-domain checks used by the legacy implementation.
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
69
|
+
const existing = existingValue;
|
|
70
|
+
return { ...existing, ...decisionValue };
|
|
71
|
+
}
|
|
72
|
+
// Resolve a submitted decision into the exact value stored at its canonical
|
|
73
|
+
// settings path, validating its decision domain before any write occurs.
|
|
74
|
+
function convertDecisionValue({ decisionId, value, globalSettings, deps, }) {
|
|
75
|
+
switch (decisionId) {
|
|
76
|
+
case 'defaultProvider':
|
|
77
|
+
if (typeof value !== 'string' || !deps.VALID_PROVIDERS.includes(value)) {
|
|
78
|
+
throw domainError(decisionId, value);
|
|
79
|
+
}
|
|
80
|
+
return value;
|
|
81
|
+
case 'defaultIsolation':
|
|
82
|
+
if (!includesValue(['worktree', 'docker', 'none'], value)) {
|
|
83
|
+
throw domainError(decisionId, value);
|
|
84
|
+
}
|
|
85
|
+
return value;
|
|
86
|
+
case 'allowLocalNoIsolation':
|
|
87
|
+
if (typeof value !== 'boolean')
|
|
88
|
+
throw domainError(decisionId, value);
|
|
89
|
+
return value;
|
|
90
|
+
case 'defaultDelivery':
|
|
91
|
+
if (!includesValue(['none', 'pr', 'ship'], value))
|
|
92
|
+
throw domainError(decisionId, value);
|
|
93
|
+
return value;
|
|
94
|
+
case 'defaultIssueSource':
|
|
95
|
+
if (typeof value !== 'string' || !deps.listIssueProviders().includes(value)) {
|
|
96
|
+
throw domainError(decisionId, value);
|
|
97
|
+
}
|
|
98
|
+
return value;
|
|
99
|
+
case 'prBase':
|
|
100
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
101
|
+
throw domainError(decisionId, value);
|
|
102
|
+
return value;
|
|
103
|
+
case 'dockerMounts': {
|
|
104
|
+
const err = validateMountConfig(value);
|
|
105
|
+
if (err)
|
|
106
|
+
throw new Error(`Invalid value for decision "${decisionId}": ${err}`);
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
109
|
+
case 'dockerEnvPassthrough': {
|
|
110
|
+
const err = validateEnvPassthrough(value);
|
|
111
|
+
if (err)
|
|
112
|
+
throw new Error(`Invalid value for decision "${decisionId}": ${err}`);
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
case 'updatePolicy':
|
|
116
|
+
if (!includesValue(['off', 'notify', 'auto'], value))
|
|
117
|
+
throw domainError(decisionId, value);
|
|
118
|
+
return value;
|
|
119
|
+
default:
|
|
120
|
+
return convertProviderLevelDecision({ decisionId, value, globalSettings, deps });
|
|
121
|
+
}
|
|
118
122
|
}
|
|
119
|
-
|
|
120
123
|
function defaultApplyDeps() {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
125
|
+
const fs = require('fs');
|
|
126
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
127
|
+
const { loadSettings, mutateSettings } = require('./settings');
|
|
128
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
129
|
+
const { readRepoSettings, writeRepoSettings } = require('./repo-settings');
|
|
130
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
131
|
+
const { checkGhAuth } = require('../src/preflight');
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
133
|
+
const { listProviders: listIssueProviders } = require('../src/issue-providers');
|
|
134
|
+
return {
|
|
135
|
+
readFile: (filePath) => fs.readFileSync(filePath, 'utf8'),
|
|
136
|
+
loadSettings,
|
|
137
|
+
mutateSettings,
|
|
138
|
+
readRepoSettings,
|
|
139
|
+
writeRepoSettings,
|
|
140
|
+
checkGhAuth,
|
|
141
|
+
listIssueProviders,
|
|
142
|
+
VALID_PROVIDERS,
|
|
143
|
+
now: () => new Date().toISOString(),
|
|
144
|
+
};
|
|
138
145
|
}
|
|
139
|
-
|
|
140
146
|
// Phase 1: resolve + validate EVERY input decision before any write happens
|
|
141
147
|
// (fail-closed — a single bad decisionId or out-of-domain value rejects the
|
|
142
148
|
// whole request, never a partial apply).
|
|
143
149
|
function resolveAndValidateDecisions(input, globalSettings, deps) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
150
|
+
const resolved = [];
|
|
151
|
+
for (const [decisionId, value] of Object.entries(input)) {
|
|
152
|
+
const target = resolveDecisionPath(decisionId);
|
|
153
|
+
if (!target) {
|
|
154
|
+
throw new Error(`Unknown decision ID: ${decisionId}`);
|
|
155
|
+
}
|
|
156
|
+
assertSecretSafePath(target.path);
|
|
157
|
+
const writeValue = convertDecisionValue({ decisionId, value, globalSettings, deps });
|
|
158
|
+
resolved.push({ decisionId, target, inputValue: value, writeValue });
|
|
149
159
|
}
|
|
150
|
-
|
|
151
|
-
const writeValue = convertDecisionValue({ decisionId, value, globalSettings, deps });
|
|
152
|
-
resolved.push({ decisionId, target, inputValue: value, writeValue });
|
|
153
|
-
}
|
|
154
|
-
return resolved;
|
|
160
|
+
return resolved;
|
|
155
161
|
}
|
|
156
|
-
|
|
157
162
|
// Decides the outcome for a single resolved decision: a skip (with reason)
|
|
158
163
|
// or the write to perform. Returns the write descriptor rather than mutating
|
|
159
164
|
// anything, so the caller controls when settings objects/journal are touched.
|
|
160
|
-
function resolveDecisionOutcome(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
priorValue: currentValue,
|
|
186
|
-
},
|
|
187
|
-
};
|
|
165
|
+
function resolveDecisionOutcome(decision, context) {
|
|
166
|
+
const { decisionId, target, inputValue, writeValue } = decision;
|
|
167
|
+
const { globalSettings, repoSettings, allowRiskyDefaults } = context;
|
|
168
|
+
const settingsObj = target.scope === 'repo' ? repoSettings : globalSettings;
|
|
169
|
+
const currentValue = getNestedValue(settingsObj, target.path) ?? null;
|
|
170
|
+
const base = { decisionId, from: currentValue, to: writeValue };
|
|
171
|
+
if (decisionId === 'defaultDelivery' && inputValue === 'ship' && !allowRiskyDefaults) {
|
|
172
|
+
return { result: { ...base, applied: false, skippedReason: 'requires-explicit-opt-in' } };
|
|
173
|
+
}
|
|
174
|
+
if (!isConsumedPath(target.scope, target.path)) {
|
|
175
|
+
return { result: { ...base, applied: false, skippedReason: 'no-consumer' } };
|
|
176
|
+
}
|
|
177
|
+
if (deepEqual(currentValue, writeValue)) {
|
|
178
|
+
return { result: { ...base, applied: false, skippedReason: 'unchanged' } };
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
result: { ...base, applied: true },
|
|
182
|
+
write: {
|
|
183
|
+
settingsObj,
|
|
184
|
+
scope: target.scope,
|
|
185
|
+
path: target.path,
|
|
186
|
+
writeValue,
|
|
187
|
+
priorValue: currentValue,
|
|
188
|
+
},
|
|
189
|
+
};
|
|
188
190
|
}
|
|
189
|
-
|
|
190
191
|
// Applies one decision's write to its in-memory settings object and journals
|
|
191
192
|
// it (deferred persistence — the caller flushes to disk once at the end).
|
|
192
|
-
function applyWrite(write,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
193
|
+
function applyWrite(write, context) {
|
|
194
|
+
const { repoRoot, journal, deps } = context;
|
|
195
|
+
setNestedValue(write.settingsObj, write.path, write.writeValue);
|
|
196
|
+
upsertJournalEntry(journal, {
|
|
197
|
+
scope: write.scope,
|
|
198
|
+
path: write.path,
|
|
199
|
+
repoRoot: write.scope === 'repo' ? repoRoot : null,
|
|
200
|
+
priorValue: write.priorValue,
|
|
201
|
+
appliedValue: write.writeValue,
|
|
202
|
+
appliedAt: deps.now(),
|
|
203
|
+
});
|
|
204
|
+
return write.scope;
|
|
203
205
|
}
|
|
204
|
-
|
|
205
206
|
// Phase 2: resolve each global outcome against the locked, freshly read state.
|
|
206
207
|
// Repo-local settings remain intentionally outside the global settings lock.
|
|
207
|
-
function writeResolvedDecisions(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
208
|
+
function writeResolvedDecisions(resolved, context) {
|
|
209
|
+
const { repoSettings, repoRoot, journal, allowRiskyDefaults, deps } = context;
|
|
210
|
+
const resultsById = new Map();
|
|
211
|
+
let repoDirty = false;
|
|
212
|
+
let globalDirty = false;
|
|
213
|
+
const globalDecisions = resolved.filter((decision) => decision.target.scope === 'global');
|
|
214
|
+
if (globalDecisions.length > 0) {
|
|
215
|
+
const globalResults = deps.mutateSettings((freshGlobalSettings) => {
|
|
216
|
+
const results = [];
|
|
217
|
+
for (const decision of globalDecisions) {
|
|
218
|
+
const freshDecision = {
|
|
219
|
+
...decision,
|
|
220
|
+
writeValue: convertDecisionValue({
|
|
221
|
+
decisionId: decision.decisionId,
|
|
222
|
+
value: decision.inputValue,
|
|
223
|
+
globalSettings: freshGlobalSettings,
|
|
224
|
+
deps,
|
|
225
|
+
}),
|
|
226
|
+
};
|
|
227
|
+
const { result, write } = resolveDecisionOutcome(freshDecision, {
|
|
228
|
+
globalSettings: freshGlobalSettings,
|
|
229
|
+
repoSettings,
|
|
230
|
+
allowRiskyDefaults,
|
|
231
|
+
});
|
|
232
|
+
results.push(result);
|
|
233
|
+
if (write) {
|
|
234
|
+
applyWrite(write, { repoRoot, journal, deps });
|
|
235
|
+
globalDirty = true;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return results;
|
|
233
239
|
});
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
240
|
+
for (const result of globalResults)
|
|
241
|
+
resultsById.set(result.decisionId, result);
|
|
242
|
+
}
|
|
243
|
+
for (const decision of resolved.filter((item) => item.target.scope === 'repo')) {
|
|
244
|
+
const { result, write } = resolveDecisionOutcome(decision, {
|
|
245
|
+
globalSettings: {},
|
|
246
|
+
repoSettings,
|
|
247
|
+
allowRiskyDefaults,
|
|
248
|
+
});
|
|
249
|
+
resultsById.set(result.decisionId, result);
|
|
250
|
+
if (!write)
|
|
251
|
+
continue;
|
|
252
|
+
applyWrite(write, { repoRoot, journal, deps });
|
|
253
|
+
repoDirty = true;
|
|
254
|
+
}
|
|
255
|
+
if (repoDirty)
|
|
256
|
+
deps.writeRepoSettings(repoRoot, repoSettings);
|
|
257
|
+
if (globalDirty || repoDirty)
|
|
258
|
+
saveJournal(journal);
|
|
259
|
+
return resolved.map((decision) => {
|
|
260
|
+
const result = resultsById.get(decision.decisionId);
|
|
261
|
+
if (!result)
|
|
262
|
+
throw new Error(`Missing apply result for decision: ${decision.decisionId}`);
|
|
263
|
+
return result;
|
|
250
264
|
});
|
|
251
|
-
resultsById.set(result.decisionId, result);
|
|
252
|
-
if (!write) continue;
|
|
253
|
-
applyWrite(write, { repoRoot, journal, deps });
|
|
254
|
-
repoDirty = true;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if (repoDirty) deps.writeRepoSettings(repoRoot, repoSettings);
|
|
258
|
-
if (globalDirty || repoDirty) saveJournal(journal);
|
|
259
|
-
return resolved.map((decision) => resultsById.get(decision.decisionId));
|
|
260
265
|
}
|
|
261
|
-
|
|
262
266
|
function assertDecisionObject(decisions, label) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
267
|
+
if (!decisions || typeof decisions !== 'object' || Array.isArray(decisions)) {
|
|
268
|
+
throw new Error(`${label} must be a JSON object of { decisionId: value }`);
|
|
269
|
+
}
|
|
266
270
|
}
|
|
267
|
-
|
|
268
271
|
/** Apply an in-memory decision object without temporary files. */
|
|
269
|
-
function applyDecisionValues({ decisions, cwd, allowRiskyDefaults = false, deps = {} }) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
return results;
|
|
272
|
+
function applyDecisionValues({ decisions, cwd, allowRiskyDefaults = false, deps = {}, }) {
|
|
273
|
+
assertDecisionObject(decisions, 'Decisions');
|
|
274
|
+
const resolvedDeps = { ...defaultApplyDeps(), ...deps };
|
|
275
|
+
const globalSettings = resolvedDeps.loadSettings();
|
|
276
|
+
const { repoRoot, settings: repoSettingsRaw } = resolvedDeps.readRepoSettings(cwd);
|
|
277
|
+
const repoSettings = repoSettingsRaw || {};
|
|
278
|
+
const resolved = resolveAndValidateDecisions(decisions, globalSettings, resolvedDeps);
|
|
279
|
+
const results = writeResolvedDecisions(resolved, {
|
|
280
|
+
repoSettings,
|
|
281
|
+
repoRoot,
|
|
282
|
+
journal: loadJournal(),
|
|
283
|
+
allowRiskyDefaults,
|
|
284
|
+
deps: resolvedDeps,
|
|
285
|
+
});
|
|
286
|
+
const issueSourceApplied = results.find((result) => result.decisionId === 'defaultIssueSource' && result.applied);
|
|
287
|
+
if (issueSourceApplied?.to === 'github') {
|
|
288
|
+
const auth = resolvedDeps.checkGhAuth();
|
|
289
|
+
if (!auth?.authenticated)
|
|
290
|
+
console.log('Run: gh auth login');
|
|
291
|
+
}
|
|
292
|
+
return results;
|
|
292
293
|
}
|
|
293
|
-
|
|
294
294
|
/** Apply a decisions JSON file through the shared object API. */
|
|
295
|
-
function applyDecisions({ decisionsPath, cwd, allowRiskyDefaults = false, deps = {} }) {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
295
|
+
function applyDecisions({ decisionsPath, cwd, allowRiskyDefaults = false, deps = {}, }) {
|
|
296
|
+
const resolvedDeps = { ...defaultApplyDeps(), ...deps };
|
|
297
|
+
let decisions;
|
|
298
|
+
try {
|
|
299
|
+
decisions = JSON.parse(resolvedDeps.readFile(decisionsPath));
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
const message = typeof error === 'object' && error !== null && 'message' in error
|
|
303
|
+
? error.message
|
|
304
|
+
: undefined;
|
|
305
|
+
throw new Error(`Failed to read decisions file "${decisionsPath}": ${String(message)}`);
|
|
306
|
+
}
|
|
307
|
+
assertDecisionObject(decisions, 'Decisions file');
|
|
308
|
+
return applyDecisionValues({
|
|
309
|
+
decisions,
|
|
310
|
+
cwd,
|
|
311
|
+
allowRiskyDefaults,
|
|
312
|
+
deps: resolvedDeps,
|
|
313
|
+
});
|
|
310
314
|
}
|
|
311
|
-
|
|
312
315
|
module.exports = {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
316
|
+
applyDecisions,
|
|
317
|
+
applyDecisionValues,
|
|
318
|
+
resolveAndValidateDecisions,
|
|
319
|
+
writeResolvedDecisions,
|
|
320
|
+
assertSecretSafePath,
|
|
321
|
+
isConsumedPath,
|
|
322
|
+
CONSUMED_PATHS,
|
|
320
323
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Undo journal for `zeroshot setup apply` / `zeroshot setup undo`.
|
|
3
|
+
*
|
|
4
|
+
* One journal entry per setting this setup owns: { scope, path, repoRoot,
|
|
5
|
+
* priorValue, appliedValue, appliedAt }. `priorValue: null` means the key
|
|
6
|
+
* did not exist before apply, so undo deletes it rather than restoring it.
|
|
7
|
+
* Shared by lib/setup-apply.js (writer) and lib/setup-undo.js (reader) so the
|
|
8
|
+
* nested-path mutation and equality semantics can't drift between the two.
|
|
9
|
+
*/
|
|
10
|
+
interface JournalEntry {
|
|
11
|
+
readonly appliedAt: string;
|
|
12
|
+
readonly appliedValue: unknown;
|
|
13
|
+
readonly path: string;
|
|
14
|
+
readonly priorValue: unknown;
|
|
15
|
+
readonly repoRoot: string | null;
|
|
16
|
+
readonly scope: string;
|
|
17
|
+
readonly [key: string]: unknown;
|
|
18
|
+
}
|
|
19
|
+
interface SetupJournal {
|
|
20
|
+
entries: JournalEntry[];
|
|
21
|
+
version: number;
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
}
|
|
24
|
+
declare function getJournalPath(): string;
|
|
25
|
+
declare function loadJournal(): SetupJournal;
|
|
26
|
+
declare function saveJournal(journal: SetupJournal): void;
|
|
27
|
+
declare function upsertJournalEntry(journal: SetupJournal, entry: JournalEntry): void;
|
|
28
|
+
declare function setNestedValue(target: Record<string, unknown>, pathStr: string, value: unknown): void;
|
|
29
|
+
declare function deleteNestedKey(target: Record<string, unknown>, pathStr: string): void;
|
|
30
|
+
declare function deepEqual(left: unknown, right: unknown): boolean;
|
|
31
|
+
declare const _default: {
|
|
32
|
+
getJournalPath: typeof getJournalPath;
|
|
33
|
+
loadJournal: typeof loadJournal;
|
|
34
|
+
saveJournal: typeof saveJournal;
|
|
35
|
+
upsertJournalEntry: typeof upsertJournalEntry;
|
|
36
|
+
getNestedValue: (source: Record<string, unknown>, pathStr: string) => unknown;
|
|
37
|
+
setNestedValue: typeof setNestedValue;
|
|
38
|
+
deleteNestedKey: typeof deleteNestedKey;
|
|
39
|
+
deepEqual: typeof deepEqual;
|
|
40
|
+
};
|
|
41
|
+
export = _default;
|