ccjk 13.6.5 → 13.6.7

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 (49) hide show
  1. package/dist/chunks/api-config-selector.mjs +6 -4
  2. package/dist/chunks/auto-updater.mjs +100 -2
  3. package/dist/chunks/banner.mjs +0 -16
  4. package/dist/chunks/ccjk-mcp.mjs +2 -2
  5. package/dist/chunks/ccr.mjs +5 -3
  6. package/dist/chunks/check-updates.mjs +12 -1
  7. package/dist/chunks/claude-code-config-manager.mjs +3 -1
  8. package/dist/chunks/claude-code-incremental-manager.mjs +46 -20
  9. package/dist/chunks/claude-config.mjs +36 -3
  10. package/dist/chunks/claude-wrapper.mjs +1 -1
  11. package/dist/chunks/cli-hook.mjs +4 -5
  12. package/dist/chunks/codex-config-switch.mjs +3 -2
  13. package/dist/chunks/codex-provider-manager.mjs +1 -0
  14. package/dist/chunks/codex.mjs +3 -359
  15. package/dist/chunks/config-switch.mjs +23 -10
  16. package/dist/chunks/config.mjs +1 -1
  17. package/dist/chunks/config2.mjs +3 -3
  18. package/dist/chunks/constants.mjs +1 -1
  19. package/dist/chunks/doctor.mjs +1 -1
  20. package/dist/chunks/features.mjs +76 -11
  21. package/dist/chunks/index10.mjs +15 -15
  22. package/dist/chunks/init.mjs +14 -30
  23. package/dist/chunks/installer.mjs +3 -3
  24. package/dist/chunks/mcp-cli.mjs +17 -16
  25. package/dist/chunks/mcp.mjs +8 -7
  26. package/dist/chunks/memory-check.mjs +1 -1
  27. package/dist/chunks/package.mjs +1 -1
  28. package/dist/chunks/platform.mjs +1 -1
  29. package/dist/chunks/quick-setup.mjs +12 -10
  30. package/dist/chunks/research.mjs +225 -27
  31. package/dist/chunks/smart-defaults.mjs +2 -2
  32. package/dist/chunks/uninstall.mjs +1 -1
  33. package/dist/chunks/update.mjs +14 -13
  34. package/dist/chunks/version-checker.mjs +11 -1
  35. package/dist/cli.mjs +5 -1
  36. package/dist/i18n/locales/en/cli.json +0 -4
  37. package/dist/i18n/locales/en/menu.json +3 -3
  38. package/dist/i18n/locales/en/notification.json +2 -2
  39. package/dist/i18n/locales/zh-CN/cli.json +0 -4
  40. package/dist/i18n/locales/zh-CN/menu.json +3 -3
  41. package/dist/i18n/locales/zh-CN/notification.json +2 -2
  42. package/dist/shared/{ccjk.DvAP4XfP.mjs → ccjk.B4aXNclK.mjs} +2 -2
  43. package/dist/shared/ccjk.BI-hdI7P.mjs +30 -0
  44. package/dist/shared/{ccjk.C4m4ypdk.mjs → ccjk.DHaUdzX3.mjs} +4 -3
  45. package/dist/shared/ccjk.DKXs7Fbm.mjs +361 -0
  46. package/dist/shared/{ccjk.BP5hsTZQ.mjs → ccjk.Dz0ssUQx.mjs} +1 -1
  47. package/package.json +3 -1
  48. package/templates/common/workflow/essential/en/feat.md +68 -291
  49. package/templates/common/workflow/sixStep/en/workflow.md +56 -330
@@ -309,15 +309,6 @@ function inferResearchPhase(name) {
309
309
  function buildPhaseHistory(runPhase) {
310
310
  return ["brief", runPhase, "verify", "report"];
311
311
  }
312
- function determineVerdict(success, metricName, metricValue) {
313
- if (!success) {
314
- return "FAIL";
315
- }
316
- if (metricName && metricValue === void 0) {
317
- return "PARTIAL";
318
- }
319
- return "PASS";
320
- }
321
312
  function sanitizeLedgerField(value) {
322
313
  if (value === void 0 || value === null) {
323
314
  return "";
@@ -407,16 +398,116 @@ function readAllResultRows(dbPath) {
407
398
  }
408
399
  return lines.slice(1).map(parseResultRow).filter((row) => Boolean(row));
409
400
  }
410
- function metricDirection(metricName) {
401
+ function resolveResearchObjective(metricName, objective = "auto") {
402
+ if (objective === "maximize" || objective === "minimize") {
403
+ return objective;
404
+ }
411
405
  const normalized = (metricName || "").toLowerCase();
412
406
  if (!normalized) {
413
- return "desc";
407
+ return "maximize";
414
408
  }
415
409
  const lowerIsBetter = ["loss", "error", "bpb", "perplexity", "ppl", "latency", "duration", "time", "cost", "price", "wer", "cer"];
416
410
  if (lowerIsBetter.some((keyword) => normalized.includes(keyword))) {
417
- return "asc";
411
+ return "minimize";
412
+ }
413
+ return "maximize";
414
+ }
415
+ function compareMetricValues(baselineMetricValue, candidateMetricValue, objective) {
416
+ if (baselineMetricValue === void 0 || candidateMetricValue === void 0) {
417
+ return "unknown";
418
+ }
419
+ if (candidateMetricValue === baselineMetricValue) {
420
+ return "equal";
421
+ }
422
+ if (objective === "minimize") {
423
+ return candidateMetricValue < baselineMetricValue ? "better" : "worse";
424
+ }
425
+ return candidateMetricValue > baselineMetricValue ? "better" : "worse";
426
+ }
427
+ function formatSignedNumber(value) {
428
+ if (value === void 0) {
429
+ return "unknown";
430
+ }
431
+ return `${value > 0 ? "+" : ""}${value}`;
432
+ }
433
+ function formatPercent(value) {
434
+ if (value === void 0) {
435
+ return "unknown";
436
+ }
437
+ return `${value > 0 ? "+" : ""}${value.toFixed(2)}%`;
438
+ }
439
+ function buildComparisonSummary(input) {
440
+ const result = compareMetricValues(input.baselineMetricValue, input.candidateMetricValue, input.objective);
441
+ const delta = input.baselineMetricValue !== void 0 && input.candidateMetricValue !== void 0 ? input.candidateMetricValue - input.baselineMetricValue : void 0;
442
+ const percentDelta = input.baselineMetricValue !== void 0 && input.baselineMetricValue !== 0 && delta !== void 0 ? delta / input.baselineMetricValue * 100 : void 0;
443
+ const goal = input.objective === "minimize" ? "lower" : "higher";
444
+ let summary = `Needs ${goal} ${input.objective === "minimize" ? "metric reduction" : "metric lift"} data.`;
445
+ if (result === "better") {
446
+ summary = `Candidate is better than baseline (${input.candidateMetricValue} vs ${input.baselineMetricValue}, \u0394 ${formatSignedNumber(delta)} / ${formatPercent(percentDelta)}).`;
447
+ } else if (result === "worse") {
448
+ summary = `Candidate is worse than baseline (${input.candidateMetricValue} vs ${input.baselineMetricValue}, \u0394 ${formatSignedNumber(delta)} / ${formatPercent(percentDelta)}).`;
449
+ } else if (result === "equal") {
450
+ summary = `Candidate matches baseline (${input.candidateMetricValue}).`;
451
+ }
452
+ return {
453
+ baselineSessionId: input.baselineSessionId,
454
+ baselineName: input.baselineName,
455
+ objective: input.objective,
456
+ result,
457
+ baselineMetricValue: input.baselineMetricValue,
458
+ candidateMetricValue: input.candidateMetricValue,
459
+ delta,
460
+ percentDelta,
461
+ summary
462
+ };
463
+ }
464
+ function determineVerdict(args) {
465
+ if (!args.success) {
466
+ return {
467
+ verdict: "FAIL",
468
+ reason: "Command execution failed."
469
+ };
470
+ }
471
+ if (args.metricName && args.metricValue === void 0) {
472
+ return {
473
+ verdict: "PARTIAL",
474
+ reason: `Metric ${args.metricName} was configured but not found in output.`
475
+ };
476
+ }
477
+ if (args.comparison?.result === "worse") {
478
+ return {
479
+ verdict: "FAIL",
480
+ reason: args.comparison.summary
481
+ };
482
+ }
483
+ if (args.comparison?.result === "unknown") {
484
+ return {
485
+ verdict: "PARTIAL",
486
+ reason: args.comparison.summary
487
+ };
418
488
  }
419
- return "desc";
489
+ if (args.comparison?.result === "equal") {
490
+ return {
491
+ verdict: "PARTIAL",
492
+ reason: args.comparison.summary
493
+ };
494
+ }
495
+ if (args.comparison?.result === "better") {
496
+ return {
497
+ verdict: "PASS",
498
+ reason: args.comparison.summary
499
+ };
500
+ }
501
+ if (args.metricName && args.metricValue !== void 0) {
502
+ return {
503
+ verdict: "PASS",
504
+ reason: `Metric ${args.metricName}=${args.metricValue} was captured successfully.`
505
+ };
506
+ }
507
+ return {
508
+ verdict: "PASS",
509
+ reason: "Command completed successfully."
510
+ };
420
511
  }
421
512
  function selectBestByMetric(rows) {
422
513
  const newestMetricRow = [...rows].reverse().find((row) => row.metricName && row.metricValue !== void 0);
@@ -427,12 +518,12 @@ function selectBestByMetric(rows) {
427
518
  if (candidates.length === 0) {
428
519
  return newestMetricRow;
429
520
  }
430
- const direction = metricDirection(newestMetricRow.metricName);
521
+ const objective = resolveResearchObjective(newestMetricRow.metricName);
431
522
  return candidates.reduce((best, current) => {
432
- if (!best.metricValue || current.metricValue === void 0) {
523
+ if (best.metricValue === void 0 || current.metricValue === void 0) {
433
524
  return best;
434
525
  }
435
- if (direction === "asc") {
526
+ if (objective === "minimize") {
436
527
  return current.metricValue < best.metricValue ? current : best;
437
528
  }
438
529
  return current.metricValue > best.metricValue ? current : best;
@@ -466,7 +557,8 @@ function buildResearchTask(taskId, options) {
466
557
  createdBy: "ccjk research",
467
558
  custom: {
468
559
  metricName: options.metricName,
469
- cwd: options.cwd
560
+ cwd: options.cwd,
561
+ baselineSessionId: options.baselineSessionId
470
562
  }
471
563
  },
472
564
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -481,6 +573,8 @@ function normalizeRunOptions(options) {
481
573
  budgetMs: options.budgetMs || DEFAULT_BUDGET_MS,
482
574
  maxRetries: options.maxRetries ?? 0,
483
575
  metricName: options.metricName,
576
+ baselineSessionId: options.baselineSessionId,
577
+ objective: options.objective || "auto",
484
578
  dbPath: options.dbPath
485
579
  };
486
580
  }
@@ -498,6 +592,24 @@ async function runResearchExperiment(options) {
498
592
  const sessionId = `research-${Date.now()}-${nanoid(6)}`;
499
593
  const taskId = `research-task-${nanoid(8)}`;
500
594
  const task = buildResearchTask(taskId, normalized);
595
+ const objective = resolveResearchObjective(normalized.metricName, normalized.objective);
596
+ let baselineSummary;
597
+ let comparison;
598
+ let baselineMetricValue;
599
+ if (normalized.baselineSessionId) {
600
+ baselineSummary = listResearchSessions(Number.MAX_SAFE_INTEGER, normalized.dbPath).find((session) => session.id === normalized.baselineSessionId);
601
+ const baselineReport = getResearchReport(normalized.baselineSessionId, normalized.dbPath);
602
+ if (baselineReport) {
603
+ baselineMetricValue = baselineReport.metricValue;
604
+ comparison = buildComparisonSummary({
605
+ baselineSessionId: baselineReport.sessionId,
606
+ baselineName: baselineReport.name,
607
+ baselineMetricValue,
608
+ candidateMetricValue: void 0,
609
+ objective
610
+ });
611
+ }
612
+ }
501
613
  persistence.saveSession(sessionId, {
502
614
  kind: RESEARCH_SESSION_KIND,
503
615
  name: normalized.name,
@@ -505,6 +617,8 @@ async function runResearchExperiment(options) {
505
617
  cwd: normalized.cwd,
506
618
  metricName: normalized.metricName,
507
619
  budgetMs: normalized.budgetMs,
620
+ objective,
621
+ baselineSessionId: normalized.baselineSessionId,
508
622
  currentPhase: runPhase,
509
623
  phaseHistory: ["brief", runPhase],
510
624
  createdAt
@@ -552,7 +666,23 @@ async function runResearchExperiment(options) {
552
666
  const status = finalizedResult.success ? "completed" : getFailureStatus(finalizedResult, error);
553
667
  const combinedOutput = [finalizedResult.stdout, finalizedResult.stderr].filter(Boolean).join("\n");
554
668
  const metricValue = extractMetricValue(combinedOutput, normalized.metricName);
555
- const verdict = determineVerdict(finalizedResult.success, normalized.metricName, metricValue);
669
+ if (normalized.baselineSessionId) {
670
+ comparison = buildComparisonSummary({
671
+ baselineSessionId: normalized.baselineSessionId,
672
+ baselineName: baselineSummary?.name || normalized.baselineSessionId,
673
+ baselineMetricValue,
674
+ candidateMetricValue: metricValue,
675
+ objective
676
+ });
677
+ }
678
+ const verdictDecision = determineVerdict({
679
+ success: finalizedResult.success,
680
+ metricName: normalized.metricName,
681
+ metricValue,
682
+ comparison
683
+ });
684
+ const verdict = verdictDecision.verdict;
685
+ const verdictReason = verdictDecision.reason;
556
686
  const output = {
557
687
  data: {
558
688
  command: normalized.command,
@@ -566,13 +696,18 @@ async function runResearchExperiment(options) {
566
696
  durationMs,
567
697
  attempts,
568
698
  phase: runPhase,
569
- verdict
699
+ objective,
700
+ verdict,
701
+ verdictReason,
702
+ baselineSessionId: normalized.baselineSessionId,
703
+ comparison
570
704
  },
571
705
  logs: combinedOutput ? combinedOutput.split(/\r?\n/) : [],
572
706
  metadata: {
573
707
  status,
574
708
  success: finalizedResult.success,
575
- verdict
709
+ verdict,
710
+ objective
576
711
  }
577
712
  };
578
713
  persistence.updateTaskStatus(
@@ -594,15 +729,17 @@ async function runResearchExperiment(options) {
594
729
  sessionId,
595
730
  taskId,
596
731
  decision: "record research run",
597
- reasoning: normalized.metricName ? `Executed the research command and tracked metric ${normalized.metricName}.` : "Executed the research command without a configured metric parser.",
732
+ reasoning: normalized.metricName ? `Executed the research command and evaluated metric ${normalized.metricName} with objective ${objective}.` : "Executed the research command without a configured metric parser.",
598
733
  context: JSON.stringify({
599
734
  command: normalized.command,
600
735
  cwd: normalized.cwd,
601
736
  budgetMs: normalized.budgetMs,
602
737
  metricName: normalized.metricName,
603
- phase: runPhase
738
+ phase: runPhase,
739
+ objective,
740
+ baselineSessionId: normalized.baselineSessionId
604
741
  }),
605
- outcome: finalizedResult.success ? metricValue === void 0 ? "completed without metric" : `${normalized.metricName}=${metricValue}` : finalizedResult.error || error?.message || "failed"
742
+ outcome: verdictReason
606
743
  });
607
744
  persistence.saveSession(sessionId, {
608
745
  kind: RESEARCH_SESSION_KIND,
@@ -611,13 +748,17 @@ async function runResearchExperiment(options) {
611
748
  cwd: normalized.cwd,
612
749
  metricName: normalized.metricName,
613
750
  budgetMs: normalized.budgetMs,
751
+ objective,
752
+ baselineSessionId: normalized.baselineSessionId,
614
753
  currentPhase: "report",
615
754
  phaseHistory,
616
755
  runPhase,
617
756
  verdict,
757
+ verdictReason,
618
758
  status,
619
759
  exitCode: finalizedResult.exitCode,
620
760
  metricValue,
761
+ comparison,
621
762
  durationMs,
622
763
  createdAt
623
764
  });
@@ -651,7 +792,11 @@ async function runResearchExperiment(options) {
651
792
  stderr: finalizedResult.stderr,
652
793
  durationMs,
653
794
  phase: runPhase,
795
+ objective,
654
796
  verdict,
797
+ verdictReason,
798
+ baselineSessionId: normalized.baselineSessionId,
799
+ comparison,
655
800
  phaseHistory,
656
801
  createdAt
657
802
  };
@@ -667,7 +812,9 @@ function listResearchSessions(limit = DEFAULT_SESSION_LIMIT, dbPath) {
667
812
  metricName: session.metadata.metricName,
668
813
  budgetMs: session.metadata.budgetMs || DEFAULT_BUDGET_MS,
669
814
  currentPhase: session.metadata.currentPhase || "experiment",
670
- verdict: session.metadata.verdict
815
+ objective: session.metadata.objective,
816
+ verdict: session.metadata.verdict,
817
+ baselineSessionId: session.metadata.baselineSessionId
671
818
  }));
672
819
  }
673
820
  function getLatestResearchSession(dbPath) {
@@ -710,7 +857,15 @@ function getResearchReport(sessionId, dbPath) {
710
857
  const latestTask = status.tasks[status.tasks.length - 1];
711
858
  const outputData = latestTask?.output?.data || {};
712
859
  const phaseHistory = status.metadata.phaseHistory || [];
713
- const verdict = status.metadata.verdict || determineVerdict(status.metrics.failedTasks === 0, status.metadata.metricName, outputData.metricValue);
860
+ const comparison = status.metadata.comparison;
861
+ const verdictDecision = determineVerdict({
862
+ success: status.metrics.failedTasks === 0,
863
+ metricName: status.metadata.metricName,
864
+ metricValue: outputData.metricValue,
865
+ comparison
866
+ });
867
+ const verdict = status.metadata.verdict || verdictDecision.verdict;
868
+ const verdictReason = String(status.metadata.verdictReason || verdictDecision.reason);
714
869
  const currentPhase = status.metadata.currentPhase || "report";
715
870
  const createdAt = String(status.metadata.createdAt || "");
716
871
  const outcome = String(
@@ -729,8 +884,19 @@ function getResearchReport(sessionId, dbPath) {
729
884
  lines.push(`**Exit Code**: ${outputData.exitCode ?? "unknown"}`);
730
885
  lines.push(`**Status**: ${outputData.status || status.metadata.status || "unknown"}`);
731
886
  lines.push(`**Metric**: ${status.metadata.metricName ? `${status.metadata.metricName}=${outputData.metricValue ?? "not found"}` : "not configured"}`);
887
+ lines.push(`**Objective**: ${status.metadata.objective || outputData.objective || "unknown"}`);
732
888
  lines.push(`**Duration**: ${outputData.durationMs ?? status.metadata.durationMs ?? 0}ms`);
889
+ lines.push(`**Reason**: ${verdictReason}`);
733
890
  lines.push(`**Outcome**: ${outcome}`);
891
+ if (comparison) {
892
+ lines.push("");
893
+ lines.push("## Comparison");
894
+ lines.push("");
895
+ lines.push(`- Baseline: ${comparison.baselineName} (${comparison.baselineSessionId})`);
896
+ lines.push(`- Objective: ${comparison.objective}`);
897
+ lines.push(`- Result: ${comparison.result}`);
898
+ lines.push(`- Summary: ${comparison.summary}`);
899
+ }
734
900
  if (phaseHistory.length > 0) {
735
901
  lines.push("");
736
902
  lines.push("## Phase History");
@@ -743,12 +909,16 @@ function getResearchReport(sessionId, dbPath) {
743
909
  createdAt,
744
910
  currentPhase,
745
911
  verdict,
912
+ verdictReason,
746
913
  command: status.metadata.command || outputData.command || "unknown",
747
914
  cwd: status.metadata.cwd || outputData.cwd || process.cwd(),
748
915
  status: String(outputData.status || status.metadata.status || "unknown"),
749
916
  exitCode: Number(outputData.exitCode ?? 0),
750
917
  metricName: status.metadata.metricName,
751
918
  metricValue: typeof outputData.metricValue === "number" ? outputData.metricValue : void 0,
919
+ objective: status.metadata.objective,
920
+ baselineSessionId: status.metadata.baselineSessionId,
921
+ comparison,
752
922
  durationMs: Number(outputData.durationMs ?? status.metadata.durationMs ?? 0),
753
923
  phaseHistory,
754
924
  outcome,
@@ -827,6 +997,8 @@ async function runResearchCommand(options) {
827
997
  metricName: options.metric,
828
998
  budgetMs: options.budgetMs,
829
999
  cwd: options.cwd,
1000
+ baselineSessionId: options.baseline,
1001
+ objective: options.objective,
830
1002
  dbPath: options.dbPath
831
1003
  });
832
1004
  console.log("");
@@ -836,12 +1008,18 @@ async function runResearchCommand(options) {
836
1008
  console.log(a.gray(`Task: ${result.taskId}`));
837
1009
  console.log(a.gray(`Name: ${result.name}`));
838
1010
  console.log(a.gray(`Phase: ${result.phase}`));
1011
+ console.log(a.gray(`Objective: ${result.objective}`));
839
1012
  console.log(a.gray(`Verdict: ${result.verdict}`));
1013
+ console.log(a.gray(`Reason: ${result.verdictReason}`));
840
1014
  console.log(a.gray(`Command: ${result.command}`));
841
1015
  console.log(a.gray(`CWD: ${result.cwd}`));
842
1016
  console.log(a.gray(`Status: ${result.status}`));
843
1017
  console.log(a.gray(`Exit code: ${result.exitCode}`));
844
1018
  console.log(a.gray(`Metric: ${formatMetric(result.metricName, result.metricValue)}`));
1019
+ if (result.comparison) {
1020
+ console.log(a.gray(`Baseline: ${result.comparison.baselineName} (${result.comparison.baselineSessionId})`));
1021
+ console.log(a.gray(`Compare: ${result.comparison.result}`));
1022
+ }
845
1023
  console.log(a.gray(`Duration: ${result.durationMs}ms`));
846
1024
  if (result.stderr) {
847
1025
  console.log("");
@@ -876,7 +1054,9 @@ async function showResearchStatus(sessionId, options) {
876
1054
  console.log(a.gray(`Session: ${status.sessionId}`));
877
1055
  console.log(a.gray(`Name: ${status.metadata.name || status.sessionId}`));
878
1056
  console.log(a.gray(`Phase: ${status.metadata.currentPhase || "unknown"}`));
1057
+ console.log(a.gray(`Objective: ${status.metadata.objective || "unknown"}`));
879
1058
  console.log(a.gray(`Verdict: ${status.metadata.verdict || "unknown"}`));
1059
+ console.log(a.gray(`Reason: ${status.metadata.verdictReason || "unknown"}`));
880
1060
  console.log(a.gray(`Command: ${status.metadata.command || "unknown"}`));
881
1061
  console.log(a.gray(`Metric: ${formatMetric(status.metadata.metricName, metricValue)}`));
882
1062
  console.log(a.gray(`Status: ${outputData.status || status.metadata.status || "unknown"}`));
@@ -886,6 +1066,12 @@ async function showResearchStatus(sessionId, options) {
886
1066
  console.log(a.gray(`Success: ${Math.round((status.metrics.successRate || 0) * 100)}%`));
887
1067
  console.log(a.gray(`Avg ms: ${status.metrics.avgExecutionTime}`));
888
1068
  console.log(a.gray(`Next: ${status.recovery.nextExecutable.length}`));
1069
+ if (status.metadata.comparison) {
1070
+ const comparison = status.metadata.comparison;
1071
+ console.log(a.gray(`Baseline: ${comparison.baselineName || comparison.baselineSessionId || "unknown"}`));
1072
+ console.log(a.gray(`Compare: ${comparison.result || "unknown"}`));
1073
+ console.log(a.gray(`Summary: ${comparison.summary || "unknown"}`));
1074
+ }
889
1075
  if (status.decisions.length > 0) {
890
1076
  const lastDecision = status.decisions[status.decisions.length - 1];
891
1077
  console.log(a.gray(`Decision: ${lastDecision.outcome || lastDecision.decision}`));
@@ -906,7 +1092,11 @@ async function listResearchCommand(options) {
906
1092
  console.log(a.bold(session.name));
907
1093
  console.log(a.gray(` ${session.id}`));
908
1094
  console.log(a.gray(` phase: ${session.currentPhase}`));
1095
+ console.log(a.gray(` objective: ${session.objective || "unknown"}`));
909
1096
  console.log(a.gray(` verdict: ${session.verdict || "unknown"}`));
1097
+ if (session.baselineSessionId) {
1098
+ console.log(a.gray(` baseline: ${session.baselineSessionId}`));
1099
+ }
910
1100
  console.log(a.gray(` cmd: ${session.command}`));
911
1101
  console.log(a.gray(` metric: ${session.metricName || "not configured"}`));
912
1102
  console.log(a.gray(` cwd: ${session.cwd}`));
@@ -927,6 +1117,7 @@ async function showResearchResults(options) {
927
1117
  if (best) {
928
1118
  console.log(a.bold("Best"));
929
1119
  console.log(a.gray(` ${best.name} \xB7 ${formatMetric(best.metricName, best.metricValue)} \xB7 ${best.status} \xB7 ${best.durationMs}ms`));
1120
+ console.log(a.gray(` objective: ${best.metricName ? ["loss", "error", "bpb", "perplexity", "ppl", "latency", "duration", "time", "cost", "price", "wer", "cer"].some((keyword) => best.metricName?.toLowerCase().includes(keyword)) ? "minimize" : "maximize" : "unknown"}`));
930
1121
  console.log(a.gray(` ${previewCommand(best.command)}`));
931
1122
  console.log("");
932
1123
  }
@@ -955,6 +1146,12 @@ async function showResearchReport(sessionId, options) {
955
1146
  console.log(a.gray(`Exit code: ${report.exitCode}`));
956
1147
  console.log(a.gray(`Duration: ${report.durationMs}ms`));
957
1148
  console.log(a.gray(`Metric: ${formatMetric(report.metricName, report.metricValue)}`));
1149
+ console.log(a.gray(`Objective: ${report.objective || "unknown"}`));
1150
+ console.log(a.gray(`Reason: ${report.verdictReason}`));
1151
+ if (report.comparison) {
1152
+ console.log(a.gray(`Baseline: ${report.comparison.baselineName} (${report.comparison.baselineSessionId})`));
1153
+ console.log(a.gray(`Compare: ${report.comparison.result}`));
1154
+ }
958
1155
  console.log(a.gray(`Outcome: ${report.outcome}`));
959
1156
  if (report.phaseHistory.length > 0) {
960
1157
  console.log(a.gray(`Phases: ${report.phaseHistory.join(" \u2192 ")}`));
@@ -965,13 +1162,14 @@ function showResearchHelp() {
965
1162
  console.log("");
966
1163
  console.log(a.bold.cyan("ccjk research"));
967
1164
  printDivider();
968
- console.log(" run Run a single persisted research experiment");
1165
+ console.log(" run Run a persisted research experiment with optional baseline comparison");
969
1166
  console.log(" status Show the latest or selected research session status");
970
1167
  console.log(" sessions List recent research sessions");
971
1168
  console.log(" results Show recent result rows and the current best run");
972
1169
  console.log(" report Render a compact persisted research report");
973
1170
  console.log("");
974
- console.log(a.dim('Example: ccjk research run --name baseline --cmd "python train.py" --metric val_bpb'));
1171
+ console.log(a.dim('Example: ccjk research run --name baseline --cmd "python train.py" --metric val_bpb --objective minimize'));
1172
+ console.log(a.dim('Example: ccjk research run --name candidate --cmd "python train.py --lr 1e-4" --metric val_bpb --baseline research-123'));
975
1173
  console.log(a.dim("Example: ccjk research report research-123"));
976
1174
  console.log("");
977
1175
  }
@@ -4,7 +4,7 @@ import { homedir } from 'node:os';
4
4
  import { CCJK_CONFIG_DIR, CODE_TOOL_INFO } from './constants.mjs';
5
5
  import { writeJsonConfig } from './json-config.mjs';
6
6
  import { j as join } from '../shared/ccjk.bQ7Dh1g4.mjs';
7
- import { g as getPlatform, e as commandExists } from './platform.mjs';
7
+ import { g as getPlatform, h as commandExists } from './platform.mjs';
8
8
  import { s as scanProject } from '../shared/ccjk.DJuyfrlL.mjs';
9
9
 
10
10
  const ORCHESTRATION_LEVELS = ["off", "minimal", "standard", "max"];
@@ -274,7 +274,7 @@ class SmartDefaultsDetector {
274
274
  if (existsSync(codexPath)) {
275
275
  return "codex";
276
276
  }
277
- return "claude-code";
277
+ return "myclaude";
278
278
  }
279
279
  /**
280
280
  * Check if CCR (Claude Code Router) should be enabled
@@ -618,7 +618,7 @@ async function uninstall(options = {}) {
618
618
  }
619
619
  const uninstaller = new ZcfUninstaller(lang);
620
620
  if (codeType === "codex") {
621
- const { runCodexUninstall } = await import('./codex.mjs').then(function (n) { return n.v; });
621
+ const { runCodexUninstall } = await import('./codex.mjs').then(function (n) { return n.q; });
622
622
  await runCodexUninstall();
623
623
  return;
624
624
  }
@@ -1,17 +1,18 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import a from './index5.mjs';
3
3
  import { i as inquirer } from './index6.mjs';
4
- import { c as runCodexUpdate, M as MCP_SERVICE_CONFIGS, g as getMcpServices } from './codex.mjs';
4
+ import { M as MCP_SERVICE_CONFIGS, g as getMcpServices } from '../shared/ccjk.DKXs7Fbm.mjs';
5
5
  import { SETTINGS_FILE, DEFAULT_CODE_TOOL_TYPE, resolveCodeToolType as resolveCodeToolType$1, isCodeToolType } from './constants.mjs';
6
6
  import { i18n } from './index2.mjs';
7
7
  import { displayBanner } from './banner.mjs';
8
8
  import { readZcfConfig, updateZcfConfig } from './ccjk-config.mjs';
9
9
  import { r as readMcpConfig } from './claude-config.mjs';
10
+ import { c as runCodexUpdate } from './codex.mjs';
10
11
  import { f as copyConfigFiles } from './config.mjs';
11
12
  import { n as needsMigration, m as migrateSettingsForTokenRetrieval, d as displayMigrationResult, p as promptMigration } from '../shared/ccjk.DDq2hqA5.mjs';
12
- import { u as updatePromptOnly } from '../shared/ccjk.BP5hsTZQ.mjs';
13
+ import { u as updatePromptOnly } from '../shared/ccjk.Dz0ssUQx.mjs';
13
14
  import { a as handleExitPromptError, h as handleGeneralError } from '../shared/ccjk.DGllfVCZ.mjs';
14
- import { a as installMcpServices } from '../shared/ccjk.C4m4ypdk.mjs';
15
+ import { a as installMcpServices } from '../shared/ccjk.DHaUdzX3.mjs';
15
16
  import { resolveAiOutputLanguage } from './prompts.mjs';
16
17
  import { g as getRuntimeVersion } from '../shared/ccjk.gDEDGD_t.mjs';
17
18
  import { checkClaudeCodeVersionAndPrompt } from './version-checker.mjs';
@@ -32,24 +33,24 @@ import 'node:os';
32
33
  import 'node:crypto';
33
34
  import 'buffer';
34
35
  import 'string_decoder';
36
+ import 'node:child_process';
37
+ import '../shared/ccjk.bQ7Dh1g4.mjs';
35
38
  import 'node:url';
36
- import '../shared/ccjk.RyizuzOI.mjs';
37
- import './index8.mjs';
38
- import '../shared/ccjk.DeWpAShp.mjs';
39
- import '../shared/ccjk.CxpGa6MC.mjs';
40
39
  import '../shared/ccjk.BBtCGd_g.mjs';
41
- import './main.mjs';
42
- import 'module';
43
- import 'node:child_process';
44
- import 'node:stream';
40
+ import './index3.mjs';
45
41
  import './fs-operations.mjs';
46
42
  import 'node:fs/promises';
47
- import '../shared/ccjk.bQ7Dh1g4.mjs';
48
43
  import './json-config.mjs';
44
+ import '../shared/ccjk.RyizuzOI.mjs';
49
45
  import './platform.mjs';
46
+ import './main.mjs';
47
+ import 'module';
48
+ import 'node:stream';
49
+ import './index8.mjs';
50
+ import '../shared/ccjk.DeWpAShp.mjs';
51
+ import '../shared/ccjk.CxpGa6MC.mjs';
50
52
  import '../shared/ccjk.BFQ7yr5S.mjs';
51
53
  import '../shared/ccjk.DZ2LLOa-.mjs';
52
- import './index3.mjs';
53
54
  import '../shared/ccjk.DScm_NnL.mjs';
54
55
 
55
56
  const ccjkVersion = getRuntimeVersion();
@@ -864,6 +864,16 @@ async function checkCometixLineVersion() {
864
864
  needsUpdate: currentVersion && latestVersion ? shouldUpdate(currentVersion, latestVersion) : false
865
865
  };
866
866
  }
867
+ async function checkMyclaudeVersion() {
868
+ const currentVersion = await getInstalledVersion("myclaude");
869
+ const latestVersion = await getLatestVersion("myclaude-code");
870
+ return {
871
+ installed: currentVersion !== null,
872
+ currentVersion,
873
+ latestVersion,
874
+ needsUpdate: currentVersion && latestVersion ? shouldUpdate(currentVersion, latestVersion) : false
875
+ };
876
+ }
867
877
  async function checkClaudeCodeVersionAndPrompt(skipPrompt = false) {
868
878
  try {
869
879
  const versionInfo = await checkClaudeCodeVersion();
@@ -878,4 +888,4 @@ async function checkClaudeCodeVersionAndPrompt(skipPrompt = false) {
878
888
  }
879
889
  }
880
890
 
881
- export { checkCcrVersion, checkClaudeCodeVersion, checkClaudeCodeVersionAndPrompt, checkCometixLineVersion, checkDuplicateInstallations, compareVersions, detectAllClaudeCodeInstallations, detectWrongClaudeCodePackage, fixBrokenNpmSymlink, getClaudeCodeInstallationSource, getHomebrewClaudeCodeVersion, getInstalledVersion, getLatestVersion, getSourceDisplayName, handleDuplicateInstallations, shouldUpdate };
891
+ export { checkCcrVersion, checkClaudeCodeVersion, checkClaudeCodeVersionAndPrompt, checkCometixLineVersion, checkDuplicateInstallations, checkMyclaudeVersion, compareVersions, detectAllClaudeCodeInstallations, detectWrongClaudeCodePackage, fixBrokenNpmSymlink, getClaudeCodeInstallationSource, getHomebrewClaudeCodeVersion, getInstalledVersion, getLatestVersion, getSourceDisplayName, handleDuplicateInstallations, shouldUpdate };
package/dist/cli.mjs CHANGED
@@ -463,12 +463,14 @@ const COMMANDS = [
463
463
  },
464
464
  {
465
465
  name: "research <action> [...args]",
466
- description: "Run focused autoresearch-style experiments",
466
+ description: "Run persisted research experiments with explicit metric comparison",
467
467
  tier: "extended",
468
468
  options: [
469
469
  { flags: "--name <name>", description: "Experiment name" },
470
470
  { flags: "--cmd <command>", description: "Shell command to execute" },
471
471
  { flags: "--metric <name>", description: "Metric name to parse from output" },
472
+ { flags: "--objective <mode>", description: "Metric objective (auto|maximize|minimize)" },
473
+ { flags: "--baseline <sessionId>", description: "Baseline session id to compare against" },
472
474
  { flags: "--budget-ms <ms>", description: "Execution budget in milliseconds" },
473
475
  { flags: "--cwd <path>", description: "Working directory for the command" },
474
476
  { flags: "--limit <n>", description: "Number of sessions to list" }
@@ -482,6 +484,8 @@ const COMMANDS = [
482
484
  name: options.name,
483
485
  cmd: options.cmd,
484
486
  metric: options.metric,
487
+ objective: options.objective,
488
+ baseline: options.baseline,
485
489
  budgetMs: options.budgetMs ? Number(options.budgetMs) : void 0,
486
490
  cwd: options.cwd,
487
491
  limit: options.limit ? Number(options.limit) : void 0
@@ -137,7 +137,6 @@
137
137
  "commands.ccjkSetup.args.rollbackOnError": "Auto-rollback on failure",
138
138
  "commands.ccjkSetup.args.lang": "Display language",
139
139
  "commandDiscovery.title": "🧠 CCJK Commands (ccjk 命令)",
140
- "commandDiscovery.claudeCodeTitle": "🤖 Claude Code Commands",
141
140
  "commandDiscovery.status": "Brain Dashboard",
142
141
  "commandDiscovery.health": "Health Check",
143
142
  "commandDiscovery.search": "Search Contexts",
@@ -145,8 +144,5 @@
145
144
  "commandDiscovery.tasks": "Task Manager",
146
145
  "commandDiscovery.backup": "Create Backup",
147
146
  "commandDiscovery.optimize": "Optimize DB",
148
- "commandDiscovery.help": "Show all commands",
149
- "commandDiscovery.clear": "Clear conversation",
150
- "commandDiscovery.reset": "Reset session",
151
147
  "commandDiscovery.footer": "Type 'ccjk --help' for full command list"
152
148
  }
@@ -10,7 +10,7 @@
10
10
  "updateDesc": "Update all components to latest version",
11
11
  "updateComplete": "Update complete! All components are up to date.",
12
12
  "notify": "Notifications",
13
- "notifyDesc": "View system notifications and announcements",
13
+ "notifyDesc": "Configure task alerts, channels, and delivery methods",
14
14
  "more": "More",
15
15
  "running": "Running..."
16
16
  },
@@ -91,7 +91,7 @@
91
91
  "model": "Model Configuration",
92
92
  "modelDesc": "Select and configure AI models",
93
93
  "memory": "Memory Configuration",
94
- "memoryDesc": "Configure conversation memory settings",
94
+ "memoryDesc": "Manage project memory sync and AI response preferences",
95
95
  "permission": "Permission Configuration",
96
96
  "permissionDesc": "Manage tool and file permissions",
97
97
  "configSwitch": "Config Switch",
@@ -189,7 +189,7 @@
189
189
  "model": "Model Configuration",
190
190
  "modelDesc": "Select and configure AI models",
191
191
  "memory": "Memory Configuration",
192
- "memoryDesc": "Configure conversation memory settings",
192
+ "memoryDesc": "Manage project memory sync and AI response preferences",
193
193
  "permission": "Permission Configuration",
194
194
  "permissionDesc": "Manage tool and file permissions",
195
195
  "configSwitch": "Config Switch",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "title": "Notification System",
3
- "description": "Task completion notifications via Feishu, WeChat Work, Email, SMS",
3
+ "description": "Task alerts and completion notifications via cloud and local delivery channels",
4
4
 
5
5
  "status.enabled": "Enabled",
6
6
  "status.disabled": "Disabled",
@@ -126,7 +126,7 @@
126
126
  "errors.cloudError": "Cloud service error: {{error}}",
127
127
  "errors.tokenInvalid": "Device token is invalid. Please regenerate.",
128
128
 
129
- "menu.title": "📱 Notification Settings",
129
+ "menu.title": "📱 Task Alert Settings",
130
130
  "menu.configure": "Configure Notifications",
131
131
  "menu.viewStatus": "View Status",
132
132
  "menu.testNotification": "Send Test",