nexus-agents 8.19.0 → 8.20.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/dist/{chunk-3W4L63ML.js → chunk-2G2ZXAD7.js} +1 -1
- package/dist/chunk-2G2ZXAD7.js.map +1 -0
- package/dist/{chunk-LB7DDJOG.js → chunk-ASUB4LSV.js} +3 -3
- package/dist/chunk-AWFW6FD4.js +7 -0
- package/dist/{chunk-ZTB4Z23O.js → chunk-FZXMMOBQ.js} +2 -2
- package/dist/{chunk-5LAPFTNG.js → chunk-PIWFHJSU.js} +301 -50
- package/dist/chunk-PIWFHJSU.js.map +1 -0
- package/dist/{chunk-KJN5RWXY.js → chunk-PODRYCRR.js} +41 -24
- package/dist/chunk-PODRYCRR.js.map +1 -0
- package/dist/{chunk-6B7E372N.js → chunk-W5M6VFDH.js} +2 -2
- package/dist/{chunk-2WAF3ZFK.js → chunk-XSRCJ7FA.js} +3 -3
- package/dist/cli.js +18 -17
- package/dist/cli.js.map +1 -1
- package/dist/{consensus-vote-QS72DIWI.js → consensus-vote-X4XXWGDD.js} +4 -4
- package/dist/{improvement-review-JRUO6SOJ.js → improvement-review-I7NBW7QO.js} +4 -4
- package/dist/index.d.ts +18 -13
- package/dist/index.js +8 -138
- package/dist/index.js.map +1 -1
- package/dist/{pr-reviewer-helpers-BINKSJSV.js → pr-reviewer-helpers-7CDQLZCS.js} +3 -3
- package/dist/{setup-data-dir-4AUIRLO4.js → setup-data-dir-JHZPDCPY.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-3W4L63ML.js.map +0 -1
- package/dist/chunk-5LAPFTNG.js.map +0 -1
- package/dist/chunk-KJN5RWXY.js.map +0 -1
- package/dist/chunk-XFDT265H.js +0 -7
- /package/dist/{chunk-LB7DDJOG.js.map → chunk-ASUB4LSV.js.map} +0 -0
- /package/dist/{chunk-XFDT265H.js.map → chunk-AWFW6FD4.js.map} +0 -0
- /package/dist/{chunk-ZTB4Z23O.js.map → chunk-FZXMMOBQ.js.map} +0 -0
- /package/dist/{chunk-6B7E372N.js.map → chunk-W5M6VFDH.js.map} +0 -0
- /package/dist/{chunk-2WAF3ZFK.js.map → chunk-XSRCJ7FA.js.map} +0 -0
- /package/dist/{consensus-vote-QS72DIWI.js.map → consensus-vote-X4XXWGDD.js.map} +0 -0
- /package/dist/{improvement-review-JRUO6SOJ.js.map → improvement-review-I7NBW7QO.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-BINKSJSV.js.map → pr-reviewer-helpers-7CDQLZCS.js.map} +0 -0
- /package/dist/{setup-data-dir-4AUIRLO4.js.map → setup-data-dir-JHZPDCPY.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dogfooding/pr-review-types.ts","../src/security/sarif-types.ts"],"sourcesContent":["/**\n * nexus-agents/dogfooding - PR Review Types\n *\n * Type definitions for automated pull request review using\n * multi-agent collaboration.\n *\n * @module dogfooding/pr-review-types\n * (Source: Issue #161, Alignment Roadmap Phase 3)\n */\n\nimport { z } from 'zod';\nimport type { FullCapableProvider } from '../scm/types.js';\nimport { FINDING_SEVERITY_LEVELS } from '../security/sarif-types.js';\n\n/**\n * Pull request file change information.\n */\nexport interface PRFileChange {\n /** File path */\n readonly filename: string;\n /** Change status */\n readonly status: 'added' | 'removed' | 'modified' | 'renamed' | 'copied';\n /** Number of additions */\n readonly additions: number;\n /** Number of deletions */\n readonly deletions: number;\n /** File patch/diff content */\n readonly patch?: string | undefined;\n /** Previous filename if renamed */\n readonly previousFilename?: string | undefined;\n}\n\n/**\n * Pull request metadata from GitHub API.\n */\nexport interface PRMetadata {\n /** PR number */\n readonly number: number;\n /** PR title */\n readonly title: string;\n /** PR description/body */\n readonly body: string;\n /** Author username */\n readonly author: string;\n /** GitHub API author_association (e.g., 'OWNER', 'COLLABORATOR', 'NONE') */\n readonly authorAssociation: string;\n /** Base branch */\n readonly base: string;\n /** Head branch */\n readonly head: string;\n /** Repository owner */\n readonly owner: string;\n /** Repository name */\n readonly repo: string;\n /** PR URL */\n readonly url: string;\n /** Whether PR is draft */\n readonly draft: boolean;\n /** PR labels */\n readonly labels: readonly string[];\n /** Changed files */\n readonly files: readonly PRFileChange[];\n /** Total additions */\n readonly additions: number;\n /** Total deletions */\n readonly deletions: number;\n /** Commit SHA of head */\n readonly headSha: string;\n}\n\n/**\n * Review severity levels.\n */\nexport type ReviewSeverity = (typeof FINDING_SEVERITY_LEVELS)[number];\n\n/**\n * Review category for organizing findings.\n */\nexport type ReviewCategory =\n 'security' | 'performance' | 'code_quality' | 'testing' | 'documentation' | 'architecture';\n\n/**\n * Individual review finding from an expert.\n */\nexport interface ReviewFinding {\n /** Unique finding ID */\n readonly id: string;\n /** Category of finding */\n readonly category: ReviewCategory;\n /** Severity level */\n readonly severity: ReviewSeverity;\n /** Finding title */\n readonly title: string;\n /** Detailed description */\n readonly description: string;\n /** Affected file (if applicable) */\n readonly file?: string | undefined;\n /** Line number (if applicable) */\n readonly line?: number | undefined;\n /** Suggested fix */\n readonly suggestion?: string | undefined;\n /** Expert that found this issue */\n readonly expertId: string;\n /** Confidence score (0-1) */\n readonly confidence: number;\n}\n\n/**\n * Review result from a single expert agent.\n */\nexport interface ExpertReviewResult {\n /** Expert ID */\n readonly expertId: string;\n /** Expert role/type */\n readonly expertType: string;\n /** Overall approval */\n readonly approved: boolean;\n /** Review summary */\n readonly summary: string;\n /** Individual findings */\n readonly findings: readonly ReviewFinding[];\n /** Execution time in ms */\n readonly durationMs: number;\n /** Confidence in review (0-1) */\n readonly confidence: number;\n /**\n * The expert never produced a verdict — its adapter failed or returned\n * nothing (#5012).\n *\n * `approved` cannot express this. A failed expert used to be recorded as\n * `approved: true` (\"don't block on failures\"), so a review in which every\n * expert failed resolved to `approve` at 100% consensus and was posted to\n * GitHub as a real APPROVE. Absence of a review is not approval — a consumer\n * must be able to tell them apart, and `confidence: 0` was already present\n * and already ignored.\n */\n readonly errored?: boolean;\n}\n\n/**\n * Aggregated review decision after multi-agent debate.\n */\nexport type ReviewDecision = 'approve' | 'request_changes' | 'comment';\n\n/**\n * Complete PR review result from multi-agent collaboration.\n */\n/**\n * Trust + reputation assessment of the PR author, surfaced for observability\n * (#3123, epic #3118 Phase 5). Mirrors `issue_triage`'s assessment.\n */\nexport interface PRTrustAssessment {\n /** Classifier trust tier (1-4) from author association. */\n readonly trustTier: string;\n /** Author's GitHub role. */\n readonly userRole: string;\n /**\n * Whether the author is on the maintainer allowlist — present only when an\n * allowlist was consulted (#4992). Absent means \"no allowlist was consulted\",\n * which is the state on every live path today; it was previously recorded\n * as `false` without being measured.\n */\n readonly isAllowlisted?: boolean;\n /**\n * Whether a durable `AuditLogger` was configured for this process (#4992\n * review). `configured` — the trust event was handed to it; delivery to the\n * hash chain is subject to the logger's own severity filter (trust events\n * are `info`), queue and fail-loud flush, and is not confirmed per call.\n * `none` — no audit logger (audit disabled, or the CLI path).\n */\n readonly auditSink: 'configured' | 'none';\n /** Reputation score (0-100) when reputation is enabled. */\n readonly reputationScore?: number | undefined;\n /** Suspicious signals detected (e.g. `new_account`, `injection_patterns_detected`). */\n readonly suspiciousSignals: readonly string[];\n /** Whether the author is flagged as suspicious. */\n readonly isSuspicious: boolean;\n /** Tier the policy gate ACTUALLY enforced (== trustTier under audit/off). */\n readonly enforcedTrustTier?: string | undefined;\n /** Tier reputation reconciliation computed — what enforce mode WOULD gate on. */\n readonly reputationReconciledTier?: string | undefined;\n /** Reputation-gating rollout mode applied: `off` | `audit` | `enforce`. */\n readonly gatingMode?: string | undefined;\n}\n\n/**\n * Result of fetching PR data plus best-effort author signals (#3133).\n */\nexport interface PRFetchData {\n readonly metadata: PRMetadata;\n readonly provider: FullCapableProvider;\n /** Author's real account age in days, when the lookup succeeded (#3133). */\n readonly accountAgeDays?: number;\n}\n\nexport interface PRReviewResult {\n /** Pull request number */\n readonly prNumber: number;\n /** Repository full name (owner/repo) */\n readonly repository: string;\n /** Overall decision */\n readonly decision: ReviewDecision;\n /** Executive summary */\n readonly summary: string;\n /** Individual expert reviews */\n readonly expertReviews: readonly ExpertReviewResult[];\n /** Aggregated findings by severity */\n readonly findingsBySeverity: Readonly<Record<ReviewSeverity, number>>;\n /** Aggregated findings by category */\n readonly findingsByCategory: Readonly<Record<ReviewCategory, number>>;\n /** Total execution time in ms */\n readonly totalDurationMs: number;\n /** Number of experts that participated */\n readonly expertCount: number;\n /** Total number of changed files reported by the SCM provider. */\n readonly totalFiles: number;\n /** Number of changed files for which the SCM provider returned a patch. */\n readonly filesWithPatch: number;\n /** Number of file patches supplied to at least one non-errored expert. */\n readonly filesReviewed: number;\n /** Whether the successful expert panel covered all, some, or no changed files. */\n readonly reviewCoverage: 'full' | 'partial' | 'none';\n /** Consensus score (0-1) */\n readonly consensusScore: number;\n /** Debate rounds completed */\n readonly debateRounds: number;\n /** Timestamp of review */\n readonly timestamp: string;\n /** Author trust + reputation assessment (#3123). */\n readonly trustAssessment: PRTrustAssessment;\n /**\n * What actually happened when the review was posted to GitHub (#4354).\n *\n * The review previously reported success whether or not the post landed: a\n * `createReview` rejection was logged and discarded, and a Rule-of-Two block\n * returned early, both leaving the CLI to print \"Review posted to GitHub.\"\n * over a review that does not exist. Callers must consult this rather than\n * inferring a successful post from a successful review.\n */\n readonly postOutcome: ReviewPostOutcome;\n}\n\n/**\n * A completed review before the posting step has run (#4354).\n *\n * Everything the reviewer aggregates is known before the post is attempted; the\n * outcome is stamped on afterwards. Keeping the two apart in the types is what\n * stops `postOutcome` from being defaulted to a hopeful value.\n */\nexport type PRReviewDraft = Omit<PRReviewResult, 'postOutcome'>;\n\n/** Terminal state of the GitHub review-posting step (#4354). */\nexport type ReviewPostOutcome =\n /** The review was created on GitHub. */\n | { readonly status: 'posted' }\n /** Posting was deliberately not attempted (dry-run, or a policy gate blocked it). */\n | { readonly status: 'skipped'; readonly reason: string }\n /** Posting was attempted and GitHub rejected it. */\n | { readonly status: 'failed'; readonly error: string };\n\n/**\n * Configuration for PR review.\n */\nexport interface PRReviewConfig {\n /** Experts to include in review */\n readonly experts: readonly ReviewCategory[];\n /** Maximum debate rounds */\n readonly maxDebateRounds: number;\n /** Consensus threshold (0-1) */\n readonly consensusThreshold: number;\n /** Minimum severity to report */\n readonly minSeverity: ReviewSeverity;\n /** Whether to post inline comments */\n readonly enableInlineComments: boolean;\n /** Whether to run in dry-run mode (no GitHub posting) */\n readonly dryRun: boolean;\n /** Whether to assess author reputation and gate on it (#3123). */\n readonly enableReputation: boolean;\n /** GitHub token for API access */\n readonly githubToken?: string | undefined;\n /** Model adapter configuration */\n readonly modelConfig?: {\n readonly temperature?: number;\n readonly maxTokens?: number;\n };\n}\n\n/**\n * Default PR review configuration.\n */\nexport const DEFAULT_PR_REVIEW_CONFIG: PRReviewConfig = {\n experts: ['security', 'code_quality', 'testing'],\n maxDebateRounds: 3,\n consensusThreshold: 0.7,\n minSeverity: 'low',\n enableInlineComments: true,\n dryRun: false,\n enableReputation: true,\n modelConfig: {\n temperature: 0.3,\n maxTokens: 8192,\n },\n};\n\n/**\n * Zod schema for PR review configuration.\n */\nexport const PRReviewConfigSchema = z.object({\n experts: z\n .array(\n z.enum([\n 'security',\n 'performance',\n 'code_quality',\n 'testing',\n 'documentation',\n 'architecture',\n ])\n )\n .default(['security', 'code_quality', 'testing']),\n maxDebateRounds: z.number().int().min(1).max(10).default(3),\n consensusThreshold: z.number().min(0).max(1).default(0.7),\n minSeverity: z.enum(FINDING_SEVERITY_LEVELS).default('low'),\n enableInlineComments: z.boolean().default(true),\n dryRun: z.boolean().default(false),\n enableReputation: z.boolean().default(true),\n githubToken: z.string().optional(),\n modelConfig: z\n .object({\n temperature: z.number().min(0).max(2).default(0.3),\n maxTokens: z.number().int().positive().default(8192),\n })\n .optional(),\n});\n\n/**\n * Severity order for comparison. INVERTED vs sarif-types' SEVERITY_ORDER by\n * design (higher = more severe here, for descending sort); only the KEY SET is\n * shared. Derived from the canonical {@link FINDING_SEVERITY_LEVELS} so the keys\n * can't drift (#3570): critical→5 … info→1.\n */\nexport const SEVERITY_ORDER: Record<ReviewSeverity, number> = Object.fromEntries(\n FINDING_SEVERITY_LEVELS.map((level, index) => [level, FINDING_SEVERITY_LEVELS.length - index])\n) as Record<ReviewSeverity, number>;\n\n/**\n * Category display names.\n */\nexport const CATEGORY_DISPLAY_NAMES: Record<ReviewCategory, string> = {\n security: 'Security',\n performance: 'Performance',\n code_quality: 'Code Quality',\n testing: 'Testing',\n documentation: 'Documentation',\n architecture: 'Architecture',\n};\n\n/**\n * Severity emoji for GitHub comments.\n */\nexport const SEVERITY_EMOJI: Record<ReviewSeverity, string> = {\n critical: ':rotating_light:',\n high: ':warning:',\n medium: ':yellow_circle:',\n low: ':large_blue_circle:',\n info: ':information_source:',\n};\n\n/**\n * Decision emoji for GitHub comments.\n */\nexport const DECISION_EMOJI: Record<ReviewDecision, string> = {\n approve: ':white_check_mark:',\n request_changes: ':x:',\n comment: ':speech_balloon:',\n};\n","/**\n * SARIF Types and Security Finding Schema (#1682)\n *\n * Types for parsing SARIF (Static Analysis Results Interchange Format)\n * output from security scanners (Semgrep, CodeQL, Bandit, ESLint).\n * Normalizes findings into a unified schema for MCP tool consumption.\n *\n * @module security/sarif-types\n * (Source: Issue #1681, #1682 — Proactive Defensive Security)\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Unified Security Finding Schema\n// ============================================================================\n\n/**\n * Canonical 5-value finding-severity vocabulary (CVSS-aligned), most→least\n * severe. THE single source of truth — every 5-value finding-severity zod enum\n * (severity-consensus, finding-triage, agents/output-schemas, expert-types\n * VulnerabilitySeverity) and both SEVERITY_ORDER maps derive from this (#3570).\n * Tuple order is authoritative: SEVERITY_ORDER below maps it to ascending ranks.\n */\nexport const FINDING_SEVERITY_LEVELS = ['critical', 'high', 'medium', 'low', 'info'] as const;\n\n/** Severity levels aligned with CVSS and common scanner output. */\nexport const FindingSeveritySchema = z.enum(FINDING_SEVERITY_LEVELS);\nexport type FindingSeverity = z.infer<typeof FindingSeveritySchema>;\n\n/** A normalized security finding from any SARIF-compatible scanner. */\nexport const SecurityFindingSchema = z.object({\n /** Unique finding ID (scanner-specific rule ID). */\n id: z.string().min(1),\n /** Scanner that produced this finding. */\n scanner: z.string().min(1),\n /** Rule identifier (e.g., 'javascript.lang.security.detect-eval'). */\n rule: z.string().min(1),\n /** Normalized severity. */\n severity: FindingSeveritySchema,\n /** Human-readable description of the finding. */\n message: z.string().min(1).max(2000),\n /** File path where the finding was detected. */\n file: z.string().min(1),\n /** Start line number (1-based). */\n startLine: z.number().int().min(1),\n /** End line number (1-based, optional). */\n endLine: z.number().int().min(1).optional(),\n /** CWE identifiers (e.g., ['CWE-79', 'CWE-89']). */\n cweIds: z.array(z.string()).default([]),\n /** Scanner confidence (0-1). */\n confidence: z.number().min(0).max(1).default(0.5),\n /** Code snippet around the finding (optional). */\n snippet: z.string().max(500).optional(),\n /** Help URL for remediation guidance. */\n helpUrl: z.string().optional(),\n});\n\nexport type SecurityFinding = z.infer<typeof SecurityFindingSchema>;\n\n/** Result of parsing a SARIF file. */\nexport interface SarifParseResult {\n /** Scanner name extracted from SARIF. */\n readonly scanner: string;\n /** Total findings parsed. */\n readonly totalFindings: number;\n /** Findings sorted by severity (critical first). */\n readonly findings: readonly SecurityFinding[];\n /** Parsing errors (non-fatal). */\n readonly errors: readonly string[];\n}\n\n// ============================================================================\n// SARIF Input Types (subset of the SARIF 2.1.0 spec we need)\n// ============================================================================\n\n/** SARIF result level → our severity mapping. */\nexport const SARIF_LEVEL_MAP: Readonly<Record<string, FindingSeverity>> = {\n error: 'high',\n warning: 'medium',\n note: 'low',\n none: 'info',\n};\n\n/**\n * Severity order for sorting (lower = more severe). Derived from the canonical\n * tuple so it can never drift from {@link FINDING_SEVERITY_LEVELS} (#3570).\n */\nexport const SEVERITY_ORDER: Readonly<Record<FindingSeverity, number>> = Object.fromEntries(\n FINDING_SEVERITY_LEVELS.map((level, index) => [level, index])\n) as Record<FindingSeverity, number>;\n"],"mappings":"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","names":["z","z","SEVERITY_ORDER"]}
|
|
@@ -23,10 +23,10 @@ import {
|
|
|
23
23
|
toolSuccessStructured,
|
|
24
24
|
withProgressHeartbeat,
|
|
25
25
|
wrapToolWithTimeout
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-FZXMMOBQ.js";
|
|
27
27
|
import {
|
|
28
28
|
VERSION
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-AWFW6FD4.js";
|
|
30
30
|
import {
|
|
31
31
|
assessPanelIndependence,
|
|
32
32
|
countDistinctModels,
|
|
@@ -7205,4 +7205,4 @@ export {
|
|
|
7205
7205
|
CONSENSUS_VOTE_TOOL_SCHEMA,
|
|
7206
7206
|
registerConsensusVoteTool
|
|
7207
7207
|
};
|
|
7208
|
-
//# sourceMappingURL=chunk-
|
|
7208
|
+
//# sourceMappingURL=chunk-ASUB4LSV.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VERSION
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AWFW6FD4.js";
|
|
4
4
|
import {
|
|
5
5
|
emitClawGuardViolation
|
|
6
6
|
} from "./chunk-TCTKOFNL.js";
|
|
@@ -2246,4 +2246,4 @@ export {
|
|
|
2246
2246
|
VOTING_THRESHOLDS,
|
|
2247
2247
|
ConsensusMetricsSchema
|
|
2248
2248
|
};
|
|
2249
|
-
//# sourceMappingURL=chunk-
|
|
2249
|
+
//# sourceMappingURL=chunk-FZXMMOBQ.js.map
|
|
@@ -17,11 +17,11 @@ import {
|
|
|
17
17
|
FINDING_SEVERITY_LEVELS,
|
|
18
18
|
SARIF_LEVEL_MAP,
|
|
19
19
|
SEVERITY_ORDER
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-2G2ZXAD7.js";
|
|
21
21
|
import {
|
|
22
22
|
DEFAULT_TASK_TTL_MS,
|
|
23
23
|
clampTaskTtl
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-XSRCJ7FA.js";
|
|
25
25
|
import {
|
|
26
26
|
executeExpert
|
|
27
27
|
} from "./chunk-C7CSLODO.js";
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
simulationDeniedResult,
|
|
49
49
|
toJobSummary,
|
|
50
50
|
writeJobCancelled
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-ASUB4LSV.js";
|
|
52
52
|
import {
|
|
53
53
|
allOf
|
|
54
54
|
} from "./chunk-OQB3XC5O.js";
|
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
} from "./chunk-ZUK5BG3Q.js";
|
|
68
68
|
import {
|
|
69
69
|
withPrerequisite
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-W5M6VFDH.js";
|
|
71
71
|
import {
|
|
72
72
|
NOOP_NOTIFIER,
|
|
73
73
|
RateLimiter,
|
|
@@ -92,7 +92,7 @@ import {
|
|
|
92
92
|
withAuditTrail,
|
|
93
93
|
withProgressHeartbeat,
|
|
94
94
|
wrapToolWithTimeout
|
|
95
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-FZXMMOBQ.js";
|
|
96
96
|
import {
|
|
97
97
|
createAuditTrail,
|
|
98
98
|
createGraphAuditBridge,
|
|
@@ -45808,6 +45808,149 @@ function checkpointToResult(state) {
|
|
|
45808
45808
|
return result;
|
|
45809
45809
|
}
|
|
45810
45810
|
|
|
45811
|
+
// src/pipeline/iterative-consensus.ts
|
|
45812
|
+
var defaultLogger3 = createLogger({ component: "iterative-consensus" });
|
|
45813
|
+
var DEFAULT_MAX_ITERATIONS = 3;
|
|
45814
|
+
var DEFAULT_MAX_NO_QUORUM_RETRIES = 2;
|
|
45815
|
+
var DEFAULT_MAX_PROPOSAL_LENGTH = 4e3;
|
|
45816
|
+
var DEFAULT_STRATEGY = "higher_order";
|
|
45817
|
+
var DEFAULT_PREFIX = "pipeline";
|
|
45818
|
+
async function voteWithQuorumRecovery(state) {
|
|
45819
|
+
const outcome = await retryNoQuorumVote(
|
|
45820
|
+
() => executeSingleVote(state.plan, state.config, state.log),
|
|
45821
|
+
state.maxNoQuorumRetries,
|
|
45822
|
+
(attempt, vote) => {
|
|
45823
|
+
state.log.warn("Vote reached no_quorum \u2014 re-running the missing voice (bounded)", {
|
|
45824
|
+
attempt,
|
|
45825
|
+
maxNoQuorumRetries: state.maxNoQuorumRetries,
|
|
45826
|
+
reason: vote.reason
|
|
45827
|
+
});
|
|
45828
|
+
emitPipelineStageEvent(state.prefix, "vote", "started");
|
|
45829
|
+
}
|
|
45830
|
+
);
|
|
45831
|
+
return outcome.vote;
|
|
45832
|
+
}
|
|
45833
|
+
async function retryNoQuorumVote(executeVote, maxRetries = DEFAULT_MAX_NO_QUORUM_RETRIES, onRetry) {
|
|
45834
|
+
let vote = await executeVote();
|
|
45835
|
+
let retries = 0;
|
|
45836
|
+
while (vote.kind === "no_quorum" && retries < maxRetries) {
|
|
45837
|
+
retries++;
|
|
45838
|
+
onRetry?.(retries, vote);
|
|
45839
|
+
vote = await executeVote();
|
|
45840
|
+
}
|
|
45841
|
+
return { vote, retries };
|
|
45842
|
+
}
|
|
45843
|
+
async function runOneIteration(state, iteration) {
|
|
45844
|
+
state.log.info("Consensus iteration", { iteration });
|
|
45845
|
+
emitPipelineStageEvent(state.prefix, "vote", "started");
|
|
45846
|
+
state.lastVote = await voteWithQuorumRecovery(state);
|
|
45847
|
+
const iterMs = getTimeProvider().now() - state.globalStart;
|
|
45848
|
+
const accepted = isVoteAccepted(state.lastVote);
|
|
45849
|
+
emitPipelineStageEvent(state.prefix, "vote", accepted ? "completed" : "failed", {
|
|
45850
|
+
durationMs: iterMs
|
|
45851
|
+
});
|
|
45852
|
+
if (accepted) {
|
|
45853
|
+
return { result: { vote: state.lastVote, iterations: iteration, durationMs: iterMs } };
|
|
45854
|
+
}
|
|
45855
|
+
if (state.lastVote.kind === "no_quorum") {
|
|
45856
|
+
const terminalVote = {
|
|
45857
|
+
kind: "no_quorum",
|
|
45858
|
+
reason: `vote could not reach quorum after ${String(state.maxNoQuorumRetries)} re-run(s): ${state.lastVote.reason}`,
|
|
45859
|
+
approvalPercentage: state.lastVote.approvalPercentage
|
|
45860
|
+
};
|
|
45861
|
+
return { terminal: { vote: terminalVote, iterations: iteration, durationMs: iterMs } };
|
|
45862
|
+
}
|
|
45863
|
+
return {};
|
|
45864
|
+
}
|
|
45865
|
+
async function runIterativeConsensus(initialPlan, revisePlan, config) {
|
|
45866
|
+
const maxIter = config?.maxIterations ?? DEFAULT_MAX_ITERATIONS;
|
|
45867
|
+
const state = {
|
|
45868
|
+
plan: initialPlan,
|
|
45869
|
+
lastVote: void 0,
|
|
45870
|
+
config,
|
|
45871
|
+
log: config?.logger ?? defaultLogger3,
|
|
45872
|
+
prefix: config?.pipelinePrefix ?? DEFAULT_PREFIX,
|
|
45873
|
+
globalStart: getTimeProvider().now(),
|
|
45874
|
+
maxNoQuorumRetries: config?.maxNoQuorumRetries ?? DEFAULT_MAX_NO_QUORUM_RETRIES
|
|
45875
|
+
};
|
|
45876
|
+
return runConsensusLoop(state, maxIter, revisePlan);
|
|
45877
|
+
}
|
|
45878
|
+
async function runConsensusLoop(state, maxIter, revisePlan) {
|
|
45879
|
+
for (let i = 0; i < maxIter; i++) {
|
|
45880
|
+
const outcome = await runOneIteration(state, i + 1);
|
|
45881
|
+
const done = outcome.result ?? outcome.terminal;
|
|
45882
|
+
if (done !== void 0) return done;
|
|
45883
|
+
await maybeRevise(state, i, maxIter, revisePlan);
|
|
45884
|
+
}
|
|
45885
|
+
return buildExhaustedResult(state, maxIter);
|
|
45886
|
+
}
|
|
45887
|
+
function isVoteAccepted(vote) {
|
|
45888
|
+
return vote.kind === "approved" || vote.kind === "conditional_go";
|
|
45889
|
+
}
|
|
45890
|
+
function extractFeedback2(vote) {
|
|
45891
|
+
if (vote === void 0) return "";
|
|
45892
|
+
return vote.kind === "rejected" ? vote.feedback : "";
|
|
45893
|
+
}
|
|
45894
|
+
async function maybeRevise(state, iteration, maxIter, revisePlan) {
|
|
45895
|
+
if (iteration >= maxIter - 1) return;
|
|
45896
|
+
state.log.info("Vote rejected, revising plan", { iteration: iteration + 1 });
|
|
45897
|
+
state.plan = await revisePlan(state.plan, extractFeedback2(state.lastVote));
|
|
45898
|
+
}
|
|
45899
|
+
function buildExhaustedResult(state, maxIter) {
|
|
45900
|
+
const totalMs = getTimeProvider().now() - state.globalStart;
|
|
45901
|
+
const fallback = {
|
|
45902
|
+
kind: "rejected",
|
|
45903
|
+
feedback: "No votes executed",
|
|
45904
|
+
approvalPercentage: 0
|
|
45905
|
+
};
|
|
45906
|
+
return { vote: state.lastVote ?? fallback, iterations: maxIter, durationMs: totalMs };
|
|
45907
|
+
}
|
|
45908
|
+
function buildVotingInput(plan, config) {
|
|
45909
|
+
const c = config ?? {};
|
|
45910
|
+
const maxLen = c.maxProposalLength ?? DEFAULT_MAX_PROPOSAL_LENGTH;
|
|
45911
|
+
return {
|
|
45912
|
+
proposal: plan.slice(0, maxLen),
|
|
45913
|
+
strategy: c.strategy ?? DEFAULT_STRATEGY,
|
|
45914
|
+
simulateVotes: c.simulateVotes ?? false,
|
|
45915
|
+
quickMode: c.quickMode ?? false,
|
|
45916
|
+
// #4138: this reusable helper opts into absolute_quorum by default.
|
|
45917
|
+
errorPolicy: c.errorPolicy ?? "absolute_quorum"
|
|
45918
|
+
};
|
|
45919
|
+
}
|
|
45920
|
+
async function executeSingleVote(plan, config, log) {
|
|
45921
|
+
try {
|
|
45922
|
+
const { executeVoting } = await import("./consensus-vote-X4XXWGDD.js");
|
|
45923
|
+
const input = buildVotingInput(plan, config);
|
|
45924
|
+
const result = await executeVoting(input, log);
|
|
45925
|
+
return parseVotingResult(result);
|
|
45926
|
+
} catch (error) {
|
|
45927
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
45928
|
+
log.warn("Vote execution failed, treating as rejected", { error: msg });
|
|
45929
|
+
return {
|
|
45930
|
+
kind: "rejected",
|
|
45931
|
+
feedback: `Vote infrastructure failed \u2014 no consensus produced: ${msg}`,
|
|
45932
|
+
approvalPercentage: 0
|
|
45933
|
+
};
|
|
45934
|
+
}
|
|
45935
|
+
}
|
|
45936
|
+
function parseVotingResult(result) {
|
|
45937
|
+
const total = Math.max(1, result.result.voteCounts.approve + result.result.voteCounts.reject);
|
|
45938
|
+
const pct = result.result.voteCounts.approve / total * 100;
|
|
45939
|
+
const decision = result.decision ?? (result.result.outcome === "approved" ? "approved" : "rejected");
|
|
45940
|
+
if (decision === "approved") {
|
|
45941
|
+
return { kind: "approved", approvalPercentage: pct };
|
|
45942
|
+
}
|
|
45943
|
+
if (decision === "no_quorum") {
|
|
45944
|
+
return {
|
|
45945
|
+
kind: "no_quorum",
|
|
45946
|
+
reason: "vote could not reach quorum (a voice was missing)",
|
|
45947
|
+
approvalPercentage: pct
|
|
45948
|
+
};
|
|
45949
|
+
}
|
|
45950
|
+
const feedback = result.votes.filter((v) => v.vote.decision !== "approve").map((v) => v.vote.reasoning).join("\n");
|
|
45951
|
+
return { kind: "rejected", feedback, approvalPercentage: pct };
|
|
45952
|
+
}
|
|
45953
|
+
|
|
45811
45954
|
// src/orchestration/qa-loop.ts
|
|
45812
45955
|
var logger40 = createLogger({ component: "qa-loop" });
|
|
45813
45956
|
var DEFAULT_MAX_QA_ITERATIONS = 3;
|
|
@@ -45882,6 +46025,11 @@ async function runDevPipelineInner(task, stages, options, sid, prior) {
|
|
|
45882
46025
|
logger41.info("Dry run \u2014 stopping after plan+vote");
|
|
45883
46026
|
return buildDryRunResult(planResult);
|
|
45884
46027
|
}
|
|
46028
|
+
if (planResult.planStatus !== void 0) {
|
|
46029
|
+
const result2 = buildPlanFailureResult(planResult);
|
|
46030
|
+
applyPipelineHindsight(bm, task, sid, result2);
|
|
46031
|
+
return result2;
|
|
46032
|
+
}
|
|
45885
46033
|
enforceConsensusExecutePolicy(sid, trustTier, auditLogger);
|
|
45886
46034
|
const tasks = await runOrResumeDecompose(prior, planResult.plan, stages, {
|
|
45887
46035
|
conditional: planResult.conditional,
|
|
@@ -46083,7 +46231,25 @@ function buildDryRunResult(planResult) {
|
|
|
46083
46231
|
// "the security gate rejected this"; `securityRan: false` says it never ran.
|
|
46084
46232
|
securityPassed: false,
|
|
46085
46233
|
securityRan: false,
|
|
46086
|
-
...planResult.
|
|
46234
|
+
...planResult.planStatus !== void 0 ? { planStatus: planResult.planStatus } : {},
|
|
46235
|
+
...planResult.planVoteReason !== void 0 ? { planVoteReason: planResult.planVoteReason } : {},
|
|
46236
|
+
...planResult.planVoteApprovalPercentage !== void 0 ? { planVoteApprovalPercentage: planResult.planVoteApprovalPercentage } : {},
|
|
46237
|
+
...planResult.planVoteFeedback !== void 0 ? { planVoteFeedback: planResult.planVoteFeedback } : {}
|
|
46238
|
+
};
|
|
46239
|
+
}
|
|
46240
|
+
function buildPlanFailureResult(planResult) {
|
|
46241
|
+
return {
|
|
46242
|
+
completed: false,
|
|
46243
|
+
plan: planResult.plan,
|
|
46244
|
+
tasks: [],
|
|
46245
|
+
voteIterations: planResult.iterations,
|
|
46246
|
+
qaIterations: 0,
|
|
46247
|
+
securityPassed: false,
|
|
46248
|
+
securityRan: false,
|
|
46249
|
+
planStatus: planResult.planStatus ?? "unapproved",
|
|
46250
|
+
...planResult.planVoteReason !== void 0 ? { planVoteReason: planResult.planVoteReason } : {},
|
|
46251
|
+
...planResult.planVoteApprovalPercentage !== void 0 ? { planVoteApprovalPercentage: planResult.planVoteApprovalPercentage } : {},
|
|
46252
|
+
...planResult.planVoteFeedback !== void 0 ? { planVoteFeedback: planResult.planVoteFeedback } : {}
|
|
46087
46253
|
};
|
|
46088
46254
|
}
|
|
46089
46255
|
async function resolveResearch(prior, task, stages, options) {
|
|
@@ -46115,7 +46281,7 @@ async function runPlanningPhase(task, stages, prior, options) {
|
|
|
46115
46281
|
sid,
|
|
46116
46282
|
limits: resolveIterationLimits(options)
|
|
46117
46283
|
});
|
|
46118
|
-
if (sid !== void 0) {
|
|
46284
|
+
if (sid !== void 0 && planResult.planStatus === void 0) {
|
|
46119
46285
|
saveStageCheckpoint(sid, "plan", {
|
|
46120
46286
|
type: "plan",
|
|
46121
46287
|
text: planResult.plan,
|
|
@@ -46123,7 +46289,7 @@ async function runPlanningPhase(task, stages, prior, options) {
|
|
|
46123
46289
|
});
|
|
46124
46290
|
saveStageCheckpoint(sid, "vote", {
|
|
46125
46291
|
type: "vote",
|
|
46126
|
-
approved:
|
|
46292
|
+
approved: true,
|
|
46127
46293
|
conditional: planResult.conditional,
|
|
46128
46294
|
conditions: planResult.conditions,
|
|
46129
46295
|
caveats: planResult.caveats,
|
|
@@ -46239,6 +46405,7 @@ function extractConditionalMeta(vote) {
|
|
|
46239
46405
|
async function planVoteLoop(task, research, stages, sessionId, limits) {
|
|
46240
46406
|
let feedback;
|
|
46241
46407
|
let plan = "";
|
|
46408
|
+
let lastRejected;
|
|
46242
46409
|
for (let i = 1; i <= limits.vote; i++) {
|
|
46243
46410
|
plan = await withStep(
|
|
46244
46411
|
{ name: `plan (i=${String(i)})`, attrs: { iteration: i } },
|
|
@@ -46246,37 +46413,100 @@ async function planVoteLoop(task, research, stages, sessionId, limits) {
|
|
|
46246
46413
|
);
|
|
46247
46414
|
if (plan.trim() === "") {
|
|
46248
46415
|
logger41.warn("Planner returned no plan \u2014 stopping before vote", { iteration: i, sessionId });
|
|
46249
|
-
return {
|
|
46250
|
-
|
|
46251
|
-
|
|
46252
|
-
|
|
46253
|
-
|
|
46254
|
-
|
|
46255
|
-
|
|
46256
|
-
|
|
46257
|
-
|
|
46258
|
-
|
|
46416
|
+
return {
|
|
46417
|
+
plan: "",
|
|
46418
|
+
iterations: i,
|
|
46419
|
+
conditional: false,
|
|
46420
|
+
conditions: [],
|
|
46421
|
+
caveats: [],
|
|
46422
|
+
planStatus: "empty"
|
|
46423
|
+
};
|
|
46424
|
+
}
|
|
46425
|
+
const voteOutcome = await retryNoQuorumVote(
|
|
46426
|
+
() => runPlanVote(plan, research, stages, i),
|
|
46427
|
+
DEFAULT_MAX_NO_QUORUM_RETRIES,
|
|
46428
|
+
(attempt, vote2) => {
|
|
46429
|
+
logQuorumRetry(attempt, vote2, sessionId);
|
|
46259
46430
|
}
|
|
46260
46431
|
);
|
|
46261
|
-
|
|
46262
|
-
|
|
46263
|
-
|
|
46264
|
-
|
|
46265
|
-
|
|
46266
|
-
|
|
46267
|
-
...meta
|
|
46268
|
-
});
|
|
46269
|
-
return { plan, iterations: i, ...meta };
|
|
46432
|
+
const vote = voteOutcome.vote;
|
|
46433
|
+
if (vote.kind === "approved" || vote.kind === "conditional_go") {
|
|
46434
|
+
return buildApprovedPlanResult(plan, i, vote, sessionId);
|
|
46435
|
+
}
|
|
46436
|
+
if (vote.kind === "no_quorum") {
|
|
46437
|
+
return buildNoQuorumPlanResult(plan, i, vote, voteOutcome.retries);
|
|
46270
46438
|
}
|
|
46271
|
-
|
|
46439
|
+
lastRejected = vote;
|
|
46440
|
+
feedback = vote.feedback;
|
|
46272
46441
|
logger41.warn("Plan rejected, iterating", {
|
|
46273
46442
|
iteration: i,
|
|
46274
46443
|
feedback: feedback.slice(0, 200),
|
|
46275
46444
|
sessionId
|
|
46276
46445
|
});
|
|
46277
46446
|
}
|
|
46278
|
-
|
|
46279
|
-
|
|
46447
|
+
return buildUnapprovedPlanResult(plan, limits.vote, lastRejected, sessionId);
|
|
46448
|
+
}
|
|
46449
|
+
function buildApprovedPlanResult(plan, iterations, vote, sessionId) {
|
|
46450
|
+
const meta = extractConditionalMeta(vote);
|
|
46451
|
+
logger41.info("Plan approved", {
|
|
46452
|
+
iteration: iterations,
|
|
46453
|
+
approval: vote.approvalPercentage,
|
|
46454
|
+
sessionId,
|
|
46455
|
+
...meta
|
|
46456
|
+
});
|
|
46457
|
+
return { plan, iterations, ...meta };
|
|
46458
|
+
}
|
|
46459
|
+
async function runPlanVote(plan, research, stages, iteration) {
|
|
46460
|
+
return withStep({ name: `vote (i=${String(iteration)})`, attrs: { iteration } }, async (ctx) => {
|
|
46461
|
+
const result = await stages.vote(plan, research);
|
|
46462
|
+
const label = result.kind === "no_quorum" ? "no_quorum" : isApproved(result) ? "approved" : "rejected";
|
|
46463
|
+
ctx.setSummary(`${String(Math.round(result.approvalPercentage))}% ${label}`);
|
|
46464
|
+
return result;
|
|
46465
|
+
});
|
|
46466
|
+
}
|
|
46467
|
+
function logQuorumRetry(attempt, vote, sessionId) {
|
|
46468
|
+
logger41.warn("Plan vote reached no_quorum \u2014 re-running the same plan", {
|
|
46469
|
+
attempt,
|
|
46470
|
+
maxNoQuorumRetries: DEFAULT_MAX_NO_QUORUM_RETRIES,
|
|
46471
|
+
reason: vote.reason,
|
|
46472
|
+
sessionId
|
|
46473
|
+
});
|
|
46474
|
+
}
|
|
46475
|
+
function buildNoQuorumPlanResult(plan, iterations, vote, retries) {
|
|
46476
|
+
logger41.warn("Plan vote could not reach quorum \u2014 stopping", {
|
|
46477
|
+
retries,
|
|
46478
|
+
reason: vote.reason
|
|
46479
|
+
});
|
|
46480
|
+
return {
|
|
46481
|
+
plan,
|
|
46482
|
+
iterations,
|
|
46483
|
+
conditional: false,
|
|
46484
|
+
conditions: [],
|
|
46485
|
+
caveats: [],
|
|
46486
|
+
planStatus: "no_quorum",
|
|
46487
|
+
planVoteReason: vote.reason,
|
|
46488
|
+
planVoteApprovalPercentage: vote.approvalPercentage
|
|
46489
|
+
};
|
|
46490
|
+
}
|
|
46491
|
+
function buildUnapprovedPlanResult(plan, iterations, vote, sessionId) {
|
|
46492
|
+
const feedback = vote?.feedback ?? "No plan vote was run";
|
|
46493
|
+
const approvalPercentage = vote?.approvalPercentage ?? 0;
|
|
46494
|
+
logger41.warn("Max vote iterations reached without plan approval \u2014 stopping", {
|
|
46495
|
+
sessionId,
|
|
46496
|
+
iterations,
|
|
46497
|
+
approvalPercentage,
|
|
46498
|
+
feedback: feedback.slice(0, 200)
|
|
46499
|
+
});
|
|
46500
|
+
return {
|
|
46501
|
+
plan,
|
|
46502
|
+
iterations,
|
|
46503
|
+
conditional: false,
|
|
46504
|
+
conditions: [],
|
|
46505
|
+
caveats: [],
|
|
46506
|
+
planStatus: "unapproved",
|
|
46507
|
+
planVoteApprovalPercentage: approvalPercentage,
|
|
46508
|
+
planVoteFeedback: feedback
|
|
46509
|
+
};
|
|
46280
46510
|
}
|
|
46281
46511
|
async function implementSingleTask(task, stages, limits) {
|
|
46282
46512
|
let currentTask = { ...task, status: "in_progress" };
|
|
@@ -47461,13 +47691,15 @@ ${contextBlock}`;
|
|
|
47461
47691
|
const strategy = config.votingStrategy ?? "higher_order";
|
|
47462
47692
|
await postProgress(config, "Vote", `Running consensus with ${strategy} strategy...`);
|
|
47463
47693
|
try {
|
|
47464
|
-
const { executeVoting } = await import("./consensus-vote-
|
|
47694
|
+
const { executeVoting } = await import("./consensus-vote-X4XXWGDD.js");
|
|
47465
47695
|
const votingResult = await executeVoting(
|
|
47466
47696
|
{
|
|
47467
47697
|
proposal: buildVoteProposal(plan, research),
|
|
47468
47698
|
strategy,
|
|
47469
47699
|
simulateVotes: config.simulateVotes ?? false,
|
|
47470
|
-
quickMode: config.quickMode ?? false
|
|
47700
|
+
quickMode: config.quickMode ?? false,
|
|
47701
|
+
// #5506: plan approval requires the requested panel, not only survivors.
|
|
47702
|
+
errorPolicy: "absolute_quorum"
|
|
47471
47703
|
},
|
|
47472
47704
|
logger45
|
|
47473
47705
|
);
|
|
@@ -50439,6 +50671,37 @@ function classifyDispatchError(err2) {
|
|
|
50439
50671
|
return err2 instanceof MetaDispatchError && err2.code === "no_executor" ? "business" : "internal";
|
|
50440
50672
|
}
|
|
50441
50673
|
|
|
50674
|
+
// src/mcp/tools/run-tool-incomplete.ts
|
|
50675
|
+
var FAILURE_PREFIX = "Engine reported failure:";
|
|
50676
|
+
function describePlanFailure(record) {
|
|
50677
|
+
if (record["planStatus"] === "empty") {
|
|
50678
|
+
return `${FAILURE_PREFIX} the planner returned no plan, so nothing was built`;
|
|
50679
|
+
}
|
|
50680
|
+
if (record["planStatus"] === "unapproved") {
|
|
50681
|
+
const iterations = typeof record["voteIterations"] === "number" ? String(record["voteIterations"]) : "an unknown number of";
|
|
50682
|
+
return `${FAILURE_PREFIX} the panel did not approve the plan after ${iterations} iterations`;
|
|
50683
|
+
}
|
|
50684
|
+
if (record["planStatus"] === "no_quorum") {
|
|
50685
|
+
const reason = typeof record["planVoteReason"] === "string" ? record["planVoteReason"] : "no reason was recorded";
|
|
50686
|
+
return `${FAILURE_PREFIX} the plan vote could not reach quorum: ${reason}`;
|
|
50687
|
+
}
|
|
50688
|
+
return void 0;
|
|
50689
|
+
}
|
|
50690
|
+
function describeIncompletePipeline(record) {
|
|
50691
|
+
const planFailure = describePlanFailure(record);
|
|
50692
|
+
if (planFailure !== void 0) return planFailure;
|
|
50693
|
+
if (record["securityRan"] === true) {
|
|
50694
|
+
return `${FAILURE_PREFIX} the security gate rejected the change`;
|
|
50695
|
+
}
|
|
50696
|
+
if (record["securityRan"] === false) {
|
|
50697
|
+
if (typeof record["securityNote"] === "string") {
|
|
50698
|
+
return `${FAILURE_PREFIX} the security scan did not run (${record["securityNote"]}); the change is blocked until it does`;
|
|
50699
|
+
}
|
|
50700
|
+
return `${FAILURE_PREFIX} the run stopped before the security gate, which never ran`;
|
|
50701
|
+
}
|
|
50702
|
+
return `${FAILURE_PREFIX} the dev pipeline did not complete`;
|
|
50703
|
+
}
|
|
50704
|
+
|
|
50442
50705
|
// src/orchestration/meta-orchestrator.ts
|
|
50443
50706
|
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
50444
50707
|
|
|
@@ -51395,6 +51658,9 @@ function buildStructuredOutput(result, simulated) {
|
|
|
51395
51658
|
// here, so they never reached the MCP surface.
|
|
51396
51659
|
...result.securityRan !== void 0 ? { securityRan: result.securityRan } : {},
|
|
51397
51660
|
...result.planStatus !== void 0 ? { planStatus: result.planStatus } : {},
|
|
51661
|
+
...result.planVoteReason !== void 0 ? { planVoteReason: result.planVoteReason } : {},
|
|
51662
|
+
...result.planVoteApprovalPercentage !== void 0 ? { planVoteApprovalPercentage: result.planVoteApprovalPercentage } : {},
|
|
51663
|
+
...result.planVoteFeedback !== void 0 ? { planVoteFeedback: result.planVoteFeedback } : {},
|
|
51398
51664
|
// #4993 added `dryRun` to DevPipelineResult for exactly the reason above —
|
|
51399
51665
|
// it says `completed: false` was the request, not a fault — and then did
|
|
51400
51666
|
// not list it here either. Same omission, same function, under the comment
|
|
@@ -51895,27 +52161,11 @@ function detectEngineFailure(result) {
|
|
|
51895
52161
|
return { message: `Engine reported failure: ${detail}` };
|
|
51896
52162
|
}
|
|
51897
52163
|
if (record["completed"] === false) {
|
|
51898
|
-
if (record["dryRun"] === true && record["planStatus"]
|
|
52164
|
+
if (record["dryRun"] === true && record["planStatus"] === void 0) return null;
|
|
51899
52165
|
return { message: describeIncompletePipeline(record), detail: record };
|
|
51900
52166
|
}
|
|
51901
52167
|
return null;
|
|
51902
52168
|
}
|
|
51903
|
-
function describeIncompletePipeline(record) {
|
|
51904
|
-
const prefix = "Engine reported failure:";
|
|
51905
|
-
if (record["planStatus"] === "empty") {
|
|
51906
|
-
return `${prefix} the planner returned no plan, so nothing was built`;
|
|
51907
|
-
}
|
|
51908
|
-
if (record["securityRan"] === true) {
|
|
51909
|
-
return `${prefix} the security gate rejected the change`;
|
|
51910
|
-
}
|
|
51911
|
-
if (record["securityRan"] === false) {
|
|
51912
|
-
if (typeof record["securityNote"] === "string") {
|
|
51913
|
-
return `${prefix} the security scan did not run (${record["securityNote"]}); the change is blocked until it does`;
|
|
51914
|
-
}
|
|
51915
|
-
return `${prefix} the run stopped before the security gate, which never ran`;
|
|
51916
|
-
}
|
|
51917
|
-
return `${prefix} the dev pipeline did not complete`;
|
|
51918
|
-
}
|
|
51919
52169
|
async function executeRunBody(input, logger57, trustTier, gatewayAdapters) {
|
|
51920
52170
|
try {
|
|
51921
52171
|
const exec2 = await executeGoal(input, {
|
|
@@ -56074,6 +56324,7 @@ export {
|
|
|
56074
56324
|
loadCheckpointState,
|
|
56075
56325
|
cleanupCheckpoint2 as cleanupCheckpoint,
|
|
56076
56326
|
checkpointToResult,
|
|
56327
|
+
runIterativeConsensus,
|
|
56077
56328
|
runDevPipeline,
|
|
56078
56329
|
flushPipelineMemory,
|
|
56079
56330
|
createAgentStages,
|
|
@@ -56125,4 +56376,4 @@ export {
|
|
|
56125
56376
|
shutdownFeedbackSubscriber,
|
|
56126
56377
|
createEventBusBridge
|
|
56127
56378
|
};
|
|
56128
|
-
//# sourceMappingURL=chunk-
|
|
56379
|
+
//# sourceMappingURL=chunk-PIWFHJSU.js.map
|