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 +2 -2
- package/dist-cli/runtrim.js +301 -142
- package/package.json +1 -1
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
|
-
-
|
|
94
|
-
-
|
|
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
|
|
package/dist-cli/runtrim.js
CHANGED
|
@@ -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.
|
|
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
|
|
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.
|
|
4731
|
+
console.log(chalk.yellow(' No runs found. Start with: runtrim go "your task"'));
|
|
4661
4732
|
console.log("");
|
|
4662
4733
|
return;
|
|
4663
4734
|
}
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
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
|
-
|
|
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: (
|
|
4739
|
-
sensitiveScope: (
|
|
4740
|
-
forbiddenScope: (
|
|
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
|
-
|
|
4751
|
-
const
|
|
4752
|
-
|
|
4753
|
-
|
|
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
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
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
|
-
|
|
4770
|
-
const
|
|
4771
|
-
|
|
4772
|
-
|
|
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 (
|
|
4787
|
-
console.log(
|
|
4788
|
-
|
|
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
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
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
|
-
|
|
4801
|
-
|
|
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
|
-
|
|
4805
|
-
|
|
4806
|
-
console.log(
|
|
4807
|
-
}
|
|
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
|
|
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
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
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
|
|
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
|
-
|
|
5084
|
-
|
|
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(
|
|
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;
|