runtrim 0.1.3 → 0.1.5

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 CHANGED
@@ -90,8 +90,8 @@ npm run runtrim -- start
90
90
  - blocks unsafe mega-runs and suggests split-safe follow-ups
91
91
  - generates guarded prompts with explicit stop rules
92
92
  - monitors changed files during execution
93
- - checks output quality and missing proof after edits
94
- - stores local run memory in `.runtrim/`
93
+ - reviews changed files, risk flags, verification debt, and next safe action after edits
94
+ - shows current project memory, latest run state, and continuation guidance in `.runtrim/`
95
95
 
96
96
  ## Core commands
97
97
 
@@ -32,7 +32,7 @@ import { execa as execa3 } from "execa";
32
32
  // package.json
33
33
  var package_default = {
34
34
  name: "runtrim",
35
- version: "0.1.2",
35
+ version: "0.1.4",
36
36
  description: "CLI guard layer that scopes AI coding runs before they waste tokens.",
37
37
  license: "MIT",
38
38
  author: "RunTrim",
@@ -3420,6 +3420,77 @@ function parseMemorySection2(memory, title) {
3420
3420
  function dedupeFiles(files) {
3421
3421
  return [...new Set(files.filter(Boolean).map((f) => f.replace(/\\/g, "/")))];
3422
3422
  }
3423
+ var HIGH_RISK_PATH_KEYWORDS = [
3424
+ "auth",
3425
+ "login",
3426
+ "signup",
3427
+ "session",
3428
+ "jwt",
3429
+ "middleware",
3430
+ "proxy",
3431
+ "billing",
3432
+ "payment",
3433
+ "stripe",
3434
+ "dodo",
3435
+ "checkout",
3436
+ "webhook",
3437
+ "database",
3438
+ "schema",
3439
+ "migration",
3440
+ "supabase",
3441
+ "env",
3442
+ "secret",
3443
+ "token",
3444
+ "admin",
3445
+ "permission",
3446
+ "security",
3447
+ "package.json",
3448
+ "package-lock.json",
3449
+ "pnpm-lock.yaml",
3450
+ "yarn.lock"
3451
+ ];
3452
+ function inferMaxFilesFromScope(scope, fallback) {
3453
+ var _a2, _b;
3454
+ const text = scope.join(" ").toLowerCase();
3455
+ const n = Number.parseInt((_b = (_a2 = text.match(/maximum\s+(\d+)\s+files/)) == null ? void 0 : _a2[1]) != null ? _b : "", 10);
3456
+ if (Number.isFinite(n) && n > 0) return n;
3457
+ return Math.max(1, fallback || 5);
3458
+ }
3459
+ function collectProtectedSystems(run, config, audit) {
3460
+ var _a2, _b, _c, _d, _e, _f;
3461
+ const values = /* @__PURE__ */ new Set();
3462
+ const add = (v) => {
3463
+ const x = v.trim().toLowerCase();
3464
+ if (!x) return;
3465
+ values.add(x);
3466
+ };
3467
+ for (const a of (_a2 = config.sensitiveAreas) != null ? _a2 : []) add(a);
3468
+ for (const a of (_b = audit == null ? void 0 : audit.protectedAreas) != null ? _b : []) add(a);
3469
+ for (const s of (_d = (_c = run == null ? void 0 : run.contract.contract) == null ? void 0 : _c.sensitiveScope) != null ? _d : []) add(s);
3470
+ for (const s of (_f = (_e = run == null ? void 0 : run.contract.contract) == null ? void 0 : _e.forbiddenScope) != null ? _f : []) add(s);
3471
+ const mapped = /* @__PURE__ */ new Set();
3472
+ for (const raw of values) {
3473
+ if (raw.includes("auth")) mapped.add("auth");
3474
+ if (raw.includes("middleware") || raw.includes("proxy")) mapped.add("middleware");
3475
+ if (raw.includes("database") || raw.includes("schema") || raw.includes("migration")) mapped.add("database");
3476
+ if (raw.includes("env") || raw.includes("secret")) mapped.add("env/secrets");
3477
+ if (raw.includes("billing")) mapped.add("billing");
3478
+ if (raw.includes("payment") || raw.includes("stripe") || raw.includes("dodo")) mapped.add("payments");
3479
+ if (raw.includes("webhook")) mapped.add("webhooks");
3480
+ if (raw.includes("package") || raw.includes("lock")) mapped.add("package/config changes");
3481
+ }
3482
+ const ordered = [
3483
+ "auth",
3484
+ "middleware",
3485
+ "database",
3486
+ "env/secrets",
3487
+ "billing",
3488
+ "payments",
3489
+ "webhooks",
3490
+ "package/config changes"
3491
+ ];
3492
+ return ordered.filter((x) => mapped.has(x));
3493
+ }
3423
3494
  var CONTINUATION_REASONS = [
3424
3495
  "usage_limit",
3425
3496
  "credits_exhausted",
@@ -4649,95 +4720,32 @@ program.command("go <task>").description("Daily shortcut: initialize if needed,
4649
4720
  console.log(chalk.white("Run `runtrim --help` for panel, check, memory and continuation commands."));
4650
4721
  console.log("");
4651
4722
  });
4652
- program.command("check").description("Check the latest run and evaluate agent output").action(async () => {
4653
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
4723
+ program.command("check").description("Check the latest run and evaluate agent output").option("--json", "Print machine-readable check summary").action(async (options) => {
4724
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
4654
4725
  const cwd = process.cwd();
4655
4726
  console.log("");
4656
4727
  console.log(BOLD("RunTrim") + DIM(" check"));
4657
4728
  console.log("");
4658
4729
  const run = loadLatestRun(cwd);
4659
4730
  if (!run) {
4660
- console.log(chalk.yellow(' No runs found. Run: runtrim guard "your task"'));
4731
+ console.log(chalk.yellow(' No runs found. Start with: runtrim go "your task"'));
4661
4732
  console.log("");
4662
4733
  return;
4663
4734
  }
4664
- if (run.evaluation) {
4665
- const { recheck } = await prompts({
4666
- type: "confirm",
4667
- name: "recheck",
4668
- message: "Latest run already has an evaluation. Re-check now?",
4669
- initial: false
4670
- });
4671
- if (!recheck) {
4672
- console.log(DIM(" Skipped. Existing evaluation retained."));
4673
- console.log("");
4674
- return;
4675
- }
4676
- }
4677
- console.log(DIM(" Latest run: ") + chalk.white(truncate(run.task, 55)));
4678
- console.log(DIM(" Guarded at: ") + chalk.white(formatDate(run.createdAt)));
4679
- console.log("");
4680
- if (run.status === "blocked" || run.status === "split_required") {
4681
- const evaluationBase2 = evaluateAgentOutput(null, [], {
4682
- task: run.task,
4683
- relevantScope: (_b = (_a2 = run.contract.contract) == null ? void 0 : _a2.relevantScope) != null ? _b : [],
4684
- sensitiveScope: (_d = (_c = run.contract.contract) == null ? void 0 : _c.sensitiveScope) != null ? _d : [],
4685
- forbiddenScope: (_f = (_e = run.contract.contract) == null ? void 0 : _e.forbiddenScope) != null ? _f : [],
4686
- runStatus: run.status
4687
- });
4688
- const evaluation2 = __spreadProps(__spreadValues({}, evaluationBase2), {
4689
- nextPrompt: evaluationBase2.nextGuardedPrompt,
4690
- nextSafePrompt: evaluationBase2.nextGuardedPrompt,
4691
- nextSafeAction: evaluationBase2.nextSafeAction,
4692
- memorySummary: evaluationBase2.memorySummary,
4693
- evaluatedAt: evaluationBase2.evaluatedAt
4694
- });
4695
- updateRun(run.id, { evaluation: evaluation2, status: "checked" }, cwd);
4696
- const latestAfterUpdate2 = loadLatestRun(cwd);
4697
- if (latestAfterUpdate2) {
4698
- writeMemoryFromRuns(latestAfterUpdate2, loadAllRuns(cwd), loadConfig(cwd), cwd);
4699
- }
4700
- await copyToClipboardSafe(evaluation2.nextPrompt);
4701
- console.log(chalk.yellow(" Latest run was blocked. Start with the recommended split audit task."));
4702
- console.log("");
4703
- console.log(DIM(" Next safe prompt:"));
4704
- for (const line of evaluation2.nextPrompt.split("\n")) console.log(DIM(" " + line));
4705
- console.log("");
4706
- console.log(ACCENT.bold(" Next prompt copied to clipboard."));
4707
- console.log("");
4708
- return;
4709
- }
4710
- const diffSpinner = oraFactory({ text: "Reading git diff...", color: "yellow" }).start();
4711
- const changedFiles = await getGitDiff(cwd);
4712
- diffSpinner.stop();
4713
- if (changedFiles.length > 0) {
4714
- console.log(DIM(" Changed files (" + changedFiles.length + "):"));
4715
- for (const f of changedFiles) console.log(DIM(" " + f));
4716
- console.log("");
4717
- } else {
4718
- console.log(DIM(" No git changes detected since last commit."));
4719
- console.log("");
4720
- }
4721
- const { pasteOutput } = await prompts({
4722
- type: "confirm",
4723
- name: "pasteOutput",
4724
- message: "Evaluate agent output? (paste output or skip)",
4725
- initial: true
4735
+ const config = configExists(cwd) ? loadConfig(cwd) : DEFAULT_CONFIG;
4736
+ const changedFiles = dedupeFiles(await getGitDiff(cwd));
4737
+ const maxFiles = inferMaxFilesFromScope((_b = (_a2 = run.contract.contract) == null ? void 0 : _a2.relevantScope) != null ? _b : [], config.maxFilesPerRun);
4738
+ const scope = evaluateWatchState({
4739
+ changedFiles,
4740
+ run,
4741
+ maxFilesPerRun: maxFiles,
4742
+ strict: false
4726
4743
  });
4727
- let agentOutput = null;
4728
- if (pasteOutput) {
4729
- const { output } = await prompts({
4730
- type: "text",
4731
- name: "output",
4732
- message: "Paste agent output:"
4733
- });
4734
- agentOutput = output != null ? output : null;
4735
- }
4736
- const evaluationBase = evaluateAgentOutput(agentOutput, changedFiles, {
4744
+ const evaluationBase = evaluateAgentOutput(null, changedFiles, {
4737
4745
  task: run.task,
4738
- relevantScope: (_h = (_g = run.contract.contract) == null ? void 0 : _g.relevantScope) != null ? _h : [],
4739
- sensitiveScope: (_j = (_i = run.contract.contract) == null ? void 0 : _i.sensitiveScope) != null ? _j : [],
4740
- forbiddenScope: (_l = (_k = run.contract.contract) == null ? void 0 : _k.forbiddenScope) != null ? _l : [],
4746
+ relevantScope: (_d = (_c = run.contract.contract) == null ? void 0 : _c.relevantScope) != null ? _d : [],
4747
+ sensitiveScope: (_f = (_e = run.contract.contract) == null ? void 0 : _e.sensitiveScope) != null ? _f : [],
4748
+ forbiddenScope: (_h = (_g = run.contract.contract) == null ? void 0 : _g.forbiddenScope) != null ? _h : [],
4741
4749
  runStatus: run.status
4742
4750
  });
4743
4751
  const evaluation = __spreadProps(__spreadValues({}, evaluationBase), {
@@ -4747,66 +4755,133 @@ program.command("check").description("Check the latest run and evaluate agent ou
4747
4755
  memorySummary: evaluationBase.memorySummary,
4748
4756
  evaluatedAt: evaluationBase.evaluatedAt
4749
4757
  });
4750
- updateRun(run.id, { evaluation, status: "checked" }, cwd);
4751
- const latestAfterUpdate = loadLatestRun(cwd);
4752
- if (latestAfterUpdate) {
4753
- writeMemoryFromRuns(latestAfterUpdate, loadAllRuns(cwd), loadConfig(cwd), cwd);
4758
+ const lowerChanged = changedFiles.map((f) => f.toLowerCase());
4759
+ const riskFlags = /* @__PURE__ */ new Set();
4760
+ for (const file of lowerChanged) {
4761
+ for (const kw of HIGH_RISK_PATH_KEYWORDS) {
4762
+ if (file.includes(kw)) {
4763
+ riskFlags.add(`High-risk path touched: ${kw}`);
4764
+ break;
4765
+ }
4766
+ }
4754
4767
  }
4755
- const statusColors2 = {
4756
- passed: chalk.green,
4757
- partial: chalk.yellow,
4758
- needs_verification: chalk.hex("#FF8C00"),
4759
- no_changes_detected: chalk.hex("#FF8C00"),
4760
- drift_detected: chalk.red,
4761
- blocked: chalk.red
4762
- };
4763
- const driftColors = {
4764
- none: chalk.green,
4765
- low: chalk.yellow,
4766
- medium: chalk.hex("#FF8C00"),
4767
- high: chalk.red
4768
+ if (scope.forbiddenFiles.length > 0) riskFlags.add("Forbidden scope changed");
4769
+ if (scope.sensitiveFiles.length > 0) riskFlags.add("Sensitive scope changed");
4770
+ if (scope.outOfScopeFiles.length > 0) riskFlags.add("Potential outside-scope changes detected");
4771
+ if (changedFiles.length > maxFiles) riskFlags.add(`File count exceeded scope limit (${maxFiles})`);
4772
+ const verificationDebt = /* @__PURE__ */ new Set();
4773
+ if (changedFiles.length > 0) {
4774
+ if (run.status === "guarded") verificationDebt.add("Run is still guarded and not checked.");
4775
+ if (!run.evaluation) verificationDebt.add("Changed files exist but no post-run check was recorded.");
4776
+ if (scope.sensitiveFiles.length > 0) verificationDebt.add("Sensitive files changed. Review and verify before continuing.");
4777
+ if (scope.forbiddenFiles.length > 0) verificationDebt.add("Forbidden files changed. Manual containment required.");
4778
+ if (changedFiles.length > maxFiles) verificationDebt.add("Too many files changed for one scoped run. Split the task.");
4779
+ if (lowerChanged.some((f) => /(^|\/)(package-lock\.json|pnpm-lock\.yaml|yarn\.lock)$/.test(f))) {
4780
+ verificationDebt.add("Lockfile changed. Confirm dependency intent.");
4781
+ }
4782
+ if (lowerChanged.some((f) => /(migration|migrations|schema|database)/.test(f))) {
4783
+ verificationDebt.add("Database or migration-related changes need explicit verification.");
4784
+ }
4785
+ if (lowerChanged.some((f) => /(middleware|auth|login|session|jwt|payment|billing|stripe|webhook)/.test(f))) {
4786
+ verificationDebt.add("Auth, middleware, payment, or webhook surface changed. Run focused verification.");
4787
+ }
4788
+ if (scope.outOfScopeFiles.length > 0) {
4789
+ verificationDebt.add("Some changed files appear outside declared relevant scope.");
4790
+ }
4791
+ for (const item of (_j = (_i = run.evaluation) == null ? void 0 : _i.missingProofItems) != null ? _j : []) verificationDebt.add(item);
4792
+ }
4793
+ let nextSafeAction = "Run is ready to continue.";
4794
+ if (scope.forbiddenFiles.length > 0) {
4795
+ nextSafeAction = "Stop and inspect forbidden files before continuing.";
4796
+ } else if (scope.sensitiveFiles.length > 0) {
4797
+ nextSafeAction = "Review sensitive changes, then run tests before continuing.";
4798
+ } else if (changedFiles.length > maxFiles) {
4799
+ nextSafeAction = "Stop scope drift and split the task.";
4800
+ } else if (changedFiles.length === 0) {
4801
+ nextSafeAction = "No local changes detected. Continue or prepare the next run.";
4802
+ } else if (verificationDebt.size > 0) {
4803
+ nextSafeAction = "Resolve verification debt, then run runtrim check again.";
4804
+ }
4805
+ evaluation.nextSafeAction = nextSafeAction;
4806
+ evaluation.nextPrompt = evaluation.nextGuardedPrompt;
4807
+ evaluation.nextSafePrompt = evaluation.nextGuardedPrompt;
4808
+ const checkSummary = {
4809
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
4810
+ changedFilesCount: changedFiles.length,
4811
+ allowedCount: scope.relevantFiles.length,
4812
+ sensitiveCount: scope.sensitiveFiles.length,
4813
+ forbiddenCount: scope.forbiddenFiles.length,
4814
+ outsideScopeCount: scope.outOfScopeFiles.length,
4815
+ verificationDebt: [...verificationDebt],
4816
+ riskFlags: [...riskFlags],
4817
+ nextSafeAction
4768
4818
  };
4769
- const statusColor = (_m = statusColors2[evaluation.status]) != null ? _m : chalk.white;
4770
- const driftColor = (_n = driftColors[evaluation.scopeDriftRisk]) != null ? _n : chalk.white;
4771
- console.log("");
4772
- console.log(DIM(" " + SECTION));
4773
- console.log(DIM(" EVALUATION"));
4774
- console.log(DIM(" " + SECTION));
4775
- console.log("");
4776
- console.log(DIM(" Status ") + statusColor(formatStatus(evaluation.status).toUpperCase()));
4777
- console.log(DIM(" Contract score ") + chalk.white(formatScore(evaluation.contractScore)));
4778
- console.log(DIM(" Scope drift ") + driftColor(evaluation.scopeDriftRisk.toUpperCase()));
4779
- console.log(DIM(" Next action ") + chalk.white(evaluation.nextSafeAction));
4780
- console.log("");
4781
- if (evaluation.driftedFiles.length > 0) {
4782
- console.log(chalk.red(" Drifted files:"));
4783
- for (const f of evaluation.driftedFiles) console.log(chalk.red(" x " + f));
4784
- console.log("");
4819
+ updateRun(run.id, { evaluation, checkSummary, status: "checked" }, cwd);
4820
+ const latestAfterUpdate = loadLatestRun(cwd);
4821
+ if (latestAfterUpdate && configExists(cwd)) {
4822
+ writeMemoryFromRuns(latestAfterUpdate, loadAllRuns(cwd), loadConfig(cwd), cwd);
4785
4823
  }
4786
- if (evaluation.outOfScopeFiles.length > 0) {
4787
- console.log(chalk.yellow(" Out-of-scope files:"));
4788
- for (const f of evaluation.outOfScopeFiles) console.log(DIM(" - " + f));
4824
+ if (options.json) {
4825
+ console.log(
4826
+ JSON.stringify(
4827
+ {
4828
+ runId: run.id,
4829
+ task: run.task,
4830
+ scopeResult: {
4831
+ allowedChanges: checkSummary.allowedCount,
4832
+ sensitiveChanges: checkSummary.sensitiveCount,
4833
+ forbiddenChanges: checkSummary.forbiddenCount,
4834
+ outsideScope: checkSummary.outsideScopeCount
4835
+ },
4836
+ verificationDebt: checkSummary.verificationDebt,
4837
+ riskFlags: checkSummary.riskFlags,
4838
+ changedFiles,
4839
+ nextSafeAction: checkSummary.nextSafeAction,
4840
+ checkedAt: checkSummary.checkedAt
4841
+ },
4842
+ null,
4843
+ 2
4844
+ )
4845
+ );
4789
4846
  console.log("");
4847
+ return;
4790
4848
  }
4791
- if (evaluation.missingProofItems.length > 0) {
4792
- console.log(chalk.yellow(" Missing:"));
4793
- for (const item of evaluation.missingProofItems) console.log(DIM(" - " + item));
4794
- console.log("");
4849
+ const changedPreview = changedFiles.slice(0, 8);
4850
+ const extraCount = Math.max(0, changedFiles.length - changedPreview.length);
4851
+ console.log(BOLD("Run"));
4852
+ console.log(chalk.white(((_k = run.task) == null ? void 0 : _k.trim()) ? truncate(run.task, 68) : "Latest run"));
4853
+ console.log("");
4854
+ console.log(BOLD("Scope result"));
4855
+ console.log(chalk.white(`- Allowed changes: ${checkSummary.allowedCount}`));
4856
+ console.log(chalk.white(`- Sensitive changes: ${checkSummary.sensitiveCount}`));
4857
+ console.log(chalk.white(`- Forbidden changes: ${checkSummary.forbiddenCount}`));
4858
+ console.log(chalk.white(`- Outside scope: ${checkSummary.outsideScopeCount}`));
4859
+ console.log("");
4860
+ console.log(BOLD("Verification debt"));
4861
+ if (checkSummary.verificationDebt.length === 0) {
4862
+ console.log(chalk.white("No verification debt recorded."));
4863
+ } else {
4864
+ for (const item of checkSummary.verificationDebt) console.log(chalk.white(`- ${item}`));
4795
4865
  }
4796
- console.log(DIM(" " + SECTION));
4797
- console.log(DIM(" NEXT GUARDED PROMPT"));
4798
- console.log(DIM(" " + SECTION));
4799
4866
  console.log("");
4800
- for (const line of evaluation.nextPrompt.split("\n")) {
4801
- console.log(DIM(" " + line));
4867
+ console.log(BOLD("Risk flags"));
4868
+ if (checkSummary.riskFlags.length === 0) {
4869
+ console.log(chalk.white("No high-risk flags detected."));
4870
+ } else {
4871
+ for (const flag of checkSummary.riskFlags) console.log(chalk.white(`- ${flag}`));
4802
4872
  }
4803
4873
  console.log("");
4804
- try {
4805
- await clipboard.write(evaluation.nextPrompt);
4806
- console.log(ACCENT.bold(" Next prompt copied to clipboard."));
4807
- } catch (e) {
4874
+ console.log(BOLD("Changed files"));
4875
+ if (changedFiles.length === 0) {
4876
+ console.log(chalk.white("No local changed files detected."));
4877
+ } else {
4878
+ for (const file of changedPreview) console.log(chalk.white(`- ${file}`));
4879
+ if (extraCount > 0) console.log(chalk.white(`+${extraCount} more`));
4808
4880
  }
4809
4881
  console.log("");
4882
+ console.log(BOLD("Next safe action"));
4883
+ console.log(chalk.white(checkSummary.nextSafeAction));
4884
+ console.log("");
4810
4885
  });
4811
4886
  program.command("sync").description("Sync local RunTrim metadata to dashboard").action(async () => {
4812
4887
  var _a2, _b;
@@ -5029,23 +5104,25 @@ program.command("panel").description("Open local RunTrim browser panel").option(
5029
5104
  cwd
5030
5105
  });
5031
5106
  });
5032
- program.command("memory").description("Show project memory and latest next safe prompt").option("--prompt", "Print only latest next safe prompt").action(async (options) => {
5033
- var _a2, _b, _c, _d, _e, _f, _g;
5107
+ program.command("memory").description("Show project memory and latest next safe prompt").option("--prompt", "Print only latest next safe prompt").option("--full", "Print full memory markdown").action(async (options) => {
5108
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
5034
5109
  const cwd = process.cwd();
5035
5110
  console.log("");
5036
5111
  console.log(BOLD("RunTrim") + DIM(" memory"));
5037
5112
  console.log("");
5113
+ const config = configExists(cwd) ? loadConfig(cwd) : DEFAULT_CONFIG;
5114
+ const audit = (_a2 = loadProjectAudit(cwd)) != null ? _a2 : performBaselineProjectAudit(cwd, null);
5115
+ const memoryPath = path9.join(getConfigDir(cwd), "memory.md");
5038
5116
  const latestRun = loadLatestRun(cwd);
5039
5117
  if (!latestRun) {
5040
- const config = configExists(cwd) ? loadConfig(cwd) : DEFAULT_CONFIG;
5041
- const audit = (_a2 = loadProjectAudit(cwd)) != null ? _a2 : performBaselineProjectAudit(cwd, null);
5042
- const memoryPath = path9.join(getConfigDir(cwd), "memory.md");
5043
5118
  let memory2 = readMemory(cwd);
5044
5119
  if (!memory2) {
5120
+ const memoryDir = path9.dirname(memoryPath);
5121
+ if (!fs9.existsSync(memoryDir)) fs9.mkdirSync(memoryDir, { recursive: true });
5045
5122
  memory2 = buildBaselineMemoryMarkdown(audit);
5046
5123
  fs9.writeFileSync(memoryPath, memory2, "utf-8");
5047
5124
  }
5048
- const baselinePrompt = 'runtrim prepare "describe your next AI coding task"';
5125
+ const baselinePrompt = 'runtrim go "your task"';
5049
5126
  if (options.prompt) {
5050
5127
  console.log(baselinePrompt);
5051
5128
  await copyToClipboardSafe(baselinePrompt);
@@ -5054,9 +5131,37 @@ program.command("memory").description("Show project memory and latest next safe
5054
5131
  console.log("");
5055
5132
  return;
5056
5133
  }
5057
- console.log(memory2);
5058
- await copyToClipboardSafe(baselinePrompt);
5059
- console.log(ACCENT.bold(" Project memory loaded. Latest next safe prompt copied."));
5134
+ if (options.full) {
5135
+ console.log(memory2);
5136
+ console.log("");
5137
+ }
5138
+ console.log(BOLD("Project"));
5139
+ console.log(chalk.white(audit.projectName || cwd));
5140
+ console.log("");
5141
+ console.log(BOLD("Current state"));
5142
+ console.log(chalk.white("No runs recorded yet."));
5143
+ console.log("");
5144
+ console.log(BOLD("Latest run"));
5145
+ console.log(chalk.white("- Task: none"));
5146
+ console.log(chalk.white("- Status: baseline"));
5147
+ console.log(chalk.white("- Proof: needs check"));
5148
+ console.log(chalk.white(`- Next: ${baselinePrompt}`));
5149
+ console.log("");
5150
+ console.log(BOLD("Protected systems"));
5151
+ const protectedSystems2 = collectProtectedSystems(null, config, audit);
5152
+ console.log(chalk.white((protectedSystems2.length ? protectedSystems2 : ["auth", "middleware", "database", "env/secrets", "billing", "webhooks", "migrations"]).join(", ")));
5153
+ console.log("");
5154
+ console.log(BOLD("Recent context"));
5155
+ console.log(chalk.white("No recent memory items yet."));
5156
+ console.log("");
5157
+ console.log(BOLD("Continuation"));
5158
+ console.log(chalk.white("No continuation prompt yet. Run `runtrim continue --reason usage_limit` when context runs out."));
5159
+ console.log("");
5160
+ console.log(BOLD("Useful commands"));
5161
+ console.log(chalk.white('- runtrim go "your task"'));
5162
+ console.log(chalk.white("- runtrim panel --monitor"));
5163
+ console.log(chalk.white("- runtrim check"));
5164
+ console.log(chalk.white("- runtrim continue --reason usage_limit"));
5060
5165
  console.log("");
5061
5166
  if (config.baselineInitialized !== true) {
5062
5167
  config.baselineInitialized = true;
@@ -5065,7 +5170,8 @@ program.command("memory").description("Show project memory and latest next safe
5065
5170
  }
5066
5171
  return;
5067
5172
  }
5068
- const memory = writeMemoryFromRuns(latestRun, loadAllRuns(cwd), loadConfig(cwd), cwd);
5173
+ const allRuns = loadAllRuns(cwd);
5174
+ const memory = writeMemoryFromRuns(latestRun, allRuns, config, cwd);
5069
5175
  const latestPrompt = (_g = (_f = (_d = (_b = latestRun == null ? void 0 : latestRun.evaluation) == null ? void 0 : _b.nextPrompt) != null ? _d : (_c = latestRun == null ? void 0 : latestRun.evaluation) == null ? void 0 : _c.nextSafePrompt) != null ? _f : (_e = latestRun == null ? void 0 : latestRun.evaluation) == null ? void 0 : _e.nextGuardedPrompt) != null ? _g : "";
5070
5176
  if (options.prompt) {
5071
5177
  if (!latestPrompt) {
@@ -5080,14 +5186,67 @@ program.command("memory").description("Show project memory and latest next safe
5080
5186
  console.log("");
5081
5187
  return;
5082
5188
  }
5083
- console.log(memory);
5084
- if (latestPrompt) {
5189
+ if (options.full) {
5190
+ console.log(memory);
5191
+ console.log("");
5192
+ }
5193
+ const status = (_i = (_h = latestRun.evaluation) == null ? void 0 : _h.status) != null ? _i : latestRun.status;
5194
+ const checkSummary = latestRun.checkSummary;
5195
+ const protectedSystems = collectProtectedSystems(latestRun, config, audit);
5196
+ const recent = allRuns.slice(0, 3).map((r) => {
5197
+ var _a3, _b2;
5198
+ const s = (_b2 = (_a3 = r.evaluation) == null ? void 0 : _a3.status) != null ? _b2 : r.status;
5199
+ return `- ${truncate(r.task, 56)} (${s})`;
5200
+ });
5201
+ const nextAction = (_l = (_k = checkSummary == null ? void 0 : checkSummary.nextSafeAction) != null ? _k : (_j = latestRun.evaluation) == null ? void 0 : _j.nextSafeAction) != null ? _l : "runtrim check";
5202
+ const proofState = checkSummary ? checkSummary.verificationDebt.length > 0 ? "verification debt" : "checked" : latestRun.evaluation ? latestRun.evaluation.missingProofItems.length > 0 ? "verification debt" : "checked" : "needs check";
5203
+ console.log(BOLD("Project"));
5204
+ console.log(chalk.white(audit.projectName || cwd));
5205
+ console.log("");
5206
+ console.log(BOLD("Current state"));
5207
+ console.log(chalk.white(((_m = latestRun.evaluation) == null ? void 0 : _m.memorySummary) || `Latest run is ${status}.`));
5208
+ console.log("");
5209
+ console.log(BOLD("Latest run"));
5210
+ console.log(chalk.white(`- Task: ${truncate(latestRun.task, 72)}`));
5211
+ console.log(chalk.white(`- Status: ${status}`));
5212
+ console.log(chalk.white(`- Proof: ${proofState}`));
5213
+ console.log(chalk.white(`- Next: ${nextAction}`));
5214
+ console.log("");
5215
+ console.log(BOLD("Protected systems"));
5216
+ console.log(chalk.white((protectedSystems.length ? protectedSystems : ["auth", "middleware", "database", "env/secrets", "billing", "webhooks", "migrations"]).join(", ")));
5217
+ console.log("");
5218
+ console.log(BOLD("Recent context"));
5219
+ if (recent.length > 0) {
5220
+ for (const line of recent) console.log(chalk.white(line));
5221
+ } else {
5222
+ console.log(chalk.white("No recent memory items yet."));
5223
+ }
5224
+ console.log("");
5225
+ console.log(BOLD("Continuation"));
5226
+ const noChangesState = status === "no_changes_detected" || ((_r = (_q = (_n = latestRun.checkSummary) == null ? void 0 : _n.changedFilesCount) != null ? _q : (_p = (_o = latestRun.evaluation) == null ? void 0 : _o.changedFiles) == null ? void 0 : _p.length) != null ? _r : 0) === 0;
5227
+ if (noChangesState) {
5228
+ console.log(chalk.white("No continuation prompt needed yet. Run `runtrim continue --reason usage_limit` when context runs out."));
5229
+ } else if (latestPrompt) {
5230
+ const compact = latestPrompt.replace(/\s+/g, " ").trim();
5231
+ const isDrift = /scope drift detected/i.test(compact);
5232
+ if (isDrift) {
5233
+ console.log(chalk.white("Scope drift detected. Run `runtrim check` before continuing."));
5234
+ } else if (compact.length > 160) {
5235
+ console.log(chalk.white(truncate(compact, 160)));
5236
+ } else {
5237
+ console.log(chalk.white(compact));
5238
+ }
5085
5239
  await copyToClipboardSafe(latestPrompt);
5086
- console.log(ACCENT.bold(" Project memory loaded. Latest next safe prompt copied."));
5087
5240
  } else {
5088
- console.log(DIM(" Project memory loaded."));
5241
+ console.log(chalk.white("No continuation prompt yet. Run `runtrim continue --reason usage_limit` when context runs out."));
5089
5242
  }
5090
5243
  console.log("");
5244
+ console.log(BOLD("Useful commands"));
5245
+ console.log(chalk.white('- runtrim go "your task"'));
5246
+ console.log(chalk.white("- runtrim panel --monitor"));
5247
+ console.log(chalk.white("- runtrim check"));
5248
+ console.log(chalk.white("- runtrim continue --reason usage_limit"));
5249
+ console.log("");
5091
5250
  });
5092
5251
  program.command("continue").description("Create a safe continuation prompt from latest RunTrim state").option("--reason <reason>", "Continuation reason").option("--agent <agent>", "Target agent hint").option("--print", "Print the full continuation prompt").option("--open", "Open continuation prompt in editor").option("--editor <editor>", "Editor command (code, cursor, or custom)").action(async (options) => {
5093
5252
  var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runtrim",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "CLI guard layer that scopes AI coding runs before they waste tokens.",
5
5
  "license": "MIT",
6
6
  "author": "RunTrim",