@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
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
interface AgentStuckDetectorModule {
|
|
2
|
+
isPlatformSupported(): boolean;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
interface LivenessIsolation {
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface NestedExecutions {
|
|
10
|
+
hasActive?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface LivenessAgent {
|
|
14
|
+
currentTask?: unknown;
|
|
15
|
+
currentTaskId?: unknown;
|
|
16
|
+
isolation?: LivenessIsolation | null;
|
|
17
|
+
nestedExecutions?: NestedExecutions | null;
|
|
18
|
+
livenessTerminationStarted?: boolean;
|
|
19
|
+
livenessTerminationContext?: unknown;
|
|
20
|
+
livenessTerminationRetryAt: number;
|
|
21
|
+
taskStartedAt?: number | null;
|
|
22
|
+
lastOutputTime?: number | null;
|
|
23
|
+
consecutiveStaleWarnings: number;
|
|
24
|
+
_publishLifecycle(event: string, details: Record<string, unknown>): unknown;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface TaskTiming {
|
|
28
|
+
taskRuntime: number;
|
|
29
|
+
timeSinceLastOutput: number;
|
|
30
|
+
lastOutputTime: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type AttemptTermination = (agent: LivenessAgent, settings: unknown) => unknown;
|
|
34
|
+
|
|
35
|
+
type BeginTermination = (
|
|
36
|
+
agent: LivenessAgent,
|
|
37
|
+
settings: unknown,
|
|
38
|
+
reason: string,
|
|
39
|
+
code: string,
|
|
40
|
+
eventData: Record<string, unknown>
|
|
41
|
+
) => unknown;
|
|
42
|
+
|
|
43
|
+
interface LivenessPollContext {
|
|
44
|
+
agent: LivenessAgent;
|
|
45
|
+
settings: unknown;
|
|
46
|
+
configuredTimeout: number | null;
|
|
47
|
+
staleDuration: number;
|
|
48
|
+
warningsBeforeKill: number;
|
|
49
|
+
attemptTermination: AttemptTermination;
|
|
50
|
+
beginTermination: BeginTermination;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function isAgentStuckDetectorModule(value: unknown): value is AgentStuckDetectorModule {
|
|
54
|
+
return (
|
|
55
|
+
typeof value === 'object' &&
|
|
56
|
+
value !== null &&
|
|
57
|
+
'isPlatformSupported' in value &&
|
|
58
|
+
typeof value.isPlatformSupported === 'function'
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const agentStuckDetectorModule: unknown = require('./agent-stuck-detector');
|
|
63
|
+
if (!isAgentStuckDetectorModule(agentStuckDetectorModule)) {
|
|
64
|
+
throw new TypeError('agent-stuck-detector must export isPlatformSupported');
|
|
65
|
+
}
|
|
66
|
+
const isPlatformSupported = agentStuckDetectorModule.isPlatformSupported;
|
|
67
|
+
|
|
68
|
+
function hasRecoverableTask(agent: LivenessAgent): boolean {
|
|
69
|
+
return (
|
|
70
|
+
Boolean(agent.currentTask) ||
|
|
71
|
+
Boolean(agent.isolation?.enabled && agent.currentTaskId) ||
|
|
72
|
+
agent.nestedExecutions?.hasActive === true
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function handlePendingTermination(
|
|
77
|
+
agent: LivenessAgent,
|
|
78
|
+
settings: unknown,
|
|
79
|
+
now: number,
|
|
80
|
+
attemptTermination: AttemptTermination
|
|
81
|
+
): boolean {
|
|
82
|
+
if (!agent.livenessTerminationContext) return false;
|
|
83
|
+
if (now >= agent.livenessTerminationRetryAt) attemptTermination(agent, settings);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function taskTiming(agent: LivenessAgent, now: number): TaskTiming {
|
|
88
|
+
const taskStartedAt = agent.taskStartedAt || agent.lastOutputTime || now;
|
|
89
|
+
const lastOutputTime = agent.lastOutputTime || taskStartedAt;
|
|
90
|
+
return {
|
|
91
|
+
taskRuntime: now - taskStartedAt,
|
|
92
|
+
timeSinceLastOutput: now - lastOutputTime,
|
|
93
|
+
lastOutputTime,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function handleTaskTimeout(context: LivenessPollContext, timing: TaskTiming): boolean {
|
|
98
|
+
const { agent, settings, configuredTimeout, beginTermination } = context;
|
|
99
|
+
if (!configuredTimeout || timing.taskRuntime < configuredTimeout) return false;
|
|
100
|
+
beginTermination(
|
|
101
|
+
agent,
|
|
102
|
+
settings,
|
|
103
|
+
`Task timed out after ${configuredTimeout}ms`,
|
|
104
|
+
'AGENT_TASK_TIMEOUT',
|
|
105
|
+
{
|
|
106
|
+
taskId: agent.currentTaskId,
|
|
107
|
+
taskRuntime: timing.taskRuntime,
|
|
108
|
+
timeout: configuredTimeout,
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function publishStaleWarning(context: LivenessPollContext, timing: TaskTiming): void {
|
|
115
|
+
const { agent, staleDuration, warningsBeforeKill } = context;
|
|
116
|
+
agent.consecutiveStaleWarnings += 1;
|
|
117
|
+
agent._publishLifecycle('AGENT_STALE_WARNING', {
|
|
118
|
+
taskId: agent.currentTaskId,
|
|
119
|
+
timeSinceLastOutput: timing.timeSinceLastOutput,
|
|
120
|
+
staleDuration,
|
|
121
|
+
lastOutputTime: timing.lastOutputTime,
|
|
122
|
+
consecutiveWarnings: agent.consecutiveStaleWarnings,
|
|
123
|
+
warningsBeforeKill,
|
|
124
|
+
processDiagnosticsAvailable: isPlatformSupported(),
|
|
125
|
+
analysis: `Provider produced no output for ${timing.timeSinceLastOutput}ms`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function terminateForInactivity(context: LivenessPollContext, timing: TaskTiming): void {
|
|
130
|
+
const { agent, settings, staleDuration, beginTermination } = context;
|
|
131
|
+
beginTermination(
|
|
132
|
+
agent,
|
|
133
|
+
settings,
|
|
134
|
+
`Provider produced no output for ${timing.timeSinceLastOutput}ms`,
|
|
135
|
+
'PROVIDER_INACTIVITY_TIMEOUT',
|
|
136
|
+
{
|
|
137
|
+
taskId: agent.currentTaskId,
|
|
138
|
+
timeSinceLastOutput: timing.timeSinceLastOutput,
|
|
139
|
+
staleDuration,
|
|
140
|
+
consecutiveWarnings: agent.consecutiveStaleWarnings,
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function createLivenessPoll(context: LivenessPollContext): () => void {
|
|
146
|
+
const { agent, settings, staleDuration, warningsBeforeKill, attemptTermination } = context;
|
|
147
|
+
return () => {
|
|
148
|
+
if (!hasRecoverableTask(agent) || agent.livenessTerminationStarted) return;
|
|
149
|
+
const now = Date.now();
|
|
150
|
+
if (handlePendingTermination(agent, settings, now, attemptTermination)) return;
|
|
151
|
+
const timing = taskTiming(agent, now);
|
|
152
|
+
if (handleTaskTimeout(context, timing)) return;
|
|
153
|
+
if (timing.timeSinceLastOutput < staleDuration) {
|
|
154
|
+
agent.consecutiveStaleWarnings = 0;
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
publishStaleWarning(context, timing);
|
|
158
|
+
if (agent.consecutiveStaleWarnings < warningsBeforeKill) return;
|
|
159
|
+
terminateForInactivity(context, timing);
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export = { createLivenessPoll };
|
|
@@ -1,102 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
function buildQualityGateSchema() {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
3
|
+
return {
|
|
4
|
+
type: 'array',
|
|
5
|
+
description: 'Tool-neutral ship handoff quality gate evidence for configured required gates.',
|
|
6
|
+
items: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
id: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
description: 'Stable gate id matching the configured required quality gate.',
|
|
12
|
+
},
|
|
13
|
+
name: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
description: 'Optional display name for the gate.',
|
|
16
|
+
},
|
|
17
|
+
status: {
|
|
18
|
+
type: 'string',
|
|
19
|
+
enum: ['PASS', 'FAIL', 'UNAVAILABLE'],
|
|
20
|
+
description: 'PASS only when the gate completed successfully.',
|
|
21
|
+
},
|
|
22
|
+
scope: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Optional repo-defined scope for the gate.',
|
|
25
|
+
},
|
|
26
|
+
evidence: {
|
|
27
|
+
type: 'object',
|
|
28
|
+
properties: {
|
|
29
|
+
command: { type: 'string' },
|
|
30
|
+
exitCode: { type: 'integer' },
|
|
31
|
+
output: { type: 'string' },
|
|
32
|
+
proof: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
description: 'Optional command proof metadata when the gate used cmdproof.',
|
|
35
|
+
properties: {
|
|
36
|
+
profile: { type: 'string' },
|
|
37
|
+
reused: { type: 'boolean' },
|
|
38
|
+
status: { type: 'string' },
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
required: ['command', 'exitCode', 'output'],
|
|
43
|
+
},
|
|
44
|
+
completedAt: {
|
|
45
|
+
anyOf: [{ type: 'string' }, { type: 'number' }],
|
|
46
|
+
description: 'When the gate completed, as an ISO string or numeric timestamp.',
|
|
47
|
+
},
|
|
48
|
+
timestamp: {
|
|
49
|
+
anyOf: [{ type: 'string' }, { type: 'number' }],
|
|
50
|
+
description: 'Alternate completion timestamp, as an ISO string or numeric timestamp.',
|
|
51
|
+
},
|
|
52
|
+
stale: {
|
|
53
|
+
type: 'boolean',
|
|
54
|
+
description: 'True when this evidence is known stale and must block handoff.',
|
|
55
|
+
},
|
|
56
|
+
reason: { type: 'string' },
|
|
39
57
|
},
|
|
40
|
-
|
|
41
|
-
required: ['command', 'exitCode', 'output'],
|
|
42
|
-
},
|
|
43
|
-
completedAt: {
|
|
44
|
-
anyOf: [{ type: 'string' }, { type: 'number' }],
|
|
45
|
-
description: 'When the gate completed, as an ISO string or numeric timestamp.',
|
|
46
|
-
},
|
|
47
|
-
timestamp: {
|
|
48
|
-
anyOf: [{ type: 'string' }, { type: 'number' }],
|
|
49
|
-
description: 'Alternate completion timestamp, as an ISO string or numeric timestamp.',
|
|
50
|
-
},
|
|
51
|
-
stale: {
|
|
52
|
-
type: 'boolean',
|
|
53
|
-
description: 'True when this evidence is known stale and must block handoff.',
|
|
58
|
+
required: ['id', 'status', 'evidence'],
|
|
54
59
|
},
|
|
55
|
-
|
|
56
|
-
},
|
|
57
|
-
required: ['id', 'status', 'evidence'],
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
+
};
|
|
60
61
|
}
|
|
61
|
-
|
|
62
62
|
function hasRequiredQualityGates(config) {
|
|
63
|
-
|
|
63
|
+
return Array.isArray(config.requiredQualityGates) && config.requiredQualityGates.length > 0;
|
|
64
64
|
}
|
|
65
|
-
|
|
66
65
|
function shouldApplyValidatorQualityGateDefaults(config) {
|
|
67
|
-
|
|
68
|
-
config.role === 'validator' && config.outputFormat === 'json' && hasRequiredQualityGates(config)
|
|
69
|
-
);
|
|
66
|
+
return (config.role === 'validator' && config.outputFormat === 'json' && hasRequiredQualityGates(config));
|
|
70
67
|
}
|
|
71
|
-
|
|
72
68
|
function applyValidatorQualityGateSchema(config) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
69
|
+
if (!shouldApplyValidatorQualityGateDefaults(config)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const properties = config.jsonSchema?.properties;
|
|
73
|
+
if (properties && !properties.qualityGates) {
|
|
74
|
+
properties.qualityGates = buildQualityGateSchema();
|
|
75
|
+
}
|
|
81
76
|
}
|
|
82
|
-
|
|
83
77
|
function applyValidatorQualityGatePublishMapping(config) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
78
|
+
if (!shouldApplyValidatorQualityGateDefaults(config)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const data = config.hooks?.onComplete?.config?.content?.data;
|
|
82
|
+
if (data && data.qualityGates === undefined) {
|
|
83
|
+
data.qualityGates = '{{result.qualityGates}}';
|
|
84
|
+
}
|
|
92
85
|
}
|
|
93
|
-
|
|
94
86
|
function applyValidatorQualityGateDefaults(config) {
|
|
95
|
-
|
|
96
|
-
|
|
87
|
+
applyValidatorQualityGateSchema(config);
|
|
88
|
+
applyValidatorQualityGatePublishMapping(config);
|
|
97
89
|
}
|
|
98
|
-
|
|
99
90
|
module.exports = {
|
|
100
|
-
|
|
101
|
-
|
|
91
|
+
applyValidatorQualityGateDefaults,
|
|
92
|
+
buildQualityGateSchema,
|
|
102
93
|
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
type JsonSchemaType = 'array' | 'boolean' | 'integer' | 'number' | 'object' | 'string';
|
|
2
|
+
|
|
3
|
+
interface JsonSchema {
|
|
4
|
+
type?: JsonSchemaType;
|
|
5
|
+
description?: string;
|
|
6
|
+
enum?: string[];
|
|
7
|
+
items?: JsonSchema;
|
|
8
|
+
properties?: Record<string, JsonSchema>;
|
|
9
|
+
required?: string[];
|
|
10
|
+
anyOf?: JsonSchema[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface QualityGatePublishData {
|
|
14
|
+
qualityGates?: unknown;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface AgentQualityGateConfig {
|
|
19
|
+
role?: string;
|
|
20
|
+
outputFormat?: string;
|
|
21
|
+
requiredQualityGates?: unknown;
|
|
22
|
+
jsonSchema?: JsonSchema;
|
|
23
|
+
hooks?: {
|
|
24
|
+
onComplete?: {
|
|
25
|
+
config?: {
|
|
26
|
+
content?: {
|
|
27
|
+
data?: QualityGatePublishData;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function buildQualityGateSchema(): JsonSchema {
|
|
35
|
+
return {
|
|
36
|
+
type: 'array',
|
|
37
|
+
description: 'Tool-neutral ship handoff quality gate evidence for configured required gates.',
|
|
38
|
+
items: {
|
|
39
|
+
type: 'object',
|
|
40
|
+
properties: {
|
|
41
|
+
id: {
|
|
42
|
+
type: 'string',
|
|
43
|
+
description: 'Stable gate id matching the configured required quality gate.',
|
|
44
|
+
},
|
|
45
|
+
name: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
description: 'Optional display name for the gate.',
|
|
48
|
+
},
|
|
49
|
+
status: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
enum: ['PASS', 'FAIL', 'UNAVAILABLE'],
|
|
52
|
+
description: 'PASS only when the gate completed successfully.',
|
|
53
|
+
},
|
|
54
|
+
scope: {
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: 'Optional repo-defined scope for the gate.',
|
|
57
|
+
},
|
|
58
|
+
evidence: {
|
|
59
|
+
type: 'object',
|
|
60
|
+
properties: {
|
|
61
|
+
command: { type: 'string' },
|
|
62
|
+
exitCode: { type: 'integer' },
|
|
63
|
+
output: { type: 'string' },
|
|
64
|
+
proof: {
|
|
65
|
+
type: 'object',
|
|
66
|
+
description: 'Optional command proof metadata when the gate used cmdproof.',
|
|
67
|
+
properties: {
|
|
68
|
+
profile: { type: 'string' },
|
|
69
|
+
reused: { type: 'boolean' },
|
|
70
|
+
status: { type: 'string' },
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
required: ['command', 'exitCode', 'output'],
|
|
75
|
+
},
|
|
76
|
+
completedAt: {
|
|
77
|
+
anyOf: [{ type: 'string' }, { type: 'number' }],
|
|
78
|
+
description: 'When the gate completed, as an ISO string or numeric timestamp.',
|
|
79
|
+
},
|
|
80
|
+
timestamp: {
|
|
81
|
+
anyOf: [{ type: 'string' }, { type: 'number' }],
|
|
82
|
+
description: 'Alternate completion timestamp, as an ISO string or numeric timestamp.',
|
|
83
|
+
},
|
|
84
|
+
stale: {
|
|
85
|
+
type: 'boolean',
|
|
86
|
+
description: 'True when this evidence is known stale and must block handoff.',
|
|
87
|
+
},
|
|
88
|
+
reason: { type: 'string' },
|
|
89
|
+
},
|
|
90
|
+
required: ['id', 'status', 'evidence'],
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function hasRequiredQualityGates(config: AgentQualityGateConfig): boolean {
|
|
96
|
+
return Array.isArray(config.requiredQualityGates) && config.requiredQualityGates.length > 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function shouldApplyValidatorQualityGateDefaults(config: AgentQualityGateConfig): boolean {
|
|
100
|
+
return (
|
|
101
|
+
config.role === 'validator' && config.outputFormat === 'json' && hasRequiredQualityGates(config)
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function applyValidatorQualityGateSchema(config: AgentQualityGateConfig): void {
|
|
106
|
+
if (!shouldApplyValidatorQualityGateDefaults(config)) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const properties = config.jsonSchema?.properties;
|
|
111
|
+
if (properties && !properties.qualityGates) {
|
|
112
|
+
properties.qualityGates = buildQualityGateSchema();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function applyValidatorQualityGatePublishMapping(config: AgentQualityGateConfig): void {
|
|
117
|
+
if (!shouldApplyValidatorQualityGateDefaults(config)) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const data = config.hooks?.onComplete?.config?.content?.data;
|
|
122
|
+
if (data && data.qualityGates === undefined) {
|
|
123
|
+
data.qualityGates = '{{result.qualityGates}}';
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function applyValidatorQualityGateDefaults(config: AgentQualityGateConfig): void {
|
|
128
|
+
applyValidatorQualityGateSchema(config);
|
|
129
|
+
applyValidatorQualityGatePublishMapping(config);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export = {
|
|
133
|
+
applyValidatorQualityGateDefaults,
|
|
134
|
+
buildQualityGateSchema,
|
|
135
|
+
};
|
|
@@ -1,56 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
function isQualityGatesModule(value) {
|
|
3
|
+
return (typeof value === 'object' &&
|
|
4
|
+
value !== null &&
|
|
5
|
+
'normalizeRequiredQualityGates' in value &&
|
|
6
|
+
typeof value.normalizeRequiredQualityGates === 'function');
|
|
7
|
+
}
|
|
8
|
+
const qualityGatesModule = require('../quality-gates');
|
|
9
|
+
if (!isQualityGatesModule(qualityGatesModule)) {
|
|
10
|
+
throw new TypeError('quality-gates must export normalizeRequiredQualityGates');
|
|
11
|
+
}
|
|
12
|
+
const normalizeRequiredQualityGates = qualityGatesModule.normalizeRequiredQualityGates;
|
|
3
13
|
function appendGateDetails(lines, gate, index) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
lines.push(`${index + 1}. id: ${gate.id}${gate.scope ? `, scope: ${gate.scope}` : ''}`);
|
|
15
|
+
if (gate.description) {
|
|
16
|
+
lines.push(` description: ${gate.description}`);
|
|
17
|
+
}
|
|
18
|
+
if (gate.command) {
|
|
19
|
+
lines.push(` command: ${gate.command}`);
|
|
20
|
+
}
|
|
21
|
+
if (gate.profile || gate.proofProfile) {
|
|
22
|
+
lines.push(` cmdproof profile: ${gate.profile || gate.proofProfile}`);
|
|
23
|
+
lines.push(` cmdproof helper: zeroshot cmdproof check ${gate.id}`);
|
|
24
|
+
}
|
|
15
25
|
}
|
|
16
|
-
|
|
17
26
|
function buildRequiredQualityGatesSection(config) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
lines.push(
|
|
39
|
-
'',
|
|
40
|
-
'For each configured gate:',
|
|
41
|
-
'- Run the configured command when one is provided by repo or cluster config.',
|
|
42
|
-
'- For gates with a cmdproof profile, run `zeroshot cmdproof check <id>` before considering a raw command.',
|
|
43
|
-
'- Put the command, numeric exit code, and string output in `evidence`.',
|
|
44
|
-
'- Set `status` to `PASS` only when the gate completes successfully.',
|
|
45
|
-
'- If a required gate fails, set `approved` to false and publish status `FAIL`.',
|
|
46
|
-
'- If a required gate cannot run because its command, tool, or service is unavailable, set `approved` to false and publish status `UNAVAILABLE`.',
|
|
47
|
-
'- Use `completedAt` or `timestamp` from the current validation run; stale evidence must be marked with `stale: true`.',
|
|
48
|
-
''
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
return lines.join('\n');
|
|
27
|
+
if (config.role !== 'validator') {
|
|
28
|
+
return '';
|
|
29
|
+
}
|
|
30
|
+
const gates = normalizeRequiredQualityGates(config.requiredQualityGates);
|
|
31
|
+
if (gates.length === 0) {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
const lines = [
|
|
35
|
+
'## Required Handoff Quality Gates',
|
|
36
|
+
'',
|
|
37
|
+
'Before approving implementation handoff, publish one `qualityGates` entry for each configured required gate.',
|
|
38
|
+
'Each entry must use the configured `id` and `scope` when a scope is configured.',
|
|
39
|
+
'',
|
|
40
|
+
'Configured gates:',
|
|
41
|
+
];
|
|
42
|
+
gates.forEach((gate, index) => appendGateDetails(lines, gate, index));
|
|
43
|
+
lines.push('', 'For each configured gate:', '- Run the configured command when one is provided by repo or cluster config.', '- For gates with a cmdproof profile, run `zeroshot cmdproof check <id>` before considering a raw command.', '- Put the command, numeric exit code, and string output in `evidence`.', '- Set `status` to `PASS` only when the gate completes successfully.', '- If a required gate fails, set `approved` to false and publish status `FAIL`.', '- If a required gate cannot run because its command, tool, or service is unavailable, ' +
|
|
44
|
+
'set `approved` to false and publish status `UNAVAILABLE`.', '- Use `completedAt` or `timestamp` from the current validation run; ' +
|
|
45
|
+
'stale evidence must be marked with `stale: true`.', '');
|
|
46
|
+
return lines.join('\n');
|
|
52
47
|
}
|
|
53
|
-
|
|
54
48
|
module.exports = {
|
|
55
|
-
|
|
49
|
+
buildRequiredQualityGatesSection,
|
|
56
50
|
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
type StringList = string[];
|
|
2
|
+
|
|
3
|
+
interface RequiredQualityGate {
|
|
4
|
+
id: string;
|
|
5
|
+
scope?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
command?: string;
|
|
8
|
+
profile?: string;
|
|
9
|
+
proofProfile?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface AgentQualityGateConfig {
|
|
13
|
+
role?: string;
|
|
14
|
+
requiredQualityGates?: unknown;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface QualityGatesModule {
|
|
18
|
+
normalizeRequiredQualityGates(value: unknown): RequiredQualityGate[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isQualityGatesModule(value: unknown): value is QualityGatesModule {
|
|
22
|
+
return (
|
|
23
|
+
typeof value === 'object' &&
|
|
24
|
+
value !== null &&
|
|
25
|
+
'normalizeRequiredQualityGates' in value &&
|
|
26
|
+
typeof value.normalizeRequiredQualityGates === 'function'
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const qualityGatesModule: unknown = require('../quality-gates');
|
|
31
|
+
if (!isQualityGatesModule(qualityGatesModule)) {
|
|
32
|
+
throw new TypeError('quality-gates must export normalizeRequiredQualityGates');
|
|
33
|
+
}
|
|
34
|
+
const normalizeRequiredQualityGates = qualityGatesModule.normalizeRequiredQualityGates;
|
|
35
|
+
|
|
36
|
+
function appendGateDetails(lines: StringList, gate: RequiredQualityGate, index: number): void {
|
|
37
|
+
lines.push(`${index + 1}. id: ${gate.id}${gate.scope ? `, scope: ${gate.scope}` : ''}`);
|
|
38
|
+
if (gate.description) {
|
|
39
|
+
lines.push(` description: ${gate.description}`);
|
|
40
|
+
}
|
|
41
|
+
if (gate.command) {
|
|
42
|
+
lines.push(` command: ${gate.command}`);
|
|
43
|
+
}
|
|
44
|
+
if (gate.profile || gate.proofProfile) {
|
|
45
|
+
lines.push(` cmdproof profile: ${gate.profile || gate.proofProfile}`);
|
|
46
|
+
lines.push(` cmdproof helper: zeroshot cmdproof check ${gate.id}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function buildRequiredQualityGatesSection(config: AgentQualityGateConfig): string {
|
|
51
|
+
if (config.role !== 'validator') {
|
|
52
|
+
return '';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const gates = normalizeRequiredQualityGates(config.requiredQualityGates);
|
|
56
|
+
if (gates.length === 0) {
|
|
57
|
+
return '';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const lines = [
|
|
61
|
+
'## Required Handoff Quality Gates',
|
|
62
|
+
'',
|
|
63
|
+
'Before approving implementation handoff, publish one `qualityGates` entry for each configured required gate.',
|
|
64
|
+
'Each entry must use the configured `id` and `scope` when a scope is configured.',
|
|
65
|
+
'',
|
|
66
|
+
'Configured gates:',
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
gates.forEach((gate, index) => appendGateDetails(lines, gate, index));
|
|
70
|
+
|
|
71
|
+
lines.push(
|
|
72
|
+
'',
|
|
73
|
+
'For each configured gate:',
|
|
74
|
+
'- Run the configured command when one is provided by repo or cluster config.',
|
|
75
|
+
'- For gates with a cmdproof profile, run `zeroshot cmdproof check <id>` before considering a raw command.',
|
|
76
|
+
'- Put the command, numeric exit code, and string output in `evidence`.',
|
|
77
|
+
'- Set `status` to `PASS` only when the gate completes successfully.',
|
|
78
|
+
'- If a required gate fails, set `approved` to false and publish status `FAIL`.',
|
|
79
|
+
'- If a required gate cannot run because its command, tool, or service is unavailable, ' +
|
|
80
|
+
'set `approved` to false and publish status `UNAVAILABLE`.',
|
|
81
|
+
'- Use `completedAt` or `timestamp` from the current validation run; ' +
|
|
82
|
+
'stale evidence must be marked with `stale: true`.',
|
|
83
|
+
''
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
return lines.join('\n');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export = {
|
|
90
|
+
buildRequiredQualityGatesSection,
|
|
91
|
+
};
|