@neurcode-ai/cli 0.9.44 → 0.9.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/commands/contract.js +47 -0
- package/dist/commands/plan.js +40 -0
- package/dist/commands/ship.js +10 -3
- package/dist/commands/verify.d.ts +2 -0
- package/dist/commands/verify.js +251 -118
- package/dist/index.js +41 -5
- package/dist/utils/advisory-signals.d.ts +20 -0
- package/dist/utils/advisory-signals.js +177 -0
- package/dist/utils/change-contract.d.ts +105 -1
- package/dist/utils/change-contract.js +685 -12
- package/dist/utils/diff-symbols.d.ts +10 -0
- package/dist/utils/diff-symbols.js +218 -0
- package/dist/utils/governance.d.ts +1 -0
- package/dist/utils/governance.js +1 -1
- package/dist/utils/plan-symbols.d.ts +17 -0
- package/dist/utils/plan-symbols.js +209 -0
- package/package.json +6 -14
- package/LICENSE +0 -201
- package/dist/api-client.d.ts.map +0 -1
- package/dist/api-client.js.map +0 -1
- package/dist/commands/allow.d.ts.map +0 -1
- package/dist/commands/allow.js.map +0 -1
- package/dist/commands/apply.d.ts.map +0 -1
- package/dist/commands/apply.js.map +0 -1
- package/dist/commands/approve.d.ts.map +0 -1
- package/dist/commands/approve.js.map +0 -1
- package/dist/commands/ask.d.ts.map +0 -1
- package/dist/commands/ask.js.map +0 -1
- package/dist/commands/audit.d.ts.map +0 -1
- package/dist/commands/audit.js.map +0 -1
- package/dist/commands/bootstrap.d.ts.map +0 -1
- package/dist/commands/bootstrap.js.map +0 -1
- package/dist/commands/brain.d.ts.map +0 -1
- package/dist/commands/brain.js.map +0 -1
- package/dist/commands/check.d.ts.map +0 -1
- package/dist/commands/check.js.map +0 -1
- package/dist/commands/config.d.ts.map +0 -1
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/contract.d.ts.map +0 -1
- package/dist/commands/contract.js.map +0 -1
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/feedback.d.ts.map +0 -1
- package/dist/commands/feedback.js.map +0 -1
- package/dist/commands/guard.d.ts.map +0 -1
- package/dist/commands/guard.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/login.d.ts.map +0 -1
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/logout.d.ts.map +0 -1
- package/dist/commands/logout.js.map +0 -1
- package/dist/commands/map.d.ts.map +0 -1
- package/dist/commands/map.js.map +0 -1
- package/dist/commands/plan-slo.d.ts.map +0 -1
- package/dist/commands/plan-slo.js.map +0 -1
- package/dist/commands/plan.d.ts.map +0 -1
- package/dist/commands/plan.js.map +0 -1
- package/dist/commands/policy.d.ts.map +0 -1
- package/dist/commands/policy.js.map +0 -1
- package/dist/commands/prompt.d.ts.map +0 -1
- package/dist/commands/prompt.js.map +0 -1
- package/dist/commands/refactor.d.ts.map +0 -1
- package/dist/commands/refactor.js.map +0 -1
- package/dist/commands/remediate.d.ts.map +0 -1
- package/dist/commands/remediate.js.map +0 -1
- package/dist/commands/repo.d.ts.map +0 -1
- package/dist/commands/repo.js.map +0 -1
- package/dist/commands/revert.d.ts.map +0 -1
- package/dist/commands/revert.js.map +0 -1
- package/dist/commands/security.d.ts.map +0 -1
- package/dist/commands/security.js.map +0 -1
- package/dist/commands/session.d.ts.map +0 -1
- package/dist/commands/session.js.map +0 -1
- package/dist/commands/ship.d.ts.map +0 -1
- package/dist/commands/ship.js.map +0 -1
- package/dist/commands/simulate.d.ts.map +0 -1
- package/dist/commands/simulate.js.map +0 -1
- package/dist/commands/verify.d.ts.map +0 -1
- package/dist/commands/verify.js.map +0 -1
- package/dist/commands/watch.d.ts.map +0 -1
- package/dist/commands/watch.js.map +0 -1
- package/dist/commands/whoami.d.ts.map +0 -1
- package/dist/commands/whoami.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/rules.d.ts.map +0 -1
- package/dist/rules.js.map +0 -1
- package/dist/services/integrations/TicketService.d.ts.map +0 -1
- package/dist/services/integrations/TicketService.js.map +0 -1
- package/dist/services/mapper/ProjectScanner.d.ts.map +0 -1
- package/dist/services/mapper/ProjectScanner.js.map +0 -1
- package/dist/services/project-knowledge-service.d.ts.map +0 -1
- package/dist/services/project-knowledge-service.js.map +0 -1
- package/dist/services/security/SecurityGuard.d.ts.map +0 -1
- package/dist/services/security/SecurityGuard.js.map +0 -1
- package/dist/services/toolbox-service.d.ts.map +0 -1
- package/dist/services/toolbox-service.js.map +0 -1
- package/dist/services/watch/BlobStore.d.ts.map +0 -1
- package/dist/services/watch/BlobStore.js.map +0 -1
- package/dist/services/watch/CommandPoller.d.ts.map +0 -1
- package/dist/services/watch/CommandPoller.js.map +0 -1
- package/dist/services/watch/Journal.d.ts.map +0 -1
- package/dist/services/watch/Journal.js.map +0 -1
- package/dist/services/watch/Sentinel.d.ts.map +0 -1
- package/dist/services/watch/Sentinel.js.map +0 -1
- package/dist/services/watch/Syncer.d.ts.map +0 -1
- package/dist/services/watch/Syncer.js.map +0 -1
- package/dist/utils/ROILogger.d.ts.map +0 -1
- package/dist/utils/ROILogger.js.map +0 -1
- package/dist/utils/RelevanceScorer.d.ts.map +0 -1
- package/dist/utils/RelevanceScorer.js.map +0 -1
- package/dist/utils/ai-debt-budget.d.ts.map +0 -1
- package/dist/utils/ai-debt-budget.js.map +0 -1
- package/dist/utils/artifact-signature.d.ts.map +0 -1
- package/dist/utils/artifact-signature.js.map +0 -1
- package/dist/utils/ask-cache.d.ts.map +0 -1
- package/dist/utils/ask-cache.js.map +0 -1
- package/dist/utils/box.d.ts.map +0 -1
- package/dist/utils/box.js.map +0 -1
- package/dist/utils/brain-context.d.ts.map +0 -1
- package/dist/utils/brain-context.js.map +0 -1
- package/dist/utils/breakage-simulator.d.ts.map +0 -1
- package/dist/utils/breakage-simulator.js.map +0 -1
- package/dist/utils/change-contract.d.ts.map +0 -1
- package/dist/utils/change-contract.js.map +0 -1
- package/dist/utils/cli-json.d.ts.map +0 -1
- package/dist/utils/cli-json.js.map +0 -1
- package/dist/utils/custom-policy-rules.d.ts.map +0 -1
- package/dist/utils/custom-policy-rules.js.map +0 -1
- package/dist/utils/git.d.ts.map +0 -1
- package/dist/utils/git.js.map +0 -1
- package/dist/utils/gitignore.d.ts.map +0 -1
- package/dist/utils/gitignore.js.map +0 -1
- package/dist/utils/governance.d.ts.map +0 -1
- package/dist/utils/governance.js.map +0 -1
- package/dist/utils/ignore.d.ts.map +0 -1
- package/dist/utils/ignore.js.map +0 -1
- package/dist/utils/manual-approvals.d.ts.map +0 -1
- package/dist/utils/manual-approvals.js.map +0 -1
- package/dist/utils/messages.d.ts.map +0 -1
- package/dist/utils/messages.js.map +0 -1
- package/dist/utils/neurcode-context.d.ts.map +0 -1
- package/dist/utils/neurcode-context.js.map +0 -1
- package/dist/utils/plan-cache.d.ts.map +0 -1
- package/dist/utils/plan-cache.js.map +0 -1
- package/dist/utils/plan-slo.d.ts.map +0 -1
- package/dist/utils/plan-slo.js.map +0 -1
- package/dist/utils/policy-audit.d.ts.map +0 -1
- package/dist/utils/policy-audit.js.map +0 -1
- package/dist/utils/policy-compiler.d.ts.map +0 -1
- package/dist/utils/policy-compiler.js.map +0 -1
- package/dist/utils/policy-exceptions.d.ts.map +0 -1
- package/dist/utils/policy-exceptions.js.map +0 -1
- package/dist/utils/policy-governance.d.ts.map +0 -1
- package/dist/utils/policy-governance.js.map +0 -1
- package/dist/utils/policy-packs.d.ts.map +0 -1
- package/dist/utils/policy-packs.js.map +0 -1
- package/dist/utils/project-detector.d.ts.map +0 -1
- package/dist/utils/project-detector.js.map +0 -1
- package/dist/utils/project-root.d.ts.map +0 -1
- package/dist/utils/project-root.js.map +0 -1
- package/dist/utils/repo-links.d.ts.map +0 -1
- package/dist/utils/repo-links.js.map +0 -1
- package/dist/utils/restore.d.ts.map +0 -1
- package/dist/utils/restore.js.map +0 -1
- package/dist/utils/runtime-guard.d.ts.map +0 -1
- package/dist/utils/runtime-guard.js.map +0 -1
- package/dist/utils/scope-telemetry.d.ts.map +0 -1
- package/dist/utils/scope-telemetry.js.map +0 -1
- package/dist/utils/secret-masking.d.ts.map +0 -1
- package/dist/utils/secret-masking.js.map +0 -1
- package/dist/utils/state.d.ts.map +0 -1
- package/dist/utils/state.js.map +0 -1
- package/dist/utils/tier.d.ts.map +0 -1
- package/dist/utils/tier.js.map +0 -1
- package/dist/utils/user-context.d.ts.map +0 -1
- package/dist/utils/user-context.js.map +0 -1
package/dist/commands/verify.js
CHANGED
|
@@ -51,7 +51,6 @@ const path_1 = require("path");
|
|
|
51
51
|
const fs_1 = require("fs");
|
|
52
52
|
const state_1 = require("../utils/state");
|
|
53
53
|
const ROILogger_1 = require("../utils/ROILogger");
|
|
54
|
-
const box_1 = require("../utils/box");
|
|
55
54
|
const ignore_1 = require("../utils/ignore");
|
|
56
55
|
const project_root_1 = require("../utils/project-root");
|
|
57
56
|
const brain_context_1 = require("../utils/brain-context");
|
|
@@ -64,6 +63,8 @@ const policy_audit_1 = require("../utils/policy-audit");
|
|
|
64
63
|
const governance_1 = require("../utils/governance");
|
|
65
64
|
const policy_compiler_1 = require("../utils/policy-compiler");
|
|
66
65
|
const change_contract_1 = require("../utils/change-contract");
|
|
66
|
+
const diff_symbols_1 = require("../utils/diff-symbols");
|
|
67
|
+
const advisory_signals_1 = require("../utils/advisory-signals");
|
|
67
68
|
const runtime_guard_1 = require("../utils/runtime-guard");
|
|
68
69
|
const artifact_signature_1 = require("../utils/artifact-signature");
|
|
69
70
|
const policy_1 = require("@neurcode-ai/policy");
|
|
@@ -820,9 +821,13 @@ function isGitRepository(cwd) {
|
|
|
820
821
|
}
|
|
821
822
|
}
|
|
822
823
|
function isSignedAiLogsRequired(orgGovernanceSettings) {
|
|
823
|
-
|
|
824
|
-
isEnabledFlag(process.env.
|
|
825
|
-
|
|
824
|
+
const explicitRequirement = isEnabledFlag(process.env.NEURCODE_GOVERNANCE_REQUIRE_SIGNED_LOGS) ||
|
|
825
|
+
isEnabledFlag(process.env.NEURCODE_AI_LOG_REQUIRE_SIGNED);
|
|
826
|
+
if (explicitRequirement) {
|
|
827
|
+
return true;
|
|
828
|
+
}
|
|
829
|
+
const honorOrgRequirement = isEnabledFlag(process.env.NEURCODE_GOVERNANCE_ENFORCE_ORG_SIGNED_LOG_REQUIREMENT);
|
|
830
|
+
return honorOrgRequirement && orgGovernanceSettings?.requireSignedAiLogs === true;
|
|
826
831
|
}
|
|
827
832
|
function policyLockMismatchMessage(mismatches) {
|
|
828
833
|
if (mismatches.length === 0) {
|
|
@@ -1011,6 +1016,7 @@ async function executePolicyOnlyMode(options, diffFiles, ignoreFilter, projectRo
|
|
|
1011
1016
|
if (!options.json) {
|
|
1012
1017
|
console.log(chalk.cyan('🛡️ General Governance mode (policy only, no plan linked)\n'));
|
|
1013
1018
|
}
|
|
1019
|
+
const signedLogsRequired = isSignedAiLogsRequired(orgGovernanceSettings);
|
|
1014
1020
|
const governanceAnalysis = (0, governance_1.evaluateGovernance)({
|
|
1015
1021
|
projectRoot,
|
|
1016
1022
|
task: 'Policy-only verification',
|
|
@@ -1018,6 +1024,7 @@ async function executePolicyOnlyMode(options, diffFiles, ignoreFilter, projectRo
|
|
|
1018
1024
|
diffFiles,
|
|
1019
1025
|
contextCandidates: diffFiles.map((file) => file.path),
|
|
1020
1026
|
orgGovernance: orgGovernanceSettings,
|
|
1027
|
+
requireSignedAiLogs: signedLogsRequired,
|
|
1021
1028
|
signingKey: aiLogSigningKey,
|
|
1022
1029
|
signingKeyId: aiLogSigningKeyId,
|
|
1023
1030
|
signingKeys: aiLogSigningKeys,
|
|
@@ -1028,7 +1035,6 @@ async function executePolicyOnlyMode(options, diffFiles, ignoreFilter, projectRo
|
|
|
1028
1035
|
changeContract: changeContractSummary,
|
|
1029
1036
|
});
|
|
1030
1037
|
const contextPolicyViolations = governanceAnalysis.contextPolicy.violations.filter((item) => !ignoreFilter(item.file));
|
|
1031
|
-
const signedLogsRequired = isSignedAiLogsRequired(orgGovernanceSettings);
|
|
1032
1038
|
if (signedLogsRequired && !governanceAnalysis.aiChangeLogIntegrity.valid) {
|
|
1033
1039
|
const message = `AI change-log integrity check failed: ${governanceAnalysis.aiChangeLogIntegrity.issues.join('; ') || 'unknown issue'}`;
|
|
1034
1040
|
if (options.json) {
|
|
@@ -2245,6 +2251,7 @@ async function verifyCommand(options) {
|
|
|
2245
2251
|
diffFiles,
|
|
2246
2252
|
contextCandidates: diffFiles.map((file) => file.path),
|
|
2247
2253
|
orgGovernance: orgGovernanceSettings,
|
|
2254
|
+
requireSignedAiLogs: signedLogsRequired,
|
|
2248
2255
|
signingKey: aiLogSigningKey,
|
|
2249
2256
|
signingKeyId: aiLogSigningKeyId,
|
|
2250
2257
|
signingKeys: aiLogSigningKeys,
|
|
@@ -2308,6 +2315,9 @@ async function verifyCommand(options) {
|
|
|
2308
2315
|
console.log(chalk.cyan('\n📊 Analyzing changes against plan...'));
|
|
2309
2316
|
console.log(chalk.dim(` Found ${summary.totalFiles} file(s) changed`));
|
|
2310
2317
|
console.log(chalk.dim(` ${summary.totalAdded} lines added, ${summary.totalRemoved} lines removed\n`));
|
|
2318
|
+
if (options.demo) {
|
|
2319
|
+
console.log(chalk.dim(' Demo mode enabled: showing extra context while keeping drift output short and grouped.\n'));
|
|
2320
|
+
}
|
|
2311
2321
|
}
|
|
2312
2322
|
const runPolicyOnlyModeAndExit = async (source) => {
|
|
2313
2323
|
const exitCode = await executePolicyOnlyMode(options, diffFiles, shouldIgnore, projectRoot, config, client, source, scopeTelemetry, projectId || undefined, orgGovernanceSettings, aiLogSigningKey, aiLogSigningKeyId, aiLogSigningKeys, aiLogSigner, compiledPolicyMetadata, changeContractSummary);
|
|
@@ -2400,10 +2410,104 @@ async function verifyCommand(options) {
|
|
|
2400
2410
|
});
|
|
2401
2411
|
process.exit(1);
|
|
2402
2412
|
}
|
|
2403
|
-
|
|
2404
|
-
|
|
2413
|
+
let autoContractPath = null;
|
|
2414
|
+
if (!changeContractRead.contract && !strictArtifactMode) {
|
|
2415
|
+
try {
|
|
2416
|
+
const fallbackPlanId = `advisory_${Date.now()}`;
|
|
2417
|
+
const advisoryContract = buildMinimalAdvisoryContractFromDiff(diffFiles, fallbackPlanId);
|
|
2418
|
+
autoContractPath = (0, change_contract_1.writeChangeContract)(projectRoot, advisoryContract, options.changeContract);
|
|
2419
|
+
changeContractSummary = {
|
|
2420
|
+
path: autoContractPath,
|
|
2421
|
+
exists: true,
|
|
2422
|
+
enforced: false,
|
|
2423
|
+
valid: true,
|
|
2424
|
+
planId: advisoryContract.planId,
|
|
2425
|
+
contractId: advisoryContract.contractId,
|
|
2426
|
+
coverage: {
|
|
2427
|
+
expectedFiles: advisoryContract.expectedFiles.length,
|
|
2428
|
+
changedFiles: diffFiles.length,
|
|
2429
|
+
outOfContractFiles: 0,
|
|
2430
|
+
missingExpectedFiles: 0,
|
|
2431
|
+
blockedFilesTouched: 0,
|
|
2432
|
+
actionMismatches: 0,
|
|
2433
|
+
expectedSymbols: advisoryContract.expectedSymbols?.length || 0,
|
|
2434
|
+
changedSymbols: 0,
|
|
2435
|
+
missingExpectedSymbols: 0,
|
|
2436
|
+
blockedSymbolsTouched: 0,
|
|
2437
|
+
symbolActionMismatches: 0,
|
|
2438
|
+
symbolRenameMatches: 0,
|
|
2439
|
+
toleratedUnexpectedFiles: 0,
|
|
2440
|
+
toleratedMissingExpectedSymbols: 0,
|
|
2441
|
+
},
|
|
2442
|
+
signature: changeContractSummary.signature,
|
|
2443
|
+
violations: [],
|
|
2444
|
+
};
|
|
2445
|
+
}
|
|
2446
|
+
catch {
|
|
2447
|
+
autoContractPath = null;
|
|
2448
|
+
}
|
|
2405
2449
|
}
|
|
2406
|
-
|
|
2450
|
+
const message = 'No plan linked yet. Ran advisory verification for quick first-run experience. ' +
|
|
2451
|
+
'Use `neurcode plan` and `neurcode contract import --auto-detect --write-change-contract` for full enforcement.';
|
|
2452
|
+
const advisorySignals = (0, advisory_signals_1.evaluateAdvisorySignals)({
|
|
2453
|
+
diffFiles,
|
|
2454
|
+
summary,
|
|
2455
|
+
});
|
|
2456
|
+
const advisoryWarnCount = advisorySignals.filter((item) => item.severity === 'warn').length;
|
|
2457
|
+
const advisoryVerdict = advisoryWarnCount > 0 ? 'WARN' : 'PASS';
|
|
2458
|
+
const advisoryGrade = advisoryWarnCount > 0 ? 'C' : 'B';
|
|
2459
|
+
const advisoryScore = advisoryWarnCount > 0 ? 60 : 70;
|
|
2460
|
+
const advisoryViolations = advisorySignals.map((item) => ({
|
|
2461
|
+
file: item.files[0] || '.',
|
|
2462
|
+
rule: `advisory:${item.code.toLowerCase()}`,
|
|
2463
|
+
severity: item.severity === 'warn' ? 'warn' : 'allow',
|
|
2464
|
+
message: `${item.title}: ${item.detail}`,
|
|
2465
|
+
}));
|
|
2466
|
+
recordVerifyEvent(advisoryVerdict, `advisory_missing_plan;signals=${advisorySignals.length};warn=${advisoryWarnCount}`, diffFiles.map((f) => f.path));
|
|
2467
|
+
if (options.json) {
|
|
2468
|
+
emitVerifyJson({
|
|
2469
|
+
grade: advisoryGrade,
|
|
2470
|
+
score: advisoryScore,
|
|
2471
|
+
verdict: advisoryVerdict,
|
|
2472
|
+
violations: advisoryViolations,
|
|
2473
|
+
adherenceScore: advisoryScore,
|
|
2474
|
+
bloatCount: 0,
|
|
2475
|
+
bloatFiles: [],
|
|
2476
|
+
plannedFilesModified: 0,
|
|
2477
|
+
totalPlannedFiles: 0,
|
|
2478
|
+
message,
|
|
2479
|
+
scopeGuardPassed: true,
|
|
2480
|
+
mode: 'advisory_missing_plan',
|
|
2481
|
+
advisoryMode: true,
|
|
2482
|
+
advisorySignals,
|
|
2483
|
+
policyOnly: true,
|
|
2484
|
+
policyOnlySource: 'fallback_missing_plan',
|
|
2485
|
+
...(autoContractPath
|
|
2486
|
+
? {
|
|
2487
|
+
changeContract: {
|
|
2488
|
+
...changeContractSummary,
|
|
2489
|
+
path: autoContractPath,
|
|
2490
|
+
},
|
|
2491
|
+
}
|
|
2492
|
+
: {
|
|
2493
|
+
changeContract: changeContractSummary,
|
|
2494
|
+
}),
|
|
2495
|
+
});
|
|
2496
|
+
}
|
|
2497
|
+
else {
|
|
2498
|
+
printFirstRunAdvisoryMessage(options.demo === true);
|
|
2499
|
+
printAdvisorySignals(advisorySignals, options.demo === true);
|
|
2500
|
+
if (autoContractPath) {
|
|
2501
|
+
console.log(chalk.green(`✅ Auto-generated minimal advisory contract: ${autoContractPath}`));
|
|
2502
|
+
}
|
|
2503
|
+
else if (!changeContractRead.contract) {
|
|
2504
|
+
console.log(chalk.yellow('⚠️ Could not auto-generate advisory contract; continuing without contract.'));
|
|
2505
|
+
}
|
|
2506
|
+
console.log(chalk.dim('Next steps: neurcode plan "<intent>"'));
|
|
2507
|
+
console.log(chalk.dim(' neurcode contract import --auto-detect --write-change-contract'));
|
|
2508
|
+
console.log(chalk.dim(`\nSummary: ${message}\n`));
|
|
2509
|
+
}
|
|
2510
|
+
process.exit(0);
|
|
2407
2511
|
}
|
|
2408
2512
|
if (!planId) {
|
|
2409
2513
|
throw new Error('Plan ID resolution failed unexpectedly');
|
|
@@ -2449,6 +2553,7 @@ async function verifyCommand(options) {
|
|
|
2449
2553
|
diffFiles,
|
|
2450
2554
|
contextCandidates: planFiles,
|
|
2451
2555
|
orgGovernance: orgGovernanceSettings,
|
|
2556
|
+
requireSignedAiLogs: signedLogsRequired,
|
|
2452
2557
|
signingKey: aiLogSigningKey,
|
|
2453
2558
|
signingKeyId: aiLogSigningKeyId,
|
|
2454
2559
|
signingKeys: aiLogSigningKeys,
|
|
@@ -2997,6 +3102,7 @@ async function verifyCommand(options) {
|
|
|
2997
3102
|
})),
|
|
2998
3103
|
})),
|
|
2999
3104
|
}));
|
|
3105
|
+
const changedSymbols = (0, diff_symbols_1.extractDeclaredSymbolsFromDiff)(diffFiles);
|
|
3000
3106
|
const compiledIntentProof = (0, governance_runtime_1.compileDeterministicConstraints)({
|
|
3001
3107
|
intentConstraints: intentConstraintsForVerification,
|
|
3002
3108
|
policyRules: deterministicPolicyRules,
|
|
@@ -3068,6 +3174,16 @@ async function verifyCommand(options) {
|
|
|
3068
3174
|
? (0, change_contract_1.evaluateChangeContract)(changeContractRead.contract, {
|
|
3069
3175
|
planId: finalPlanId,
|
|
3070
3176
|
changedFiles: changedFiles.map((file) => file.path),
|
|
3177
|
+
changedFileEntries: changedFiles.map((file) => ({
|
|
3178
|
+
path: file.path,
|
|
3179
|
+
changeType: file.changeType,
|
|
3180
|
+
})),
|
|
3181
|
+
changedSymbols: changedSymbols.map((symbol) => ({
|
|
3182
|
+
name: symbol.name,
|
|
3183
|
+
type: symbol.type,
|
|
3184
|
+
action: symbol.action,
|
|
3185
|
+
file: symbol.file,
|
|
3186
|
+
})),
|
|
3071
3187
|
policyLockFingerprint: (0, policy_packs_1.readPolicyLockFile)(projectRoot).lock?.effective.fingerprint || null,
|
|
3072
3188
|
compiledPolicyFingerprint: effectiveCompiledPolicy?.fingerprint || null,
|
|
3073
3189
|
})
|
|
@@ -3086,6 +3202,8 @@ async function verifyCommand(options) {
|
|
|
3086
3202
|
code: item.code,
|
|
3087
3203
|
message: item.message,
|
|
3088
3204
|
file: item.file,
|
|
3205
|
+
symbol: item.symbol,
|
|
3206
|
+
symbolType: item.symbolType,
|
|
3089
3207
|
expected: item.expected,
|
|
3090
3208
|
actual: item.actual,
|
|
3091
3209
|
})),
|
|
@@ -3097,9 +3215,8 @@ async function verifyCommand(options) {
|
|
|
3097
3215
|
severity: 'block',
|
|
3098
3216
|
message: item.message,
|
|
3099
3217
|
}));
|
|
3100
|
-
const message = `
|
|
3101
|
-
.
|
|
3102
|
-
.join('; ')}`;
|
|
3218
|
+
const message = `Implementation deviates from intended contract (` +
|
|
3219
|
+
`${changeContractEvaluation.violations.length} violation(s)).`;
|
|
3103
3220
|
if (options.json) {
|
|
3104
3221
|
emitVerifyJson({
|
|
3105
3222
|
grade: 'F',
|
|
@@ -3120,11 +3237,7 @@ async function verifyCommand(options) {
|
|
|
3120
3237
|
});
|
|
3121
3238
|
}
|
|
3122
3239
|
else {
|
|
3123
|
-
|
|
3124
|
-
changeContractEvaluation.violations.forEach((item) => {
|
|
3125
|
-
console.log(chalk.red(` • ${item.message}`));
|
|
3126
|
-
});
|
|
3127
|
-
console.log(chalk.dim(` Contract path: ${changeContractRead.path}`));
|
|
3240
|
+
displayChangeContractDrift(changeContractSummary, { advisory: false });
|
|
3128
3241
|
}
|
|
3129
3242
|
await recordVerificationIfRequested(options, config, {
|
|
3130
3243
|
grade: 'F',
|
|
@@ -3148,13 +3261,7 @@ async function verifyCommand(options) {
|
|
|
3148
3261
|
process.exit(2);
|
|
3149
3262
|
}
|
|
3150
3263
|
else if (!changeContractEvaluation.valid && !options.json) {
|
|
3151
|
-
|
|
3152
|
-
changeContractEvaluation.violations.slice(0, 5).forEach((item) => {
|
|
3153
|
-
console.log(chalk.yellow(` • ${item.message}`));
|
|
3154
|
-
});
|
|
3155
|
-
if (changeContractEvaluation.violations.length > 5) {
|
|
3156
|
-
console.log(chalk.dim(` ... ${changeContractEvaluation.violations.length - 5} more violation(s)`));
|
|
3157
|
-
}
|
|
3264
|
+
displayChangeContractDrift(changeContractSummary, { advisory: true });
|
|
3158
3265
|
}
|
|
3159
3266
|
}
|
|
3160
3267
|
// Call verify API
|
|
@@ -3912,111 +4019,137 @@ function displayGovernanceInsights(governance, options = {}) {
|
|
|
3912
4019
|
});
|
|
3913
4020
|
}
|
|
3914
4021
|
}
|
|
4022
|
+
function displayChangeContractDrift(summary, options = { advisory: false }) {
|
|
4023
|
+
const groups = (0, change_contract_1.groupChangeContractViolations)(summary.violations.map((item) => ({
|
|
4024
|
+
code: item.code,
|
|
4025
|
+
message: item.message,
|
|
4026
|
+
...(item.file ? { file: item.file } : {}),
|
|
4027
|
+
...(item.symbol ? { symbol: item.symbol } : {}),
|
|
4028
|
+
...(item.symbolType ? { symbolType: item.symbolType } : {}),
|
|
4029
|
+
...(item.expected ? { expected: item.expected } : {}),
|
|
4030
|
+
...(item.actual ? { actual: item.actual } : {}),
|
|
4031
|
+
})));
|
|
4032
|
+
if (groups.length === 0)
|
|
4033
|
+
return;
|
|
4034
|
+
const maxItemsPerGroup = options.maxItemsPerGroup ?? 12;
|
|
4035
|
+
const header = options.advisory
|
|
4036
|
+
? chalk.yellow('\nWARN ⚠️ Change contract drift detected')
|
|
4037
|
+
: chalk.red('\nFAIL ❌ Change contract enforcement failed');
|
|
4038
|
+
console.log(header);
|
|
4039
|
+
for (const group of groups) {
|
|
4040
|
+
console.log(chalk.white(`\n${group.title}:`));
|
|
4041
|
+
group.items.slice(0, maxItemsPerGroup).forEach((entry) => {
|
|
4042
|
+
console.log(` - ${entry}`);
|
|
4043
|
+
});
|
|
4044
|
+
if (group.items.length > maxItemsPerGroup) {
|
|
4045
|
+
console.log(chalk.dim(` - ... ${group.items.length - maxItemsPerGroup} more`));
|
|
4046
|
+
}
|
|
4047
|
+
console.log(chalk.dim(` Why it matters: ${group.impact}`));
|
|
4048
|
+
}
|
|
4049
|
+
console.log(chalk.dim('\nSummary:'));
|
|
4050
|
+
console.log(chalk.dim('Implementation deviates from intended contract.'));
|
|
4051
|
+
console.log(chalk.dim(`Contract path: ${summary.path}`));
|
|
4052
|
+
}
|
|
3915
4053
|
/**
|
|
3916
4054
|
* Display verification results in a formatted report card
|
|
3917
4055
|
*/
|
|
3918
4056
|
function displayVerifyResults(result, policyViolations) {
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
// Bloat drops grade by one letter (B -> C, C -> D, D -> F)
|
|
3937
|
-
if (result.bloatCount > 0) {
|
|
3938
|
-
if (baseGrade === 'B')
|
|
3939
|
-
baseGrade = 'C';
|
|
3940
|
-
else if (baseGrade === 'C')
|
|
3941
|
-
baseGrade = 'D';
|
|
3942
|
-
else if (baseGrade === 'D')
|
|
3943
|
-
baseGrade = 'F';
|
|
3944
|
-
}
|
|
3945
|
-
grade = baseGrade;
|
|
3946
|
-
gradeColor = chalk.yellow;
|
|
3947
|
-
}
|
|
3948
|
-
else {
|
|
3949
|
-
grade = 'F';
|
|
3950
|
-
gradeColor = chalk.red;
|
|
3951
|
-
}
|
|
3952
|
-
// Calculate estimated time saved (5 minutes per VERIFY_PASS)
|
|
3953
|
-
const estimatedMinutesSaved = result.verdict === 'PASS' ? 5 : 0;
|
|
3954
|
-
// Calculate policy compliance percentage
|
|
3955
|
-
const policyCompliance = result.bloatCount === 0 ? 100 : Math.max(0, 100 - (result.bloatCount * 10));
|
|
3956
|
-
// Display Governance Badge for PASS and FAIL verdicts (high visibility)
|
|
3957
|
-
if (result.verdict === 'PASS' || result.verdict === 'FAIL') {
|
|
3958
|
-
console.log('\n');
|
|
3959
|
-
const borderColor = result.verdict === 'PASS' ? 'green' : 'red';
|
|
3960
|
-
const gradeColorFunc = result.verdict === 'PASS' ? chalk.green.bold : chalk.red.bold;
|
|
3961
|
-
const badgeContent = [
|
|
3962
|
-
`${chalk.bold.white('Governance Badge')}`,
|
|
3963
|
-
'',
|
|
3964
|
-
`${chalk.cyan('Grade:')} ${gradeColorFunc(grade)} ${chalk.dim(`(${result.adherenceScore}%)`)}`,
|
|
3965
|
-
result.verdict === 'PASS' ? `${chalk.cyan('Estimated Time Saved:')} ${chalk.green.bold(`${estimatedMinutesSaved}m`)}` : '',
|
|
3966
|
-
`${chalk.cyan('Policy Compliance:')} ${result.verdict === 'PASS' ? chalk.green.bold(`${policyCompliance}%`) : chalk.red.bold(`${policyCompliance}%`)}`,
|
|
3967
|
-
].filter(line => line !== '').join('\n');
|
|
3968
|
-
console.log((0, box_1.createBox)(badgeContent, {
|
|
3969
|
-
borderColor,
|
|
3970
|
-
titleColor: 'white',
|
|
3971
|
-
padding: 2,
|
|
3972
|
-
}));
|
|
3973
|
-
console.log('');
|
|
3974
|
-
}
|
|
3975
|
-
console.log(chalk.bold.cyan('📋 Plan Adherence Report\n'));
|
|
3976
|
-
console.log('━'.repeat(50));
|
|
3977
|
-
const scoreDisplay = gradeColor(`Grade: ${grade} (${result.adherenceScore}%)`);
|
|
3978
|
-
if (result.verdict === 'PASS') {
|
|
3979
|
-
console.log(chalk.green('✅'), scoreDisplay);
|
|
4057
|
+
const verdictLabel = result.verdict === 'PASS'
|
|
4058
|
+
? chalk.green('PASS ✅')
|
|
4059
|
+
: result.verdict === 'WARN'
|
|
4060
|
+
? chalk.yellow('WARN ⚠️')
|
|
4061
|
+
: chalk.red('FAIL ❌');
|
|
4062
|
+
const plannedText = `${result.plannedFilesModified}/${result.totalPlannedFiles}`;
|
|
4063
|
+
console.log(`\n${verdictLabel}`);
|
|
4064
|
+
console.log(chalk.dim(`Plan adherence: ${plannedText} files (${result.adherenceScore}%)`));
|
|
4065
|
+
const maxItems = 20;
|
|
4066
|
+
if (result.bloatCount > 0) {
|
|
4067
|
+
console.log(chalk.red('\nOut-of-scope changes:'));
|
|
4068
|
+
result.bloatFiles.slice(0, maxItems).forEach((file) => {
|
|
4069
|
+
console.log(` - ${file}`);
|
|
4070
|
+
});
|
|
4071
|
+
if (result.bloatFiles.length > maxItems) {
|
|
4072
|
+
console.log(chalk.dim(` - ... ${result.bloatFiles.length - maxItems} more`));
|
|
4073
|
+
}
|
|
3980
4074
|
}
|
|
3981
|
-
|
|
3982
|
-
|
|
4075
|
+
if (policyViolations && policyViolations.length > 0) {
|
|
4076
|
+
const blocking = policyViolations.filter((item) => item.severity === 'block');
|
|
4077
|
+
const warnings = policyViolations.filter((item) => item.severity !== 'block');
|
|
4078
|
+
if (blocking.length > 0) {
|
|
4079
|
+
console.log(chalk.red('\nBlocking policy violations:'));
|
|
4080
|
+
blocking.slice(0, maxItems).forEach((item) => {
|
|
4081
|
+
console.log(` - ${item.file}: ${item.message || item.rule}`);
|
|
4082
|
+
});
|
|
4083
|
+
if (blocking.length > maxItems) {
|
|
4084
|
+
console.log(chalk.dim(` - ... ${blocking.length - maxItems} more`));
|
|
4085
|
+
}
|
|
4086
|
+
}
|
|
4087
|
+
if (warnings.length > 0) {
|
|
4088
|
+
console.log(chalk.yellow('\nPolicy warnings:'));
|
|
4089
|
+
warnings.slice(0, maxItems).forEach((item) => {
|
|
4090
|
+
console.log(` - ${item.file}: ${item.message || item.rule}`);
|
|
4091
|
+
});
|
|
4092
|
+
if (warnings.length > maxItems) {
|
|
4093
|
+
console.log(chalk.dim(` - ... ${warnings.length - maxItems} more`));
|
|
4094
|
+
}
|
|
4095
|
+
}
|
|
3983
4096
|
}
|
|
3984
|
-
|
|
3985
|
-
console.log(chalk.
|
|
4097
|
+
if (result.bloatCount === 0 && (!policyViolations || policyViolations.length === 0)) {
|
|
4098
|
+
console.log(chalk.green('\nNo drift detected.'));
|
|
3986
4099
|
}
|
|
3987
|
-
console.log(
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
console.log(
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
});
|
|
4100
|
+
console.log(chalk.dim(`\nSummary: ${result.message}\n`));
|
|
4101
|
+
}
|
|
4102
|
+
function printFirstRunAdvisoryMessage(demoMode) {
|
|
4103
|
+
console.log(chalk.cyan('\nNeurcode first-run advisory mode'));
|
|
4104
|
+
console.log(chalk.dim('Neurcode checks if your AI-generated code matches your intended plan.'));
|
|
4105
|
+
console.log(chalk.dim('To get full enforcement:'));
|
|
4106
|
+
console.log(chalk.dim('1. Define a plan'));
|
|
4107
|
+
console.log(chalk.dim('2. Generate a contract'));
|
|
4108
|
+
console.log(chalk.dim('Running in advisory mode for now.\n'));
|
|
4109
|
+
if (demoMode) {
|
|
4110
|
+
console.log(chalk.dim('Demo mode: this run is intentionally non-blocking to make evaluation easy.'));
|
|
3999
4111
|
}
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4112
|
+
}
|
|
4113
|
+
function printAdvisorySignals(signals, demoMode) {
|
|
4114
|
+
if (signals.length === 0) {
|
|
4115
|
+
if (demoMode) {
|
|
4116
|
+
console.log(chalk.dim('No high-signal advisory findings detected for this diff.'));
|
|
4117
|
+
}
|
|
4118
|
+
return;
|
|
4003
4119
|
}
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
console.log(label);
|
|
4012
|
-
policyViolations.forEach(v => {
|
|
4013
|
-
const lineColor = v.severity === 'block' ? chalk.red : chalk.yellow;
|
|
4014
|
-
console.log(lineColor(` • ${v.file}: ${v.message || v.rule}`));
|
|
4120
|
+
console.log(chalk.yellow('\nAdvisory findings (non-blocking):'));
|
|
4121
|
+
for (const signal of signals) {
|
|
4122
|
+
const severityLabel = signal.severity === 'warn' ? chalk.yellow('[warn]') : chalk.dim('[info]');
|
|
4123
|
+
console.log(`${severityLabel} ${signal.title}`);
|
|
4124
|
+
console.log(chalk.dim(` ${signal.detail}`));
|
|
4125
|
+
signal.files.forEach((file) => {
|
|
4126
|
+
console.log(chalk.dim(` - ${file}`));
|
|
4015
4127
|
});
|
|
4016
4128
|
}
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4129
|
+
}
|
|
4130
|
+
function buildMinimalAdvisoryContractFromDiff(diffFiles, fallbackPlanId) {
|
|
4131
|
+
const expectedFiles = [...new Set(diffFiles.map((file) => toUnixPath(file.path)).filter(Boolean))];
|
|
4132
|
+
const planFiles = expectedFiles.map((path) => {
|
|
4133
|
+
const entry = diffFiles.find((file) => toUnixPath(file.path) === path);
|
|
4134
|
+
const changeType = entry?.changeType;
|
|
4135
|
+
const action = changeType === 'add' ? 'CREATE' : 'MODIFY';
|
|
4136
|
+
return {
|
|
4137
|
+
path,
|
|
4138
|
+
action: action,
|
|
4139
|
+
reason: 'Auto-generated advisory baseline from current diff',
|
|
4140
|
+
};
|
|
4141
|
+
});
|
|
4142
|
+
return (0, change_contract_1.createChangeContract)({
|
|
4143
|
+
planId: fallbackPlanId,
|
|
4144
|
+
intent: 'Advisory baseline generated from current repository diff',
|
|
4145
|
+
expectedFiles,
|
|
4146
|
+
planFiles,
|
|
4147
|
+
options: {
|
|
4148
|
+
enforceExpectedFiles: false,
|
|
4149
|
+
enforceActionMatching: false,
|
|
4150
|
+
enforceExpectedSymbols: false,
|
|
4151
|
+
enforceSymbolActionMatching: false,
|
|
4152
|
+
},
|
|
4153
|
+
});
|
|
4021
4154
|
}
|
|
4022
4155
|
//# sourceMappingURL=verify.js.map
|
package/dist/index.js
CHANGED
|
@@ -62,12 +62,15 @@ catch (error) {
|
|
|
62
62
|
const program = new commander_1.Command();
|
|
63
63
|
const CORE_WORKFLOW_STEPS = [
|
|
64
64
|
'1) neurcode init',
|
|
65
|
-
'2) neurcode
|
|
66
|
-
'3) neurcode
|
|
67
|
-
'4) neurcode
|
|
68
|
-
'5) neurcode ship "Goal" --max-fix-attempts 2',
|
|
65
|
+
'2) neurcode login',
|
|
66
|
+
'3) neurcode verify --plan-id <id> --enforce-change-contract',
|
|
67
|
+
'4) neurcode fix --plan-id <id> (optional)',
|
|
69
68
|
];
|
|
70
69
|
const ADVANCED_WORKFLOW_HINTS = [
|
|
70
|
+
'neurcode plan "Describe the change"',
|
|
71
|
+
'neurcode contract import --auto-detect --write-change-contract',
|
|
72
|
+
'neurcode prompt',
|
|
73
|
+
'neurcode ship "Goal" --max-fix-attempts 2',
|
|
71
74
|
'neurcode ask "<question>"',
|
|
72
75
|
'neurcode simulate --base origin/main',
|
|
73
76
|
'neurcode guard start && neurcode guard check --staged',
|
|
@@ -121,7 +124,7 @@ showWelcomeIfNeeded().catch(() => {
|
|
|
121
124
|
});
|
|
122
125
|
program
|
|
123
126
|
.command('start')
|
|
124
|
-
.description('Show guided Neurcode flow (init ->
|
|
127
|
+
.description('Show guided Neurcode flow (init -> login -> verify -> fix)')
|
|
125
128
|
.option('--run-init', 'Run `neurcode init` immediately after showing the guide')
|
|
126
129
|
.option('--json', 'Output machine-readable onboarding metadata')
|
|
127
130
|
.action(async (options) => {
|
|
@@ -643,6 +646,37 @@ program
|
|
|
643
646
|
json: options.json === true,
|
|
644
647
|
});
|
|
645
648
|
});
|
|
649
|
+
program
|
|
650
|
+
.command('fix')
|
|
651
|
+
.description('Primary alias for remediation loop (verify -> fix -> verify)')
|
|
652
|
+
.option('--goal <text>', 'Goal text for remediation loop')
|
|
653
|
+
.option('--plan-id <id>', 'Plan ID for verify scope checks')
|
|
654
|
+
.option('--project-id <id>', 'Project ID override')
|
|
655
|
+
.option('--max-fix-attempts <n>', 'Maximum remediation attempts (default: 2)', (val) => parseInt(val, 10))
|
|
656
|
+
.option('--policy-only', 'Run in policy-only verification mode')
|
|
657
|
+
.option('--require-plan', 'Fail verify if plan context is missing')
|
|
658
|
+
.option('--strict-artifacts', 'Require deterministic compiled-policy/change-contract artifacts')
|
|
659
|
+
.option('--no-strict-artifacts', 'Disable strict deterministic artifact enforcement')
|
|
660
|
+
.option('--enforce-change-contract', 'Require change contract enforcement')
|
|
661
|
+
.option('--no-enforce-change-contract', 'Disable change contract enforcement')
|
|
662
|
+
.option('--require-runtime-guard', 'Require runtime guard checks before each remediation attempt')
|
|
663
|
+
.option('--no-record', 'Disable cloud recording during verify/ship runs')
|
|
664
|
+
.option('--json', 'Output machine-readable JSON')
|
|
665
|
+
.action((options) => {
|
|
666
|
+
(0, remediate_1.remediateCommand)({
|
|
667
|
+
goal: options.goal,
|
|
668
|
+
planId: options.planId,
|
|
669
|
+
projectId: options.projectId,
|
|
670
|
+
maxFixAttempts: Number.isFinite(options.maxFixAttempts) ? options.maxFixAttempts : undefined,
|
|
671
|
+
policyOnly: options.policyOnly === true,
|
|
672
|
+
requirePlan: options.requirePlan === true,
|
|
673
|
+
strictArtifacts: options.strictArtifacts !== false,
|
|
674
|
+
enforceChangeContract: options.enforceChangeContract !== false,
|
|
675
|
+
requireRuntimeGuard: options.requireRuntimeGuard === true,
|
|
676
|
+
noRecord: options.record === false,
|
|
677
|
+
json: options.json === true,
|
|
678
|
+
});
|
|
679
|
+
});
|
|
646
680
|
program
|
|
647
681
|
.command('verify')
|
|
648
682
|
.description('Verify plan adherence - Compare current changes against an Architect Plan')
|
|
@@ -668,6 +702,7 @@ program
|
|
|
668
702
|
.option('--head', 'Verify changes against HEAD')
|
|
669
703
|
.option('--base <ref>', 'Verify changes against a specific base ref')
|
|
670
704
|
.option('--explain', 'Include AI change justification details in human-readable output')
|
|
705
|
+
.option('--demo', 'Demo mode: print extra explanatory output')
|
|
671
706
|
.option('--json', 'Output results as JSON')
|
|
672
707
|
.option('--record', 'Report verification results to Neurcode Cloud')
|
|
673
708
|
.option('--api-key <key>', 'Neurcode API Key (overrides config and env var)')
|
|
@@ -679,6 +714,7 @@ program
|
|
|
679
714
|
staged: options.staged,
|
|
680
715
|
head: options.head,
|
|
681
716
|
base: options.base,
|
|
717
|
+
demo: options.demo === true,
|
|
682
718
|
explain: options.explain === true,
|
|
683
719
|
json: options.json,
|
|
684
720
|
record: options.record,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DiffFile } from '@neurcode-ai/diff-parser';
|
|
2
|
+
export type AdvisorySignalSeverity = 'info' | 'warn';
|
|
3
|
+
export interface AdvisorySignal {
|
|
4
|
+
code: 'SENSITIVE_DOMAIN_SPAN' | 'DIRECT_DB_IN_REQUEST_LAYER' | 'LARGE_CHANGE_SURFACE' | 'CODE_WITHOUT_TEST_UPDATES' | 'INFRA_AND_APP_MIXED' | 'POSSIBLE_SECRET_ADDITION';
|
|
5
|
+
severity: AdvisorySignalSeverity;
|
|
6
|
+
title: string;
|
|
7
|
+
detail: string;
|
|
8
|
+
files: string[];
|
|
9
|
+
}
|
|
10
|
+
interface AdvisoryInput {
|
|
11
|
+
diffFiles: DiffFile[];
|
|
12
|
+
summary?: {
|
|
13
|
+
totalFiles: number;
|
|
14
|
+
totalAdded: number;
|
|
15
|
+
totalRemoved: number;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export declare function evaluateAdvisorySignals(input: AdvisoryInput): AdvisorySignal[];
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=advisory-signals.d.ts.map
|