infraweaver 0.1.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/LICENSE +661 -0
- package/README.md +244 -0
- package/dist/agents/claude.d.ts +113 -0
- package/dist/agents/claudePretoolGate.d.ts +137 -0
- package/dist/agents/dispatchMetrics.d.ts +77 -0
- package/dist/agents/gateServer.d.ts +7 -0
- package/dist/agents/index.d.ts +6 -0
- package/dist/agents/nativeFsDenies.d.ts +46 -0
- package/dist/agents/opencode.d.ts +284 -0
- package/dist/agents/opencodePlugin.d.ts +96 -0
- package/dist/agents/opencodeShared.d.ts +40 -0
- package/dist/agents/postRun.d.ts +126 -0
- package/dist/agents/reviewer.d.ts +41 -0
- package/dist/agents/sessionLabeler.d.ts +97 -0
- package/dist/agents/shared.d.ts +246 -0
- package/dist/agents/subagentModels.d.ts +19 -0
- package/dist/agents/tokenQuota.d.ts +118 -0
- package/dist/agents/writeGateSource.d.ts +22 -0
- package/dist/agents/writePolicy.d.ts +79 -0
- package/dist/brand.d.ts +67 -0
- package/dist/cli.mjs +247846 -0
- package/dist/external.d.ts +227 -0
- package/dist/i18n/scaffolding.d.ts +59 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +247061 -0
- package/dist/internal/index.d.ts +18 -0
- package/dist/internal.js +2398 -0
- package/dist/lifecycle.d.ts +2 -0
- package/dist/main.d.ts +8 -0
- package/dist/mcp/arkConfig.d.ts +1 -0
- package/dist/mcp/assess.d.ts +157 -0
- package/dist/mcp/capabilityContext.d.ts +71 -0
- package/dist/mcp/changeSummary.d.ts +52 -0
- package/dist/mcp/checkSuite.d.ts +27 -0
- package/dist/mcp/checkout.d.ts +92 -0
- package/dist/mcp/comment.d.ts +127 -0
- package/dist/mcp/commitInfo.d.ts +11 -0
- package/dist/mcp/crosswalk.d.ts +178 -0
- package/dist/mcp/crosswalkDigest.d.ts +1 -0
- package/dist/mcp/cyberEssentials.d.ts +24 -0
- package/dist/mcp/dashboard.d.ts +125 -0
- package/dist/mcp/dependencies.d.ts +12 -0
- package/dist/mcp/frameworks.d.ts +74 -0
- package/dist/mcp/geminiSanitizer.d.ts +28 -0
- package/dist/mcp/git.d.ts +60 -0
- package/dist/mcp/guardrails.d.ts +222 -0
- package/dist/mcp/issue.d.ts +20 -0
- package/dist/mcp/issueComments.d.ts +11 -0
- package/dist/mcp/issueEvents.d.ts +11 -0
- package/dist/mcp/issueInfo.d.ts +11 -0
- package/dist/mcp/labels.d.ts +14 -0
- package/dist/mcp/localContext.d.ts +26 -0
- package/dist/mcp/moduleExtraction.d.ts +79 -0
- package/dist/mcp/moduleTests.d.ts +106 -0
- package/dist/mcp/modules.d.ts +198 -0
- package/dist/mcp/output.d.ts +16 -0
- package/dist/mcp/pathSafety.d.ts +14 -0
- package/dist/mcp/policy.d.ts +50 -0
- package/dist/mcp/pr.d.ts +64 -0
- package/dist/mcp/prInfo.d.ts +11 -0
- package/dist/mcp/providerSchema.d.ts +52 -0
- package/dist/mcp/review.d.ts +212 -0
- package/dist/mcp/reviewComments.d.ts +245 -0
- package/dist/mcp/roots.d.ts +60 -0
- package/dist/mcp/scope.d.ts +26 -0
- package/dist/mcp/selectMode.d.ts +20 -0
- package/dist/mcp/server.d.ts +61 -0
- package/dist/mcp/shared.d.ts +62 -0
- package/dist/mcp/shell.d.ts +58 -0
- package/dist/mcp/staleFix.d.ts +138 -0
- package/dist/mcp/terraform/azurePrices.d.ts +8 -0
- package/dist/mcp/terraform/baseline.d.ts +57 -0
- package/dist/mcp/terraform/concernResult.d.ts +38 -0
- package/dist/mcp/terraform/cost.d.ts +55 -0
- package/dist/mcp/terraform/cspm.d.ts +80 -0
- package/dist/mcp/terraform/currency.d.ts +110 -0
- package/dist/mcp/terraform/decisions.d.ts +178 -0
- package/dist/mcp/terraform/eidas.d.ts +100 -0
- package/dist/mcp/terraform/evidence.d.ts +343 -0
- package/dist/mcp/terraform/findings.d.ts +76 -0
- package/dist/mcp/terraform/fixMemory.d.ts +81 -0
- package/dist/mcp/terraform/governance.d.ts +56 -0
- package/dist/mcp/terraform/hcl.d.ts +115 -0
- package/dist/mcp/terraform/iacLanguages.d.ts +120 -0
- package/dist/mcp/terraform/idleFloor.d.ts +78 -0
- package/dist/mcp/terraform/keyless.d.ts +68 -0
- package/dist/mcp/terraform/moduleDocs.d.ts +56 -0
- package/dist/mcp/terraform/nativeRules.d.ts +38 -0
- package/dist/mcp/terraform/nativeScan.d.ts +11 -0
- package/dist/mcp/terraform/noiseProfile.d.ts +100 -0
- package/dist/mcp/terraform/normalization.d.ts +52 -0
- package/dist/mcp/terraform/oscal.d.ts +103 -0
- package/dist/mcp/terraform/packs/azurerm-3-4.d.ts +2 -0
- package/dist/mcp/terraform/packs/cloudflare-4-5.d.ts +2 -0
- package/dist/mcp/terraform/paths.d.ts +28 -0
- package/dist/mcp/terraform/plan.d.ts +157 -0
- package/dist/mcp/terraform/planDrift.d.ts +199 -0
- package/dist/mcp/terraform/policyAuthor.d.ts +191 -0
- package/dist/mcp/terraform/prowlerOcsf.d.ts +136 -0
- package/dist/mcp/terraform/refactor.d.ts +183 -0
- package/dist/mcp/terraform/registry.d.ts +108 -0
- package/dist/mcp/terraform/risk.d.ts +41 -0
- package/dist/mcp/terraform/scanSession.d.ts +116 -0
- package/dist/mcp/terraform/scannerCache.d.ts +15 -0
- package/dist/mcp/terraform/scannerEgress.d.ts +72 -0
- package/dist/mcp/terraform/scannerJson.d.ts +13 -0
- package/dist/mcp/terraform/scanners.d.ts +205 -0
- package/dist/mcp/terraform/signing.d.ts +61 -0
- package/dist/mcp/terraform/stateLocking.d.ts +18 -0
- package/dist/mcp/terraform/subprocess.d.ts +43 -0
- package/dist/mcp/terraform/suppressions.d.ts +90 -0
- package/dist/mcp/terraform/taxonomy.d.ts +39 -0
- package/dist/mcp/terraform/tfquery.d.ts +47 -0
- package/dist/mcp/terraform/toolchainIntegrity.d.ts +82 -0
- package/dist/mcp/terraform/tools/authorPolicy.d.ts +59 -0
- package/dist/mcp/terraform/tools/detectPlanDrift.d.ts +20 -0
- package/dist/mcp/terraform/tools/emitCost.d.ts +11 -0
- package/dist/mcp/terraform/tools/emitSarif.d.ts +14 -0
- package/dist/mcp/terraform/tools/fixMemory.d.ts +19 -0
- package/dist/mcp/terraform/tools/infracostDiff.d.ts +22 -0
- package/dist/mcp/terraform/tools/ingestExternalFindings.d.ts +21 -0
- package/dist/mcp/terraform/tools/moduleLookup.d.ts +14 -0
- package/dist/mcp/terraform/tools/moduleSearch.d.ts +23 -0
- package/dist/mcp/terraform/tools/plan.d.ts +59 -0
- package/dist/mcp/terraform/tools/providerUpgrade.d.ts +55 -0
- package/dist/mcp/terraform/tools/readFindings.d.ts +17 -0
- package/dist/mcp/terraform/tools/scan.d.ts +114 -0
- package/dist/mcp/terraform/tools/validate.d.ts +31 -0
- package/dist/mcp/terraform/tools/verifyRemediation.d.ts +31 -0
- package/dist/mcp/terraform/tools/versionCurrency.d.ts +5 -0
- package/dist/mcp/terraform/tools.d.ts +16 -0
- package/dist/mcp/terraform/transformPacks.d.ts +267 -0
- package/dist/mcp/terraform/types.d.ts +226 -0
- package/dist/mcp/terraform/verification.d.ts +81 -0
- package/dist/mcp/terraform/vex.d.ts +115 -0
- package/dist/mcp/terraform/writeOnly.d.ts +67 -0
- package/dist/mcp/terraform.d.ts +51 -0
- package/dist/mcp/terratest.d.ts +85 -0
- package/dist/mcp/untrustedContent.d.ts +76 -0
- package/dist/mcp/upload.d.ts +8 -0
- package/dist/models.d.ts +181 -0
- package/dist/modes/address-reviews.d.ts +2 -0
- package/dist/modes/assess.d.ts +2 -0
- package/dist/modes/build.d.ts +2 -0
- package/dist/modes/compliance-audit.d.ts +2 -0
- package/dist/modes/cost-optimization.d.ts +2 -0
- package/dist/modes/drift-detect.d.ts +2 -0
- package/dist/modes/fix.d.ts +2 -0
- package/dist/modes/incremental-review.d.ts +2 -0
- package/dist/modes/index.d.ts +24 -0
- package/dist/modes/modernize-deprecated.d.ts +2 -0
- package/dist/modes/plan.d.ts +2 -0
- package/dist/modes/policy-gate.d.ts +2 -0
- package/dist/modes/prFormats.d.ts +3 -0
- package/dist/modes/refactor.d.ts +2 -0
- package/dist/modes/refresh-remediation.d.ts +2 -0
- package/dist/modes/remediate-and-refactor.d.ts +2 -0
- package/dist/modes/remediate.d.ts +2 -0
- package/dist/modes/resolve-conflicts.d.ts +2 -0
- package/dist/modes/review.d.ts +2 -0
- package/dist/modes/summarize-pr.d.ts +2 -0
- package/dist/modes/task.d.ts +2 -0
- package/dist/modes/terraform-code-review.d.ts +2 -0
- package/dist/modes/types.d.ts +9 -0
- package/dist/modes/update-dependencies.d.ts +2 -0
- package/dist/prep/index.d.ts +7 -0
- package/dist/prep/installNodeDependencies.d.ts +2 -0
- package/dist/prep/installPythonDependencies.d.ts +2 -0
- package/dist/prep/types.d.ts +31 -0
- package/dist/reviewQuality.d.ts +107 -0
- package/dist/skills/terraform-best-practices/SKILL.md +379 -0
- package/dist/toolState.d.ts +123 -0
- package/dist/utils/activity.d.ts +40 -0
- package/dist/utils/agent.d.ts +47 -0
- package/dist/utils/agentHangReport.d.ts +38 -0
- package/dist/utils/annotations.d.ts +17 -0
- package/dist/utils/apiFetch.d.ts +11 -0
- package/dist/utils/apiKeys.d.ts +48 -0
- package/dist/utils/apiUrl.d.ts +28 -0
- package/dist/utils/assets.d.ts +8 -0
- package/dist/utils/baseRefConfig.d.ts +121 -0
- package/dist/utils/billingErrors.d.ts +85 -0
- package/dist/utils/body.d.ts +34 -0
- package/dist/utils/buildInfraweaverFooter.d.ts +29 -0
- package/dist/utils/byokFallback.d.ts +85 -0
- package/dist/utils/changeImpact.d.ts +101 -0
- package/dist/utils/claudeSubscription.d.ts +30 -0
- package/dist/utils/cli.d.ts +10 -0
- package/dist/utils/cloudClient.d.ts +33 -0
- package/dist/utils/cloudFetchCore.d.ts +42 -0
- package/dist/utils/cloudReport.d.ts +114 -0
- package/dist/utils/codexHome.d.ts +29 -0
- package/dist/utils/codexOAuth.d.ts +60 -0
- package/dist/utils/diffCoverage.d.ts +63 -0
- package/dist/utils/env.d.ts +46 -0
- package/dist/utils/errorReport.d.ts +17 -0
- package/dist/utils/exitHandler.d.ts +8 -0
- package/dist/utils/fixDoubleEscapedString.d.ts +1 -0
- package/dist/utils/gitAuth.d.ts +84 -0
- package/dist/utils/gitAuthServer.d.ts +24 -0
- package/dist/utils/github.d.ts +104 -0
- package/dist/utils/globals.d.ts +3 -0
- package/dist/utils/infraweaverConfig.d.ts +56 -0
- package/dist/utils/install.d.ts +37 -0
- package/dist/utils/instructions.d.ts +48 -0
- package/dist/utils/keylessOidc.d.ts +28 -0
- package/dist/utils/leapingComment.d.ts +11 -0
- package/dist/utils/learnings.d.ts +62 -0
- package/dist/utils/learningsTruncate.d.ts +25 -0
- package/dist/utils/lifecycle.d.ts +57 -0
- package/dist/utils/log.d.ts +111 -0
- package/dist/utils/modelResolver.d.ts +63 -0
- package/dist/utils/moduleFetch.d.ts +39 -0
- package/dist/utils/normalizeEnv.d.ts +30 -0
- package/dist/utils/openCodeModels.d.ts +11 -0
- package/dist/utils/openaiCompatible.d.ts +26 -0
- package/dist/utils/opentofuMcp.d.ts +50 -0
- package/dist/utils/overrides.d.ts +40 -0
- package/dist/utils/packageManager.d.ts +49 -0
- package/dist/utils/patchWorkflowRunFields.d.ts +29 -0
- package/dist/utils/payload.d.ts +249 -0
- package/dist/utils/prSummary.d.ts +61 -0
- package/dist/utils/presets.d.ts +36 -0
- package/dist/utils/progressComment.d.ts +146 -0
- package/dist/utils/providerErrors.d.ts +31 -0
- package/dist/utils/proxyModel.d.ts +76 -0
- package/dist/utils/rangeDiff.d.ts +51 -0
- package/dist/utils/redact.d.ts +33 -0
- package/dist/utils/registryAuth.d.ts +52 -0
- package/dist/utils/remediationCommand.d.ts +58 -0
- package/dist/utils/retry.d.ts +38 -0
- package/dist/utils/reviewCleanup.d.ts +14 -0
- package/dist/utils/run.d.ts +9 -0
- package/dist/utils/runContext.d.ts +112 -0
- package/dist/utils/runContextData.d.ts +42 -0
- package/dist/utils/runErrorRenderer.d.ts +64 -0
- package/dist/utils/runLifecycle.d.ts +89 -0
- package/dist/utils/runStartupLog.d.ts +15 -0
- package/dist/utils/secrets.d.ts +34 -0
- package/dist/utils/setup.d.ts +90 -0
- package/dist/utils/shell.d.ts +44 -0
- package/dist/utils/skills.d.ts +10 -0
- package/dist/utils/subprocess.d.ts +81 -0
- package/dist/utils/terraformMcp.d.ts +46 -0
- package/dist/utils/time.d.ts +15 -0
- package/dist/utils/timer.d.ts +23 -0
- package/dist/utils/todoTracking.d.ts +16 -0
- package/dist/utils/token.d.ts +52 -0
- package/dist/utils/toolLicensing.d.ts +56 -0
- package/dist/utils/toolSelection.d.ts +73 -0
- package/dist/utils/toon.d.ts +16 -0
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/versioning.d.ts +7 -0
- package/dist/utils/vertex.d.ts +16 -0
- package/dist/utils/workflow.d.ts +13 -0
- package/package.json +132 -0
- package/src/agents/claude.ts +1588 -0
- package/src/agents/claudePretoolGate.ts +286 -0
- package/src/agents/dispatchMetrics.ts +162 -0
- package/src/agents/gateServer.ts +178 -0
- package/src/agents/index.ts +10 -0
- package/src/agents/nativeFsDenies.ts +164 -0
- package/src/agents/opencode.ts +1600 -0
- package/src/agents/opencodePlugin.ts +304 -0
- package/src/agents/opencodeShared.ts +134 -0
- package/src/agents/postRun.ts +615 -0
- package/src/agents/reviewer.ts +134 -0
- package/src/agents/sessionLabeler.ts +185 -0
- package/src/agents/shared.ts +377 -0
- package/src/agents/subagentModels.ts +40 -0
- package/src/agents/tokenQuota.ts +203 -0
- package/src/agents/writeGateSource.ts +148 -0
- package/src/agents/writePolicy.ts +132 -0
- package/src/brand.ts +84 -0
- package/src/cli.ts +117 -0
- package/src/commands/gha.ts +188 -0
- package/src/commands/mcp.ts +126 -0
- package/src/commands/verifyEvidence.ts +100 -0
- package/src/entry.ts +7 -0
- package/src/entryPost.ts +109 -0
- package/src/external.ts +308 -0
- package/src/i18n/scaffolding.ts +191 -0
- package/src/index.ts +7 -0
- package/src/internal/index.ts +74 -0
- package/src/lifecycle.ts +2 -0
- package/src/main.ts +815 -0
- package/src/mcp/__fixtures__/infraweaver-scratch-pr-49-review-3485940013.json +110 -0
- package/src/mcp/__fixtures__/infraweaver-scratch-pr-64-review-3531000326.json +14 -0
- package/src/mcp/__fixtures__/infraweaver-test-repo-pr-1.diff.json +67 -0
- package/src/mcp/__snapshots__/checkout.test.ts.snap +109 -0
- package/src/mcp/__snapshots__/reviewComments.test.ts.snap +71 -0
- package/src/mcp/arkConfig.ts +7 -0
- package/src/mcp/assess.ts +723 -0
- package/src/mcp/capabilityContext.ts +80 -0
- package/src/mcp/changeSummary.ts +145 -0
- package/src/mcp/checkSuite.ts +261 -0
- package/src/mcp/checkout.ts +1015 -0
- package/src/mcp/comment.ts +683 -0
- package/src/mcp/commitInfo.ts +57 -0
- package/src/mcp/crosswalk.ts +1253 -0
- package/src/mcp/crosswalkDigest.ts +5 -0
- package/src/mcp/cyberEssentials.ts +60 -0
- package/src/mcp/dashboard.ts +232 -0
- package/src/mcp/dependencies.ts +190 -0
- package/src/mcp/frameworks.ts +236 -0
- package/src/mcp/geminiSanitizer.ts +212 -0
- package/src/mcp/git.ts +1116 -0
- package/src/mcp/guardrails.ts +771 -0
- package/src/mcp/issue.ts +74 -0
- package/src/mcp/issueComments.ts +48 -0
- package/src/mcp/issueEvents.ts +100 -0
- package/src/mcp/issueInfo.ts +72 -0
- package/src/mcp/labels.ts +35 -0
- package/src/mcp/localContext.ts +65 -0
- package/src/mcp/localServer.ts +217 -0
- package/src/mcp/moduleExtraction.ts +368 -0
- package/src/mcp/moduleTests.ts +421 -0
- package/src/mcp/modules.ts +752 -0
- package/src/mcp/output.ts +71 -0
- package/src/mcp/pathSafety.ts +28 -0
- package/src/mcp/policy.ts +226 -0
- package/src/mcp/pr.ts +238 -0
- package/src/mcp/prInfo.ts +91 -0
- package/src/mcp/providerSchema.ts +175 -0
- package/src/mcp/review.ts +1081 -0
- package/src/mcp/reviewComments.ts +1137 -0
- package/src/mcp/roots.ts +217 -0
- package/src/mcp/scope.ts +82 -0
- package/src/mcp/selectMode.ts +207 -0
- package/src/mcp/server.ts +498 -0
- package/src/mcp/shared.ts +120 -0
- package/src/mcp/shell.ts +631 -0
- package/src/mcp/staleFix.ts +557 -0
- package/src/mcp/terraform/__snapshots__/moduleDocs.test.ts.snap +40 -0
- package/src/mcp/terraform/azurePrices.ts +38 -0
- package/src/mcp/terraform/baseline.ts +172 -0
- package/src/mcp/terraform/concernResult.ts +111 -0
- package/src/mcp/terraform/cost.ts +175 -0
- package/src/mcp/terraform/cspm.ts +326 -0
- package/src/mcp/terraform/currency.ts +354 -0
- package/src/mcp/terraform/decisions.ts +590 -0
- package/src/mcp/terraform/eidas.ts +134 -0
- package/src/mcp/terraform/evidence.ts +771 -0
- package/src/mcp/terraform/findings.ts +383 -0
- package/src/mcp/terraform/fixMemory.ts +253 -0
- package/src/mcp/terraform/governance.ts +231 -0
- package/src/mcp/terraform/hcl.ts +273 -0
- package/src/mcp/terraform/iacLanguages.ts +431 -0
- package/src/mcp/terraform/idleFloor.ts +304 -0
- package/src/mcp/terraform/keyless.ts +123 -0
- package/src/mcp/terraform/moduleDocs.ts +303 -0
- package/src/mcp/terraform/nativeRules.ts +152 -0
- package/src/mcp/terraform/nativeScan.ts +67 -0
- package/src/mcp/terraform/noiseProfile.ts +183 -0
- package/src/mcp/terraform/normalization.ts +265 -0
- package/src/mcp/terraform/oscal.ts +283 -0
- package/src/mcp/terraform/packs/azurerm-3-4.ts +382 -0
- package/src/mcp/terraform/packs/cloudflare-4-5.ts +114 -0
- package/src/mcp/terraform/paths.ts +59 -0
- package/src/mcp/terraform/plan.ts +377 -0
- package/src/mcp/terraform/planDrift.ts +520 -0
- package/src/mcp/terraform/policyAuthor.ts +886 -0
- package/src/mcp/terraform/prowlerOcsf.ts +380 -0
- package/src/mcp/terraform/refactor.ts +879 -0
- package/src/mcp/terraform/registry.ts +317 -0
- package/src/mcp/terraform/risk.ts +99 -0
- package/src/mcp/terraform/scanSession.ts +242 -0
- package/src/mcp/terraform/scannerCache.ts +86 -0
- package/src/mcp/terraform/scannerEgress.ts +141 -0
- package/src/mcp/terraform/scannerJson.ts +22 -0
- package/src/mcp/terraform/scanners.ts +1134 -0
- package/src/mcp/terraform/signing.ts +151 -0
- package/src/mcp/terraform/stateLocking.ts +106 -0
- package/src/mcp/terraform/subprocess.ts +102 -0
- package/src/mcp/terraform/suppressions.ts +551 -0
- package/src/mcp/terraform/taxonomy.ts +0 -0
- package/src/mcp/terraform/tfquery.ts +159 -0
- package/src/mcp/terraform/toolchainIntegrity.ts +151 -0
- package/src/mcp/terraform/tools/authorPolicy.ts +185 -0
- package/src/mcp/terraform/tools/detectPlanDrift.ts +279 -0
- package/src/mcp/terraform/tools/emitCost.ts +130 -0
- package/src/mcp/terraform/tools/emitSarif.ts +108 -0
- package/src/mcp/terraform/tools/fixMemory.ts +82 -0
- package/src/mcp/terraform/tools/infracostDiff.ts +110 -0
- package/src/mcp/terraform/tools/ingestExternalFindings.ts +259 -0
- package/src/mcp/terraform/tools/moduleLookup.ts +86 -0
- package/src/mcp/terraform/tools/moduleSearch.ts +46 -0
- package/src/mcp/terraform/tools/plan.ts +384 -0
- package/src/mcp/terraform/tools/providerUpgrade.ts +217 -0
- package/src/mcp/terraform/tools/readFindings.ts +138 -0
- package/src/mcp/terraform/tools/scan.ts +303 -0
- package/src/mcp/terraform/tools/validate.ts +160 -0
- package/src/mcp/terraform/tools/verifyRemediation.ts +190 -0
- package/src/mcp/terraform/tools/versionCurrency.ts +64 -0
- package/src/mcp/terraform/tools.ts +62 -0
- package/src/mcp/terraform/transformPacks.ts +594 -0
- package/src/mcp/terraform/types.ts +382 -0
- package/src/mcp/terraform/verification.ts +150 -0
- package/src/mcp/terraform/vex.ts +367 -0
- package/src/mcp/terraform/writeOnly.ts +252 -0
- package/src/mcp/terraform.ts +52 -0
- package/src/mcp/terratest.ts +215 -0
- package/src/mcp/untrustedContent.ts +126 -0
- package/src/mcp/upload.ts +123 -0
- package/src/models.ts +753 -0
- package/src/modes/address-reviews.ts +35 -0
- package/src/modes/assess.ts +27 -0
- package/src/modes/build.ts +86 -0
- package/src/modes/compliance-audit.ts +25 -0
- package/src/modes/cost-optimization.ts +36 -0
- package/src/modes/drift-detect.ts +31 -0
- package/src/modes/fix.ts +29 -0
- package/src/modes/incremental-review.ts +103 -0
- package/src/modes/index.ts +94 -0
- package/src/modes/modernize-deprecated.ts +36 -0
- package/src/modes/plan.ts +21 -0
- package/src/modes/policy-gate.ts +27 -0
- package/src/modes/prFormats.ts +325 -0
- package/src/modes/refactor.ts +74 -0
- package/src/modes/refresh-remediation.ts +40 -0
- package/src/modes/remediate-and-refactor.ts +42 -0
- package/src/modes/remediate.ts +78 -0
- package/src/modes/resolve-conflicts.ts +32 -0
- package/src/modes/review.ts +135 -0
- package/src/modes/summarize-pr.ts +42 -0
- package/src/modes/task.ts +26 -0
- package/src/modes/terraform-code-review.ts +68 -0
- package/src/modes/types.ts +17 -0
- package/src/modes/update-dependencies.ts +44 -0
- package/src/prep/index.ts +96 -0
- package/src/prep/installNodeDependencies.ts +251 -0
- package/src/prep/installPythonDependencies.ts +235 -0
- package/src/prep/types.ts +38 -0
- package/src/reviewQuality.ts +237 -0
- package/src/runCli.ts +335 -0
- package/src/skills/terraform-best-practices/SKILL.md +379 -0
- package/src/toolState.ts +241 -0
- package/src/utils/activity.ts +210 -0
- package/src/utils/agent.ts +245 -0
- package/src/utils/agentHangReport.ts +180 -0
- package/src/utils/annotations.ts +56 -0
- package/src/utils/apiFetch.ts +19 -0
- package/src/utils/apiKeys.ts +305 -0
- package/src/utils/apiUrl.ts +42 -0
- package/src/utils/assets.ts +123 -0
- package/src/utils/baseRefConfig.ts +254 -0
- package/src/utils/billingErrors.ts +210 -0
- package/src/utils/body.ts +168 -0
- package/src/utils/buildInfraweaverFooter.ts +104 -0
- package/src/utils/byokFallback.ts +137 -0
- package/src/utils/changeImpact.ts +330 -0
- package/src/utils/claudeSubscription.ts +93 -0
- package/src/utils/cli.ts +36 -0
- package/src/utils/cloudClient.ts +57 -0
- package/src/utils/cloudFetchCore.ts +139 -0
- package/src/utils/cloudReport.ts +316 -0
- package/src/utils/codexHome.ts +204 -0
- package/src/utils/codexOAuth.ts +154 -0
- package/src/utils/codexRefreshDetect.ts +36 -0
- package/src/utils/diffCoverage.ts +404 -0
- package/src/utils/env.ts +84 -0
- package/src/utils/errorReport.ts +94 -0
- package/src/utils/exitHandler.ts +35 -0
- package/src/utils/fixDoubleEscapedString.ts +9 -0
- package/src/utils/ghaCore.ts +13 -0
- package/src/utils/gitAuth.ts +268 -0
- package/src/utils/gitAuthServer.ts +186 -0
- package/src/utils/github.ts +676 -0
- package/src/utils/globals.ts +9 -0
- package/src/utils/humanEditCapture.ts +198 -0
- package/src/utils/infraweaverConfig.ts +202 -0
- package/src/utils/install.ts +279 -0
- package/src/utils/instructions.ts +640 -0
- package/src/utils/keylessOidc.ts +47 -0
- package/src/utils/leapingComment.ts +20 -0
- package/src/utils/learnings.ts +145 -0
- package/src/utils/learningsTruncate.ts +42 -0
- package/src/utils/lifecycle.ts +198 -0
- package/src/utils/log.ts +452 -0
- package/src/utils/modelResolver.ts +105 -0
- package/src/utils/moduleFetch.ts +138 -0
- package/src/utils/normalizeEnv.ts +106 -0
- package/src/utils/openCodeModels.ts +86 -0
- package/src/utils/openaiCompatible.ts +52 -0
- package/src/utils/opentofuMcp.ts +61 -0
- package/src/utils/overrides.ts +100 -0
- package/src/utils/packageManager.ts +257 -0
- package/src/utils/patchWorkflowRunFields.ts +173 -0
- package/src/utils/payload.ts +1206 -0
- package/src/utils/prSummary.ts +148 -0
- package/src/utils/presets.ts +105 -0
- package/src/utils/progressComment.ts +266 -0
- package/src/utils/providerErrors.ts +189 -0
- package/src/utils/proxyModel.ts +239 -0
- package/src/utils/rangeDiff.ts +182 -0
- package/src/utils/redact.ts +86 -0
- package/src/utils/registryAuth.ts +115 -0
- package/src/utils/remediationCommand.ts +144 -0
- package/src/utils/retry.ts +180 -0
- package/src/utils/reviewCleanup.ts +116 -0
- package/src/utils/run.ts +100 -0
- package/src/utils/runContext.ts +276 -0
- package/src/utils/runContextData.ts +121 -0
- package/src/utils/runErrorRenderer.ts +282 -0
- package/src/utils/runFixture.ts +91 -0
- package/src/utils/runLifecycle.ts +360 -0
- package/src/utils/runStartupLog.ts +67 -0
- package/src/utils/secrets.ts +208 -0
- package/src/utils/setup.ts +368 -0
- package/src/utils/shell.ts +132 -0
- package/src/utils/skills.ts +67 -0
- package/src/utils/subprocess.ts +474 -0
- package/src/utils/terraformMcp.ts +99 -0
- package/src/utils/time.ts +59 -0
- package/src/utils/timer.ts +72 -0
- package/src/utils/todoTracking.ts +168 -0
- package/src/utils/token.ts +294 -0
- package/src/utils/toolLicensing.ts +152 -0
- package/src/utils/toolSelection.ts +239 -0
- package/src/utils/toon.ts +76 -0
- package/src/utils/version.ts +10 -0
- package/src/utils/versioning.ts +44 -0
- package/src/utils/vertex.ts +94 -0
- package/src/utils/workflow.ts +25 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stash for the GitHub Actions OIDC request creds used by KEYLESS (Sigstore)
|
|
3
|
+
* evidence signing.
|
|
4
|
+
*
|
|
5
|
+
* The `terraform_emit_evidence` / `terraform_emit_vex` tools run DURING the agent
|
|
6
|
+
* loop — after `main.ts` scrubs `ACTIONS_ID_TOKEN_REQUEST_*` from the env (in
|
|
7
|
+
* every shell mode) — so they can't call `core.getIDToken()` / read those vars
|
|
8
|
+
* themselves. Infraweaver already snapshots the request creds early (see
|
|
9
|
+
* `resolveTokens` in `utils/token.ts`, which reads them for mid-run token
|
|
10
|
+
* re-mints); this module lets that same snapshot feed a `sigstore`-audience OIDC
|
|
11
|
+
* token to Fulcio at emit time.
|
|
12
|
+
*
|
|
13
|
+
* Fulcio requires the OIDC token's `aud` to be exactly `sigstore` (its configured
|
|
14
|
+
* audience), distinct from Infraweaver Cloud's own `cloudOidcAudience()`.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { fetchOidcIdToken, type OidcCreds } from "#app/utils/github";
|
|
18
|
+
|
|
19
|
+
/** Fulcio's required OIDC audience for the public-good instance. */
|
|
20
|
+
export const SIGSTORE_OIDC_AUDIENCE = "sigstore" as const;
|
|
21
|
+
|
|
22
|
+
let stashedCreds: OidcCreds | undefined;
|
|
23
|
+
|
|
24
|
+
/** Record the OIDC request creds for later keyless signing. Call once at startup
|
|
25
|
+
* (before the restricted-mode env scrub), passing `readOidcCreds()`. `undefined`
|
|
26
|
+
* off-CI, which simply disables keyless signing (there is no ambient identity). */
|
|
27
|
+
export function stashKeylessOidcCreds(creds: OidcCreds | undefined): void {
|
|
28
|
+
stashedCreds = creds;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** True when an ambient GitHub Actions OIDC identity was captured — i.e. keyless
|
|
32
|
+
* signing is possible (running in CI with `id-token: write`). */
|
|
33
|
+
export function keylessOidcAvailable(): boolean {
|
|
34
|
+
return stashedCreds !== undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Fetch a fresh `sigstore`-audience OIDC JWT for Fulcio from the stashed creds.
|
|
38
|
+
* Throws when no creds were stashed (off-CI, or the workflow lacks id-token:write). */
|
|
39
|
+
export async function fetchSigstoreOidcToken(): Promise<string> {
|
|
40
|
+
if (!stashedCreds) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
"keyless signing needs a GitHub Actions OIDC identity, but none was captured — " +
|
|
43
|
+
"run inside GitHub Actions with `permissions: id-token: write`.",
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return fetchOidcIdToken(stashedCreds, SIGSTORE_OIDC_AUDIENCE);
|
|
47
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { stripExistingFooter } from "#app/utils/buildInfraweaverFooter";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The prefix text for the initial "leaping into action" comment.
|
|
5
|
+
* Used to detect whether a progress comment is still in its initial state
|
|
6
|
+
* and hasn't been updated with real progress or error messages.
|
|
7
|
+
*
|
|
8
|
+
* Lives in `utils/` (not `mcp/`) so it can be re-exported via `infraweaver/internal`
|
|
9
|
+
* without dragging the MCP server's transitive imports into the Next.js app's
|
|
10
|
+
* type-check graph.
|
|
11
|
+
*/
|
|
12
|
+
export const LEAPING_INTO_ACTION_PREFIX = "Leaping into action";
|
|
13
|
+
|
|
14
|
+
export function isLeapingIntoActionCommentBody(body: string): boolean {
|
|
15
|
+
const content = stripExistingFooter(body).trimStart();
|
|
16
|
+
const firstLine = content.split(/\r?\n/, 1)[0]?.trimEnd() ?? "";
|
|
17
|
+
return new RegExp(`(^|\\s)${LEAPING_INTO_ACTION_PREFIX}(\\.\\.\\.)?$`).test(
|
|
18
|
+
firstLine,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { LEARNINGS_FILE } from "#app/brand";
|
|
4
|
+
import type { ToolContext } from "#app/mcp/server";
|
|
5
|
+
import { cloudRequest } from "#app/utils/cloudClient";
|
|
6
|
+
import { isBackendConfigured } from "#app/utils/apiUrl";
|
|
7
|
+
import { log } from "#app/utils/cli";
|
|
8
|
+
import {
|
|
9
|
+
MAX_LEARNINGS_LENGTH,
|
|
10
|
+
truncateAtLineBoundary,
|
|
11
|
+
} from "#app/utils/learningsTruncate";
|
|
12
|
+
|
|
13
|
+
export { MAX_LEARNINGS_LENGTH, truncateAtLineBoundary };
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Repo-level learnings — operational facts about a repo (setup steps, test
|
|
17
|
+
* commands, conventions, gotchas) that accumulate across agent runs and feed
|
|
18
|
+
* back into future runs as durable context. Modeled on the PR-summary tmpfile
|
|
19
|
+
* pattern (see action/utils/prSummary.ts):
|
|
20
|
+
*
|
|
21
|
+
* 1. server seeds `infraweaver-learnings.md` with the verbatim body of
|
|
22
|
+
* `Repo.learnings` (or empty for fresh repos), and parses headings
|
|
23
|
+
* server-side (`utils/learningsToc.ts`) — the parsed TOC is rendered
|
|
24
|
+
* into the LEARNINGS prompt section, not into the file
|
|
25
|
+
* 2. the agent reads the TOC in the prompt and uses listed line ranges
|
|
26
|
+
* to read just the sections relevant to the current task — file can
|
|
27
|
+
* grow large, but only targeted ranges hit the agent's context
|
|
28
|
+
* 3. agent edits the file in place at end-of-run during the reflection
|
|
29
|
+
* turn (see action/agents/postRun.ts buildLearningsReflectionPrompt)
|
|
30
|
+
* 4. main.ts reads the file back at end-of-run and PATCHes
|
|
31
|
+
* `/api/repo/[owner]/[repo]/learnings` if the body changed
|
|
32
|
+
*
|
|
33
|
+
* Edit-in-place avoids stuffing the entire learnings list into both the
|
|
34
|
+
* prompt context and an `update_learnings` MCP tool call (which previously
|
|
35
|
+
* required passing the FULL merged list as a string parameter — an
|
|
36
|
+
* output-token tax that grew linearly with the learnings size).
|
|
37
|
+
*
|
|
38
|
+
* Section structure is agent-curated. The reflection prompt teaches
|
|
39
|
+
* hierarchy + a soft 300-line-per-section cap to keep TOC ranges
|
|
40
|
+
* agent-targetable on long-lived repos; there is no fixed taxonomy.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
export const LEARNINGS_FILE_NAME = LEARNINGS_FILE;
|
|
44
|
+
|
|
45
|
+
export function learningsFilePath(tmpdir: string): string {
|
|
46
|
+
return join(tmpdir, LEARNINGS_FILE_NAME);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** seed the rolling learnings tmpfile with the verbatim DB body (or empty
|
|
50
|
+
* string for fresh repos). returns the absolute path. the parsed TOC is
|
|
51
|
+
* carried separately via `RepoSettings.learningsHeadings` and rendered
|
|
52
|
+
* into the prompt by `resolveInstructions`, so the file on disk is just
|
|
53
|
+
* the body — no markers, no scaffold, no in-file TOC. */
|
|
54
|
+
export async function seedLearningsFile(params: {
|
|
55
|
+
tmpdir: string;
|
|
56
|
+
current: string | null;
|
|
57
|
+
}): Promise<string> {
|
|
58
|
+
const path = learningsFilePath(params.tmpdir);
|
|
59
|
+
await mkdir(dirname(path), { recursive: true });
|
|
60
|
+
await writeFile(path, params.current ?? "", "utf8");
|
|
61
|
+
return path;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** read the agent-edited learnings file. returns null when the file is
|
|
65
|
+
* missing or unreadable (treated as "no change"). caps content at the
|
|
66
|
+
* server's max length to avoid a 400 round-trip. */
|
|
67
|
+
export async function readLearningsFile(path: string): Promise<string | null> {
|
|
68
|
+
let raw: string;
|
|
69
|
+
try {
|
|
70
|
+
raw = await readFile(path, "utf8");
|
|
71
|
+
} catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
return truncateAtLineBoundary(raw.trim(), MAX_LEARNINGS_LENGTH);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Read the agent-edited repo-level learnings tmpfile and PATCH it to
|
|
79
|
+
* `Repo.learnings`.
|
|
80
|
+
*
|
|
81
|
+
* Best-effort: any failure is logged and does not affect the run's success
|
|
82
|
+
* status. Skips the PATCH when the file is byte-trim-identical to its seed —
|
|
83
|
+
* the agent didn't touch it, so writing the same content back would just
|
|
84
|
+
* burn a `LearningsRevision` row and an API round-trip.
|
|
85
|
+
*
|
|
86
|
+
* `ctx.toolState.model` is forwarded so `LearningsRevision.model` keeps
|
|
87
|
+
* populating; it powers the per-revision attribution badge in the UI
|
|
88
|
+
* history view.
|
|
89
|
+
*
|
|
90
|
+
* `learningsPersistAttempted` guards against double-execution between the
|
|
91
|
+
* normal end-of-run path and the SIGINT/SIGTERM handler.
|
|
92
|
+
*/
|
|
93
|
+
export async function persistLearnings(ctx: ToolContext): Promise<void> {
|
|
94
|
+
const filePath = ctx.toolState.learningsFilePath;
|
|
95
|
+
if (!filePath) return;
|
|
96
|
+
if (ctx.toolState.learningsPersistAttempted) return;
|
|
97
|
+
ctx.toolState.learningsPersistAttempted = true;
|
|
98
|
+
// dormant open-core seam: with no backend configured (standalone BYOK), there
|
|
99
|
+
// is nowhere to persist repo learnings — no-op silently instead of PATCHing
|
|
100
|
+
// the default marketing host and warning on its 404.
|
|
101
|
+
if (!isBackendConfigured()) {
|
|
102
|
+
log.debug(
|
|
103
|
+
"no backend configured (API_URL unset) — skipping learnings persist",
|
|
104
|
+
);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const current = await readLearningsFile(filePath);
|
|
108
|
+
if (current === null) {
|
|
109
|
+
log.debug(
|
|
110
|
+
`learnings tmpfile missing or unreadable at ${filePath} — skipping persist`,
|
|
111
|
+
);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const seed = ctx.toolState.learningsSeed?.trim() ?? "";
|
|
115
|
+
if (current === seed) {
|
|
116
|
+
log.debug("learnings tmpfile unchanged from seed — skipping persist");
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const response = await cloudRequest({
|
|
121
|
+
path: `/api/repo/${ctx.repo.owner}/${ctx.repo.name}/learnings`,
|
|
122
|
+
method: "PATCH",
|
|
123
|
+
credential: ctx.apiToken,
|
|
124
|
+
json: {
|
|
125
|
+
learnings: current,
|
|
126
|
+
model: ctx.toolState.model,
|
|
127
|
+
},
|
|
128
|
+
timeoutMs: 10_000,
|
|
129
|
+
});
|
|
130
|
+
if (!response.ok) {
|
|
131
|
+
const error = await response.text().catch(() => "(no body)");
|
|
132
|
+
// promoted from debug → warning: this path means the agent edited the
|
|
133
|
+
// file (we already short-circuited the unchanged-from-seed case above)
|
|
134
|
+
// but the PATCH dropped it on the floor. silently losing real work is
|
|
135
|
+
// worse than the noise of a CI warning.
|
|
136
|
+
log.warning(`learnings persist failed (${response.status}): ${error}`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
log.info("» learnings updated");
|
|
140
|
+
} catch (err) {
|
|
141
|
+
log.warning(
|
|
142
|
+
`learnings persist failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pure string helpers for capping and line-boundary-truncating the
|
|
3
|
+
* `Repo.learnings` body. lives in its own module (vs alongside
|
|
4
|
+
* `learnings.ts`) so the proprietary root app can re-export it through
|
|
5
|
+
* `action/internal/index.ts` without dragging the entire MCP type graph
|
|
6
|
+
* along — `learnings.ts` imports `ToolContext` for its runtime helpers,
|
|
7
|
+
* and pulling that into the SDK-facing `internal` barrel expands the
|
|
8
|
+
* type graph reachable from root `tsc` and `cf-worker-indexing` to every
|
|
9
|
+
* tool module under `action/mcp/`. keeping these helpers MCP-free is the
|
|
10
|
+
* cheap structural fix.
|
|
11
|
+
*
|
|
12
|
+
* see `action/utils/learnings.ts` for the full learnings-file lifecycle.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** maximum size of `Repo.learnings` body in chars. action truncates the
|
|
16
|
+
* read-back BEFORE the PATCH to avoid sending an oversized payload; the
|
|
17
|
+
* server applies the same truncation as a defense-in-depth backstop (any
|
|
18
|
+
* caller that misses the client-side step would otherwise persist a
|
|
19
|
+
* mid-line tail, breaking the next-run TOC parse).
|
|
20
|
+
*
|
|
21
|
+
* raised from 10k → 100k once the TOC affordance landed: with line-range
|
|
22
|
+
* reads via the server-parsed TOC the agent doesn't ingest the whole
|
|
23
|
+
* file, so the cap is governed by curation discipline rather than a
|
|
24
|
+
* tight byte ceiling. 100k holds ~400-500 short bullets. */
|
|
25
|
+
export const MAX_LEARNINGS_LENGTH = 100_000;
|
|
26
|
+
|
|
27
|
+
/** truncate at the last newline boundary before `cap` so we don't leave
|
|
28
|
+
* a partial line at the tail (a half-truncated `## Headi` confuses the
|
|
29
|
+
* server's next-seed TOC parse and shrinks visible structure). falls
|
|
30
|
+
* back to a hard `slice` when the line boundary would discard a large
|
|
31
|
+
* run of content — i.e. when the tail of `head` is one giant line (rare:
|
|
32
|
+
* minified pastes, fenced log dumps). losing a partial last line is
|
|
33
|
+
* preferable to losing kilobytes of body. */
|
|
34
|
+
const TRUNCATION_LINE_BOUNDARY_TOLERANCE = 4096;
|
|
35
|
+
export function truncateAtLineBoundary(body: string, cap: number): string {
|
|
36
|
+
if (body.length <= cap) return body;
|
|
37
|
+
const head = body.slice(0, cap);
|
|
38
|
+
const lastNewline = head.lastIndexOf("\n");
|
|
39
|
+
if (lastNewline <= 0) return head;
|
|
40
|
+
if (cap - lastNewline > TRUNCATION_LINE_BOUNDARY_TOLERANCE) return head;
|
|
41
|
+
return head.slice(0, lastNewline);
|
|
42
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { LIFECYCLE_HOOK_TIMEOUT_MS } from "#app/lifecycle";
|
|
2
|
+
import { log } from "#app/utils/cli";
|
|
3
|
+
import {
|
|
4
|
+
SPAWN_ACTIVITY_TIMEOUT_CODE,
|
|
5
|
+
SPAWN_TIMEOUT_CODE,
|
|
6
|
+
SpawnTimeoutError,
|
|
7
|
+
spawn,
|
|
8
|
+
} from "#app/utils/subprocess";
|
|
9
|
+
|
|
10
|
+
export interface ExecuteLifecycleHookParams {
|
|
11
|
+
event: string;
|
|
12
|
+
script: string | null;
|
|
13
|
+
/**
|
|
14
|
+
* when true, after the hook runs (success or failure), discard tracked-file
|
|
15
|
+
* mods so the agent doesn't see hook-generated drift (e.g. `pnpm install`
|
|
16
|
+
* rewriting a lockfile). untracked files are preserved — hooks that
|
|
17
|
+
* intentionally materialize files (e.g. a `.env` from a template) stay
|
|
18
|
+
* visible to the agent. skipped (with a warning) if the tree had
|
|
19
|
+
* pre-existing tracked changes before the hook ran, so we never clobber
|
|
20
|
+
* pre-existing work; pre-existing untracked files are ignored for this
|
|
21
|
+
* gate because `git restore --staged --worktree .` doesn't touch them
|
|
22
|
+
* anyway. no-op when no script was configured.
|
|
23
|
+
*/
|
|
24
|
+
normalizeWorkingTreeAfter?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** structured failure info — `output` on the `exit` variant is trimmed
|
|
28
|
+
* stderr, falling back to stdout when stderr is empty. */
|
|
29
|
+
export type LifecycleHookFailure =
|
|
30
|
+
| { kind: "exit"; exitCode: number; output: string }
|
|
31
|
+
| { kind: "timeout" }
|
|
32
|
+
| { kind: "spawn"; spawnError: string };
|
|
33
|
+
|
|
34
|
+
/** one-line, agent-facing description of a hook failure. empty string when
|
|
35
|
+
* there was no failure, so callers can pass the result straight through to a
|
|
36
|
+
* prompt section that omits itself on empty. */
|
|
37
|
+
export function describeSetupFailure(failure: LifecycleHookFailure | undefined): string {
|
|
38
|
+
if (!failure) return "";
|
|
39
|
+
switch (failure.kind) {
|
|
40
|
+
case "exit":
|
|
41
|
+
return `It exited with code ${failure.exitCode}. Output:\n\n${failure.output || "(empty)"}`;
|
|
42
|
+
case "timeout":
|
|
43
|
+
return "It timed out and was killed before completing.";
|
|
44
|
+
case "spawn":
|
|
45
|
+
return `It failed to start: ${failure.spawnError}`;
|
|
46
|
+
default: {
|
|
47
|
+
const _exhaustive: never = failure;
|
|
48
|
+
return _exhaustive satisfies never;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface LifecycleHookResult {
|
|
54
|
+
/**
|
|
55
|
+
* human-readable warning when the hook failed. includes retry guidance:
|
|
56
|
+
* transient spawn/exit errors are worth retrying, timeouts and
|
|
57
|
+
* persistent failures are not. absent when the hook succeeded or was
|
|
58
|
+
* skipped. setup/post-checkout callers surface this verbatim; prepush
|
|
59
|
+
* builds its own message from `failure` instead.
|
|
60
|
+
*/
|
|
61
|
+
warning?: string;
|
|
62
|
+
/**
|
|
63
|
+
* structured failure info — undefined when the hook succeeded or was
|
|
64
|
+
* skipped. lets callers compose their own messaging without parsing the
|
|
65
|
+
* `warning` string.
|
|
66
|
+
*/
|
|
67
|
+
failure?: LifecycleHookFailure;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* execute a lifecycle hook script if one is configured.
|
|
72
|
+
*
|
|
73
|
+
* soft-fails: instead of throwing on hook errors, returns a warning string
|
|
74
|
+
* (and structured failure info) so callers can choose how to surface it
|
|
75
|
+
* (mcp tools relay it to the agent; setup logs it and adds a prompt banner).
|
|
76
|
+
* timeouts are flagged as non-retryable in the warning text.
|
|
77
|
+
*/
|
|
78
|
+
export async function executeLifecycleHook(
|
|
79
|
+
params: ExecuteLifecycleHookParams,
|
|
80
|
+
): Promise<LifecycleHookResult> {
|
|
81
|
+
if (!params.script) return {};
|
|
82
|
+
|
|
83
|
+
log.info(`» executing ${params.event} lifecycle hook...`);
|
|
84
|
+
|
|
85
|
+
// snapshot tracked-file mods BEFORE the hook runs so we can distinguish
|
|
86
|
+
// hook-generated drift from pre-existing work. both hook windows should
|
|
87
|
+
// start clean in normal operation (setup runs before any working-tree
|
|
88
|
+
// writes; checkout_pr refuses to run with a dirty tree), but if that
|
|
89
|
+
// invariant breaks we'd rather warn than discard whatever was there.
|
|
90
|
+
// pre-existing untracked files don't matter here — `git restore --staged
|
|
91
|
+
// --worktree .` never touches untracked files, so they're never at risk.
|
|
92
|
+
const preHookTrackedCount = params.normalizeWorkingTreeAfter
|
|
93
|
+
? (await runGitLines(["diff", "--name-only", "HEAD"])).length
|
|
94
|
+
: 0;
|
|
95
|
+
|
|
96
|
+
// single try/finally so normalization fires on success AND failure paths.
|
|
97
|
+
// a hook that fails partway through (e.g. `pnpm install` updates the
|
|
98
|
+
// lockfile then explodes on a peer-dep conflict) leaves the same kind of
|
|
99
|
+
// drift a successful run does, and the agent will see it next regardless
|
|
100
|
+
// of which path we took. failure-mode messaging is unchanged; the only
|
|
101
|
+
// delta is that we don't return tracked drift to the agent.
|
|
102
|
+
let result: LifecycleHookResult;
|
|
103
|
+
try {
|
|
104
|
+
try {
|
|
105
|
+
const spawnResult = await spawn({
|
|
106
|
+
cmd: "bash",
|
|
107
|
+
args: ["-c", params.script],
|
|
108
|
+
env: process.env,
|
|
109
|
+
timeout: LIFECYCLE_HOOK_TIMEOUT_MS,
|
|
110
|
+
activityTimeout: 0,
|
|
111
|
+
onStdout: (chunk) => process.stdout.write(chunk),
|
|
112
|
+
onStderr: (chunk) => process.stderr.write(chunk),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (spawnResult.exitCode !== 0) {
|
|
116
|
+
const output = (spawnResult.stderr || spawnResult.stdout).trim();
|
|
117
|
+
result = {
|
|
118
|
+
failure: { kind: "exit", output, exitCode: spawnResult.exitCode },
|
|
119
|
+
warning:
|
|
120
|
+
`lifecycle hook '${params.event}' failed with exit code ${spawnResult.exitCode}. ` +
|
|
121
|
+
`output: ${output || "(empty)"}. ` +
|
|
122
|
+
`retry the operation if the failure looks flaky (network blips, transient rate limits). ` +
|
|
123
|
+
`do NOT retry if the script is broken (missing commands, syntax errors) or the error is persistent.`,
|
|
124
|
+
};
|
|
125
|
+
} else {
|
|
126
|
+
log.info(`» ${params.event} lifecycle hook completed successfully`);
|
|
127
|
+
result = {};
|
|
128
|
+
}
|
|
129
|
+
} catch (err) {
|
|
130
|
+
const isTimeout =
|
|
131
|
+
err instanceof SpawnTimeoutError &&
|
|
132
|
+
(err.code === SPAWN_TIMEOUT_CODE || err.code === SPAWN_ACTIVITY_TIMEOUT_CODE);
|
|
133
|
+
if (isTimeout) {
|
|
134
|
+
const minutes = Math.round(LIFECYCLE_HOOK_TIMEOUT_MS / 60000);
|
|
135
|
+
result = {
|
|
136
|
+
failure: { kind: "timeout" },
|
|
137
|
+
warning:
|
|
138
|
+
`lifecycle hook '${params.event}' timed out after ${minutes}min. ` +
|
|
139
|
+
`do NOT retry — the script is likely hung or doing too much work. ` +
|
|
140
|
+
`ask the repo owner to simplify the hook (e.g. move long-running work out of the hook, add caching, or split it).`,
|
|
141
|
+
};
|
|
142
|
+
} else {
|
|
143
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
144
|
+
result = {
|
|
145
|
+
failure: { kind: "spawn", spawnError: msg },
|
|
146
|
+
warning:
|
|
147
|
+
`lifecycle hook '${params.event}' failed to spawn: ${msg}. ` +
|
|
148
|
+
`this is likely a transient failure — retry the operation.`,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
} finally {
|
|
153
|
+
if (params.normalizeWorkingTreeAfter) {
|
|
154
|
+
await normalizeWorkingTreeAfterHook({ event: params.event, preHookTrackedCount });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* discard tracked-file mods left by a lifecycle hook so the agent's next
|
|
162
|
+
* `git status` matches the pre-hook state. untracked files (e.g. a `.env`
|
|
163
|
+
* the hook materialized from a template) are left alone — the agent decides
|
|
164
|
+
* what to do with them. skipped (with a warning) when the tree had
|
|
165
|
+
* pre-existing tracked changes before the hook ran, so pre-existing work
|
|
166
|
+
* is never clobbered. idempotent: a second call on a clean tree is a no-op
|
|
167
|
+
* and stays quiet.
|
|
168
|
+
*/
|
|
169
|
+
async function normalizeWorkingTreeAfterHook(params: {
|
|
170
|
+
event: string;
|
|
171
|
+
preHookTrackedCount: number;
|
|
172
|
+
}): Promise<void> {
|
|
173
|
+
if (params.preHookTrackedCount > 0) {
|
|
174
|
+
log.warning(
|
|
175
|
+
`» working tree had ${params.preHookTrackedCount} pre-existing tracked changes before ${params.event} hook; ` +
|
|
176
|
+
`skipping post-hook normalization to avoid clobbering pre-existing work`,
|
|
177
|
+
);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const trackedCount = (await runGitLines(["diff", "--name-only", "HEAD"])).length;
|
|
181
|
+
if (trackedCount === 0) return;
|
|
182
|
+
await runGit(["restore", "--staged", "--worktree", "."]);
|
|
183
|
+
log.info(`» discarded ${trackedCount} tracked changes from ${params.event} hook`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function runGit(args: string[]): Promise<string> {
|
|
187
|
+
const result = await spawn({ cmd: "git", args, env: process.env, activityTimeout: 0 });
|
|
188
|
+
if (result.exitCode !== 0) {
|
|
189
|
+
throw new Error(
|
|
190
|
+
`git ${args.join(" ")} failed (exit ${result.exitCode}): ${result.stderr.trim() || "(no stderr)"}`,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
return result.stdout;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async function runGitLines(args: string[]): Promise<string[]> {
|
|
197
|
+
return (await runGit(args)).split("\n").filter(Boolean);
|
|
198
|
+
}
|