@neurcode-ai/cli 0.9.43 → 0.9.45

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.
Files changed (180) hide show
  1. package/dist/commands/check.js +20 -2
  2. package/dist/commands/contract.js +47 -0
  3. package/dist/commands/plan.js +40 -0
  4. package/dist/commands/verify.d.ts +2 -0
  5. package/dist/commands/verify.js +294 -136
  6. package/dist/config.d.ts +13 -0
  7. package/dist/config.js +48 -0
  8. package/dist/index.js +41 -5
  9. package/dist/utils/advisory-signals.d.ts +20 -0
  10. package/dist/utils/advisory-signals.js +177 -0
  11. package/dist/utils/artifact-signature.js +21 -0
  12. package/dist/utils/change-contract.d.ts +105 -1
  13. package/dist/utils/change-contract.js +685 -12
  14. package/dist/utils/diff-symbols.d.ts +10 -0
  15. package/dist/utils/diff-symbols.js +218 -0
  16. package/dist/utils/plan-symbols.d.ts +17 -0
  17. package/dist/utils/plan-symbols.js +209 -0
  18. package/package.json +2 -11
  19. package/dist/api-client.d.ts.map +0 -1
  20. package/dist/api-client.js.map +0 -1
  21. package/dist/commands/allow.d.ts.map +0 -1
  22. package/dist/commands/allow.js.map +0 -1
  23. package/dist/commands/apply.d.ts.map +0 -1
  24. package/dist/commands/apply.js.map +0 -1
  25. package/dist/commands/approve.d.ts.map +0 -1
  26. package/dist/commands/approve.js.map +0 -1
  27. package/dist/commands/ask.d.ts.map +0 -1
  28. package/dist/commands/ask.js.map +0 -1
  29. package/dist/commands/audit.d.ts.map +0 -1
  30. package/dist/commands/audit.js.map +0 -1
  31. package/dist/commands/bootstrap.d.ts.map +0 -1
  32. package/dist/commands/bootstrap.js.map +0 -1
  33. package/dist/commands/brain.d.ts.map +0 -1
  34. package/dist/commands/brain.js.map +0 -1
  35. package/dist/commands/check.d.ts.map +0 -1
  36. package/dist/commands/check.js.map +0 -1
  37. package/dist/commands/config.d.ts.map +0 -1
  38. package/dist/commands/config.js.map +0 -1
  39. package/dist/commands/contract.d.ts.map +0 -1
  40. package/dist/commands/contract.js.map +0 -1
  41. package/dist/commands/doctor.d.ts.map +0 -1
  42. package/dist/commands/doctor.js.map +0 -1
  43. package/dist/commands/feedback.d.ts.map +0 -1
  44. package/dist/commands/feedback.js.map +0 -1
  45. package/dist/commands/guard.d.ts.map +0 -1
  46. package/dist/commands/guard.js.map +0 -1
  47. package/dist/commands/init.d.ts.map +0 -1
  48. package/dist/commands/init.js.map +0 -1
  49. package/dist/commands/login.d.ts.map +0 -1
  50. package/dist/commands/login.js.map +0 -1
  51. package/dist/commands/logout.d.ts.map +0 -1
  52. package/dist/commands/logout.js.map +0 -1
  53. package/dist/commands/map.d.ts.map +0 -1
  54. package/dist/commands/map.js.map +0 -1
  55. package/dist/commands/plan-slo.d.ts.map +0 -1
  56. package/dist/commands/plan-slo.js.map +0 -1
  57. package/dist/commands/plan.d.ts.map +0 -1
  58. package/dist/commands/plan.js.map +0 -1
  59. package/dist/commands/policy.d.ts.map +0 -1
  60. package/dist/commands/policy.js.map +0 -1
  61. package/dist/commands/prompt.d.ts.map +0 -1
  62. package/dist/commands/prompt.js.map +0 -1
  63. package/dist/commands/refactor.d.ts.map +0 -1
  64. package/dist/commands/refactor.js.map +0 -1
  65. package/dist/commands/remediate.d.ts.map +0 -1
  66. package/dist/commands/remediate.js.map +0 -1
  67. package/dist/commands/repo.d.ts.map +0 -1
  68. package/dist/commands/repo.js.map +0 -1
  69. package/dist/commands/revert.d.ts.map +0 -1
  70. package/dist/commands/revert.js.map +0 -1
  71. package/dist/commands/security.d.ts.map +0 -1
  72. package/dist/commands/security.js.map +0 -1
  73. package/dist/commands/session.d.ts.map +0 -1
  74. package/dist/commands/session.js.map +0 -1
  75. package/dist/commands/ship.d.ts.map +0 -1
  76. package/dist/commands/ship.js.map +0 -1
  77. package/dist/commands/simulate.d.ts.map +0 -1
  78. package/dist/commands/simulate.js.map +0 -1
  79. package/dist/commands/verify.d.ts.map +0 -1
  80. package/dist/commands/verify.js.map +0 -1
  81. package/dist/commands/watch.d.ts.map +0 -1
  82. package/dist/commands/watch.js.map +0 -1
  83. package/dist/commands/whoami.d.ts.map +0 -1
  84. package/dist/commands/whoami.js.map +0 -1
  85. package/dist/config.d.ts.map +0 -1
  86. package/dist/config.js.map +0 -1
  87. package/dist/index.d.ts.map +0 -1
  88. package/dist/index.js.map +0 -1
  89. package/dist/rules.d.ts.map +0 -1
  90. package/dist/rules.js.map +0 -1
  91. package/dist/services/integrations/TicketService.d.ts.map +0 -1
  92. package/dist/services/integrations/TicketService.js.map +0 -1
  93. package/dist/services/mapper/ProjectScanner.d.ts.map +0 -1
  94. package/dist/services/mapper/ProjectScanner.js.map +0 -1
  95. package/dist/services/project-knowledge-service.d.ts.map +0 -1
  96. package/dist/services/project-knowledge-service.js.map +0 -1
  97. package/dist/services/security/SecurityGuard.d.ts.map +0 -1
  98. package/dist/services/security/SecurityGuard.js.map +0 -1
  99. package/dist/services/toolbox-service.d.ts.map +0 -1
  100. package/dist/services/toolbox-service.js.map +0 -1
  101. package/dist/services/watch/BlobStore.d.ts.map +0 -1
  102. package/dist/services/watch/BlobStore.js.map +0 -1
  103. package/dist/services/watch/CommandPoller.d.ts.map +0 -1
  104. package/dist/services/watch/CommandPoller.js.map +0 -1
  105. package/dist/services/watch/Journal.d.ts.map +0 -1
  106. package/dist/services/watch/Journal.js.map +0 -1
  107. package/dist/services/watch/Sentinel.d.ts.map +0 -1
  108. package/dist/services/watch/Sentinel.js.map +0 -1
  109. package/dist/services/watch/Syncer.d.ts.map +0 -1
  110. package/dist/services/watch/Syncer.js.map +0 -1
  111. package/dist/utils/ROILogger.d.ts.map +0 -1
  112. package/dist/utils/ROILogger.js.map +0 -1
  113. package/dist/utils/RelevanceScorer.d.ts.map +0 -1
  114. package/dist/utils/RelevanceScorer.js.map +0 -1
  115. package/dist/utils/ai-debt-budget.d.ts.map +0 -1
  116. package/dist/utils/ai-debt-budget.js.map +0 -1
  117. package/dist/utils/artifact-signature.d.ts.map +0 -1
  118. package/dist/utils/artifact-signature.js.map +0 -1
  119. package/dist/utils/ask-cache.d.ts.map +0 -1
  120. package/dist/utils/ask-cache.js.map +0 -1
  121. package/dist/utils/box.d.ts.map +0 -1
  122. package/dist/utils/box.js.map +0 -1
  123. package/dist/utils/brain-context.d.ts.map +0 -1
  124. package/dist/utils/brain-context.js.map +0 -1
  125. package/dist/utils/breakage-simulator.d.ts.map +0 -1
  126. package/dist/utils/breakage-simulator.js.map +0 -1
  127. package/dist/utils/change-contract.d.ts.map +0 -1
  128. package/dist/utils/change-contract.js.map +0 -1
  129. package/dist/utils/cli-json.d.ts.map +0 -1
  130. package/dist/utils/cli-json.js.map +0 -1
  131. package/dist/utils/custom-policy-rules.d.ts.map +0 -1
  132. package/dist/utils/custom-policy-rules.js.map +0 -1
  133. package/dist/utils/git.d.ts.map +0 -1
  134. package/dist/utils/git.js.map +0 -1
  135. package/dist/utils/gitignore.d.ts.map +0 -1
  136. package/dist/utils/gitignore.js.map +0 -1
  137. package/dist/utils/governance.d.ts.map +0 -1
  138. package/dist/utils/governance.js.map +0 -1
  139. package/dist/utils/ignore.d.ts.map +0 -1
  140. package/dist/utils/ignore.js.map +0 -1
  141. package/dist/utils/manual-approvals.d.ts.map +0 -1
  142. package/dist/utils/manual-approvals.js.map +0 -1
  143. package/dist/utils/messages.d.ts.map +0 -1
  144. package/dist/utils/messages.js.map +0 -1
  145. package/dist/utils/neurcode-context.d.ts.map +0 -1
  146. package/dist/utils/neurcode-context.js.map +0 -1
  147. package/dist/utils/plan-cache.d.ts.map +0 -1
  148. package/dist/utils/plan-cache.js.map +0 -1
  149. package/dist/utils/plan-slo.d.ts.map +0 -1
  150. package/dist/utils/plan-slo.js.map +0 -1
  151. package/dist/utils/policy-audit.d.ts.map +0 -1
  152. package/dist/utils/policy-audit.js.map +0 -1
  153. package/dist/utils/policy-compiler.d.ts.map +0 -1
  154. package/dist/utils/policy-compiler.js.map +0 -1
  155. package/dist/utils/policy-exceptions.d.ts.map +0 -1
  156. package/dist/utils/policy-exceptions.js.map +0 -1
  157. package/dist/utils/policy-governance.d.ts.map +0 -1
  158. package/dist/utils/policy-governance.js.map +0 -1
  159. package/dist/utils/policy-packs.d.ts.map +0 -1
  160. package/dist/utils/policy-packs.js.map +0 -1
  161. package/dist/utils/project-detector.d.ts.map +0 -1
  162. package/dist/utils/project-detector.js.map +0 -1
  163. package/dist/utils/project-root.d.ts.map +0 -1
  164. package/dist/utils/project-root.js.map +0 -1
  165. package/dist/utils/repo-links.d.ts.map +0 -1
  166. package/dist/utils/repo-links.js.map +0 -1
  167. package/dist/utils/restore.d.ts.map +0 -1
  168. package/dist/utils/restore.js.map +0 -1
  169. package/dist/utils/runtime-guard.d.ts.map +0 -1
  170. package/dist/utils/runtime-guard.js.map +0 -1
  171. package/dist/utils/scope-telemetry.d.ts.map +0 -1
  172. package/dist/utils/scope-telemetry.js.map +0 -1
  173. package/dist/utils/secret-masking.d.ts.map +0 -1
  174. package/dist/utils/secret-masking.js.map +0 -1
  175. package/dist/utils/state.d.ts.map +0 -1
  176. package/dist/utils/state.js.map +0 -1
  177. package/dist/utils/tier.d.ts.map +0 -1
  178. package/dist/utils/tier.js.map +0 -1
  179. package/dist/utils/user-context.d.ts.map +0 -1
  180. package/dist/utils/user-context.js.map +0 -1
@@ -44,12 +44,30 @@ const project_detector_1 = require("../utils/project-detector");
44
44
  const promises_1 = require("readline/promises");
45
45
  const process_1 = require("process");
46
46
  const messages_1 = require("../utils/messages");
47
+ function isGitRepository(cwd) {
48
+ try {
49
+ const output = (0, child_process_1.execSync)('git rev-parse --is-inside-work-tree', {
50
+ cwd,
51
+ encoding: 'utf-8',
52
+ stdio: ['ignore', 'pipe', 'pipe'],
53
+ maxBuffer: 1024 * 1024,
54
+ }).trim().toLowerCase();
55
+ return output === 'true';
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
47
61
  async function checkCommand(options) {
48
62
  try {
63
+ if (!isGitRepository(process.cwd())) {
64
+ (0, messages_1.printError)('Git repository required', 'Run this command inside a git repository. If this is a new folder, run: git init && git add . && git commit -m "chore: baseline"');
65
+ process.exit(1);
66
+ }
49
67
  // Determines which diff to capture
50
68
  let diffText;
51
69
  if (options.staged) {
52
- diffText = (0, child_process_1.execSync)('git diff --staged', { maxBuffer: 1024 * 1024 * 1024, encoding: 'utf-8' });
70
+ diffText = (0, child_process_1.execSync)('git diff --cached', { maxBuffer: 1024 * 1024 * 1024, encoding: 'utf-8' });
53
71
  }
54
72
  else if (options.base) {
55
73
  diffText = (0, git_1.getDiffFromBase)(options.base);
@@ -60,7 +78,7 @@ async function checkCommand(options) {
60
78
  else {
61
79
  // Default: check staged, fallback to HEAD
62
80
  try {
63
- diffText = (0, child_process_1.execSync)('git diff --staged', { maxBuffer: 1024 * 1024 * 1024, encoding: 'utf-8' });
81
+ diffText = (0, child_process_1.execSync)('git diff --cached', { maxBuffer: 1024 * 1024 * 1024, encoding: 'utf-8' });
64
82
  }
65
83
  catch {
66
84
  diffText = (0, child_process_1.execSync)('git diff HEAD', { maxBuffer: 1024 * 1024 * 1024, encoding: 'utf-8' });
@@ -12,6 +12,7 @@ const policy_packs_1 = require("../utils/policy-packs");
12
12
  const policy_compiler_1 = require("../utils/policy-compiler");
13
13
  const change_contract_1 = require("../utils/change-contract");
14
14
  const artifact_signature_1 = require("../utils/artifact-signature");
15
+ const plan_symbols_1 = require("../utils/plan-symbols");
15
16
  let chalk;
16
17
  try {
17
18
  chalk = require('chalk');
@@ -60,6 +61,49 @@ function parseAsJsonIfPossible(raw) {
60
61
  function normalizeProvider(provider) {
61
62
  return String(provider || 'generic').trim().toLowerCase();
62
63
  }
64
+ function parseBooleanFlag(raw, fallback) {
65
+ if (!raw || !raw.trim())
66
+ return fallback;
67
+ const normalized = raw.trim().toLowerCase();
68
+ if (normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on')
69
+ return true;
70
+ if (normalized === '0' || normalized === 'false' || normalized === 'no' || normalized === 'off')
71
+ return false;
72
+ return fallback;
73
+ }
74
+ function parseNonNegativeInt(raw) {
75
+ if (!raw || !raw.trim())
76
+ return undefined;
77
+ const parsed = Number(raw);
78
+ if (!Number.isFinite(parsed))
79
+ return undefined;
80
+ const rounded = Math.floor(parsed);
81
+ return rounded >= 0 ? rounded : undefined;
82
+ }
83
+ function resolveChangeContractOptionsFromEnv() {
84
+ const maxUnexpectedFiles = parseNonNegativeInt(process.env.NEURCODE_CHANGE_CONTRACT_MAX_UNEXPECTED_FILES);
85
+ const maxMissingExpectedSymbols = parseNonNegativeInt(process.env.NEURCODE_CHANGE_CONTRACT_MAX_MISSING_EXPECTED_SYMBOLS);
86
+ return {
87
+ enforceExpectedFiles: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_ENFORCE_EXPECTED_FILES, false),
88
+ enforceActionMatching: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_ENFORCE_ACTION_MATCHING, true),
89
+ allowRenameForModify: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_ALLOW_RENAME_FOR_MODIFY, true),
90
+ enforceExpectedSymbols: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_ENFORCE_EXPECTED_SYMBOLS, false),
91
+ enforceSymbolActionMatching: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_ENFORCE_SYMBOL_ACTION_MATCHING, false),
92
+ symbolTypeRelaxedMatching: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_SYMBOL_TYPE_RELAXED_MATCHING, true),
93
+ symbolFileBasenameFallback: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_SYMBOL_FILE_BASENAME_FALLBACK, false),
94
+ ...(maxUnexpectedFiles !== undefined ? { maxUnexpectedFiles } : {}),
95
+ ...(maxMissingExpectedSymbols !== undefined ? { maxMissingExpectedSymbols } : {}),
96
+ };
97
+ }
98
+ function mapPlanFilesForChangeContract(files) {
99
+ return files
100
+ .map((file) => ({
101
+ path: file.path,
102
+ action: file.action,
103
+ reason: file.reason,
104
+ }))
105
+ .filter((file) => typeof file.path === 'string' && file.path.trim().length > 0);
106
+ }
63
107
  function normalizeCandidateLimit(value) {
64
108
  if (!Number.isFinite(value))
65
109
  return 8;
@@ -407,6 +451,9 @@ function contractCommand(program) {
407
451
  projectId: options.projectId || null,
408
452
  intent: options.intent || response.plan.summary || 'imported-plan',
409
453
  expectedFiles,
454
+ planFiles: mapPlanFilesForChangeContract(response.plan.files),
455
+ expectedSymbols: (0, plan_symbols_1.mapPlanSymbolsForChangeContract)(response.plan),
456
+ options: resolveChangeContractOptionsFromEnv(),
410
457
  policyLockFingerprint: policyLock.lock?.effective.fingerprint || null,
411
458
  compiledPolicyFingerprint: compiledPolicy.artifact?.fingerprint || null,
412
459
  });
@@ -55,6 +55,7 @@ const change_contract_1 = require("../utils/change-contract");
55
55
  const policy_packs_1 = require("../utils/policy-packs");
56
56
  const policy_compiler_1 = require("../utils/policy-compiler");
57
57
  const artifact_signature_1 = require("../utils/artifact-signature");
58
+ const plan_symbols_1 = require("../utils/plan-symbols");
58
59
  // Import chalk with fallback for plain strings if not available
59
60
  let chalk;
60
61
  try {
@@ -591,6 +592,39 @@ function parseBooleanFlag(raw, fallback) {
591
592
  }
592
593
  return fallback;
593
594
  }
595
+ function parseNonNegativeInt(raw) {
596
+ if (!raw || !raw.trim())
597
+ return undefined;
598
+ const parsed = Number(raw);
599
+ if (!Number.isFinite(parsed))
600
+ return undefined;
601
+ const rounded = Math.floor(parsed);
602
+ return rounded >= 0 ? rounded : undefined;
603
+ }
604
+ function resolveChangeContractOptionsFromEnv() {
605
+ const maxUnexpectedFiles = parseNonNegativeInt(process.env.NEURCODE_CHANGE_CONTRACT_MAX_UNEXPECTED_FILES);
606
+ const maxMissingExpectedSymbols = parseNonNegativeInt(process.env.NEURCODE_CHANGE_CONTRACT_MAX_MISSING_EXPECTED_SYMBOLS);
607
+ return {
608
+ enforceExpectedFiles: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_ENFORCE_EXPECTED_FILES, false),
609
+ enforceActionMatching: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_ENFORCE_ACTION_MATCHING, true),
610
+ allowRenameForModify: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_ALLOW_RENAME_FOR_MODIFY, true),
611
+ enforceExpectedSymbols: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_ENFORCE_EXPECTED_SYMBOLS, false),
612
+ enforceSymbolActionMatching: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_ENFORCE_SYMBOL_ACTION_MATCHING, false),
613
+ symbolTypeRelaxedMatching: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_SYMBOL_TYPE_RELAXED_MATCHING, true),
614
+ symbolFileBasenameFallback: parseBooleanFlag(process.env.NEURCODE_CHANGE_CONTRACT_SYMBOL_FILE_BASENAME_FALLBACK, false),
615
+ ...(maxUnexpectedFiles !== undefined ? { maxUnexpectedFiles } : {}),
616
+ ...(maxMissingExpectedSymbols !== undefined ? { maxMissingExpectedSymbols } : {}),
617
+ };
618
+ }
619
+ function mapPlanFilesForChangeContract(files) {
620
+ return files
621
+ .map((file) => ({
622
+ path: file.path,
623
+ action: file.action,
624
+ reason: file.reason,
625
+ }))
626
+ .filter((file) => typeof file.path === 'string' && file.path.trim().length > 0);
627
+ }
594
628
  function parseConfidenceScoreThreshold(raw) {
595
629
  if (!raw)
596
630
  return null;
@@ -854,6 +888,9 @@ function emitCachedPlanHit(input) {
854
888
  projectId: input.projectId || null,
855
889
  intent: input.response.plan.summary || 'cached-plan',
856
890
  expectedFiles,
891
+ planFiles: mapPlanFilesForChangeContract(input.response.plan.files),
892
+ expectedSymbols: (0, plan_symbols_1.mapPlanSymbolsForChangeContract)(input.response.plan),
893
+ options: resolveChangeContractOptionsFromEnv(),
857
894
  policyLockFingerprint: lockRead.lock?.effective.fingerprint || null,
858
895
  compiledPolicyFingerprint: compiledPolicyRead.artifact?.fingerprint || null,
859
896
  });
@@ -2284,6 +2321,9 @@ async function planCommand(intent, options) {
2284
2321
  projectId: finalProjectId || null,
2285
2322
  intent,
2286
2323
  expectedFiles,
2324
+ planFiles: mapPlanFilesForChangeContract(response.plan.files),
2325
+ expectedSymbols: (0, plan_symbols_1.mapPlanSymbolsForChangeContract)(response.plan),
2326
+ options: resolveChangeContractOptionsFromEnv(),
2287
2327
  policyLockFingerprint: lockRead.lock?.effective.fingerprint || null,
2288
2328
  compiledPolicyFingerprint: compiledPolicyRead.artifact?.fingerprint || null,
2289
2329
  });
@@ -37,6 +37,8 @@ interface VerifyOptions {
37
37
  runtimeGuard?: string;
38
38
  /** Print detailed AI change justification reasoning. */
39
39
  explain?: boolean;
40
+ /** Print extra explanatory output for demos/onboarding. */
41
+ demo?: boolean;
40
42
  /** Use queue-backed async verification mode on the API. */
41
43
  asyncMode?: boolean;
42
44
  /** Poll interval for async verification job status. */