runtrim 0.1.3 → 0.1.4
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 +295 -141
- 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.3",
|
|
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.
|
|
4661
|
-
console.log("");
|
|
4662
|
-
return;
|
|
4663
|
-
}
|
|
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."));
|
|
4731
|
+
console.log(chalk.yellow(' No runs found. Start with: runtrim go "your task"'));
|
|
4707
4732
|
console.log("");
|
|
4708
4733
|
return;
|
|
4709
4734
|
}
|
|
4710
|
-
const
|
|
4711
|
-
const changedFiles = await getGitDiff(cwd);
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
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,131 @@ 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 (run.status === "guarded") verificationDebt.add("Run is still guarded and not checked.");
|
|
4774
|
+
if (changedFiles.length > 0 && !run.evaluation) verificationDebt.add("Changed files exist but no post-run check was recorded.");
|
|
4775
|
+
if (scope.sensitiveFiles.length > 0) verificationDebt.add("Sensitive files changed. Review and verify before continuing.");
|
|
4776
|
+
if (scope.forbiddenFiles.length > 0) verificationDebt.add("Forbidden files changed. Manual containment required.");
|
|
4777
|
+
if (changedFiles.length > maxFiles) verificationDebt.add("Too many files changed for one scoped run. Split the task.");
|
|
4778
|
+
if (lowerChanged.some((f) => /(^|\/)(package-lock\.json|pnpm-lock\.yaml|yarn\.lock)$/.test(f))) {
|
|
4779
|
+
verificationDebt.add("Lockfile changed. Confirm dependency intent.");
|
|
4780
|
+
}
|
|
4781
|
+
if (lowerChanged.some((f) => /(migration|migrations|schema|database)/.test(f))) {
|
|
4782
|
+
verificationDebt.add("Database or migration-related changes need explicit verification.");
|
|
4783
|
+
}
|
|
4784
|
+
if (lowerChanged.some((f) => /(middleware|auth|login|session|jwt|payment|billing|stripe|webhook)/.test(f))) {
|
|
4785
|
+
verificationDebt.add("Auth, middleware, payment, or webhook surface changed. Run focused verification.");
|
|
4786
|
+
}
|
|
4787
|
+
if (scope.outOfScopeFiles.length > 0) {
|
|
4788
|
+
verificationDebt.add("Some changed files appear outside declared relevant scope.");
|
|
4789
|
+
}
|
|
4790
|
+
for (const item of (_j = (_i = run.evaluation) == null ? void 0 : _i.missingProofItems) != null ? _j : []) verificationDebt.add(item);
|
|
4791
|
+
let nextSafeAction = "Run is ready to continue.";
|
|
4792
|
+
if (scope.forbiddenFiles.length > 0) {
|
|
4793
|
+
nextSafeAction = "Stop and inspect forbidden files before continuing.";
|
|
4794
|
+
} else if (scope.sensitiveFiles.length > 0) {
|
|
4795
|
+
nextSafeAction = "Review sensitive changes, then run tests before continuing.";
|
|
4796
|
+
} else if (changedFiles.length > maxFiles) {
|
|
4797
|
+
nextSafeAction = "Stop scope drift and split the task.";
|
|
4798
|
+
} else if (changedFiles.length === 0) {
|
|
4799
|
+
nextSafeAction = "No local changes detected. Continue or prepare the next run.";
|
|
4800
|
+
} else if (verificationDebt.size > 0) {
|
|
4801
|
+
nextSafeAction = "Resolve verification debt, then run runtrim check again.";
|
|
4802
|
+
}
|
|
4803
|
+
evaluation.nextSafeAction = nextSafeAction;
|
|
4804
|
+
evaluation.nextPrompt = evaluation.nextGuardedPrompt;
|
|
4805
|
+
evaluation.nextSafePrompt = evaluation.nextGuardedPrompt;
|
|
4806
|
+
const checkSummary = {
|
|
4807
|
+
checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4808
|
+
changedFilesCount: changedFiles.length,
|
|
4809
|
+
allowedCount: scope.relevantFiles.length,
|
|
4810
|
+
sensitiveCount: scope.sensitiveFiles.length,
|
|
4811
|
+
forbiddenCount: scope.forbiddenFiles.length,
|
|
4812
|
+
outsideScopeCount: scope.outOfScopeFiles.length,
|
|
4813
|
+
verificationDebt: [...verificationDebt],
|
|
4814
|
+
riskFlags: [...riskFlags],
|
|
4815
|
+
nextSafeAction
|
|
4768
4816
|
};
|
|
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("");
|
|
4817
|
+
updateRun(run.id, { evaluation, checkSummary, status: "checked" }, cwd);
|
|
4818
|
+
const latestAfterUpdate = loadLatestRun(cwd);
|
|
4819
|
+
if (latestAfterUpdate && configExists(cwd)) {
|
|
4820
|
+
writeMemoryFromRuns(latestAfterUpdate, loadAllRuns(cwd), loadConfig(cwd), cwd);
|
|
4785
4821
|
}
|
|
4786
|
-
if (
|
|
4787
|
-
console.log(
|
|
4788
|
-
|
|
4822
|
+
if (options.json) {
|
|
4823
|
+
console.log(
|
|
4824
|
+
JSON.stringify(
|
|
4825
|
+
{
|
|
4826
|
+
runId: run.id,
|
|
4827
|
+
task: run.task,
|
|
4828
|
+
scopeResult: {
|
|
4829
|
+
allowedChanges: checkSummary.allowedCount,
|
|
4830
|
+
sensitiveChanges: checkSummary.sensitiveCount,
|
|
4831
|
+
forbiddenChanges: checkSummary.forbiddenCount,
|
|
4832
|
+
outsideScope: checkSummary.outsideScopeCount
|
|
4833
|
+
},
|
|
4834
|
+
verificationDebt: checkSummary.verificationDebt,
|
|
4835
|
+
riskFlags: checkSummary.riskFlags,
|
|
4836
|
+
changedFiles,
|
|
4837
|
+
nextSafeAction: checkSummary.nextSafeAction,
|
|
4838
|
+
checkedAt: checkSummary.checkedAt
|
|
4839
|
+
},
|
|
4840
|
+
null,
|
|
4841
|
+
2
|
|
4842
|
+
)
|
|
4843
|
+
);
|
|
4789
4844
|
console.log("");
|
|
4845
|
+
return;
|
|
4790
4846
|
}
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4847
|
+
const changedPreview = changedFiles.slice(0, 8);
|
|
4848
|
+
const extraCount = Math.max(0, changedFiles.length - changedPreview.length);
|
|
4849
|
+
console.log(BOLD("Run"));
|
|
4850
|
+
console.log(chalk.white(((_k = run.task) == null ? void 0 : _k.trim()) ? truncate(run.task, 68) : "Latest run"));
|
|
4851
|
+
console.log("");
|
|
4852
|
+
console.log(BOLD("Scope result"));
|
|
4853
|
+
console.log(chalk.white(`- Allowed changes: ${checkSummary.allowedCount}`));
|
|
4854
|
+
console.log(chalk.white(`- Sensitive changes: ${checkSummary.sensitiveCount}`));
|
|
4855
|
+
console.log(chalk.white(`- Forbidden changes: ${checkSummary.forbiddenCount}`));
|
|
4856
|
+
console.log(chalk.white(`- Outside scope: ${checkSummary.outsideScopeCount}`));
|
|
4857
|
+
console.log("");
|
|
4858
|
+
console.log(BOLD("Verification debt"));
|
|
4859
|
+
if (checkSummary.verificationDebt.length === 0) {
|
|
4860
|
+
console.log(chalk.white("No verification debt recorded."));
|
|
4861
|
+
} else {
|
|
4862
|
+
for (const item of checkSummary.verificationDebt) console.log(chalk.white(`- ${item}`));
|
|
4795
4863
|
}
|
|
4796
|
-
console.log(DIM(" " + SECTION));
|
|
4797
|
-
console.log(DIM(" NEXT GUARDED PROMPT"));
|
|
4798
|
-
console.log(DIM(" " + SECTION));
|
|
4799
4864
|
console.log("");
|
|
4800
|
-
|
|
4801
|
-
|
|
4865
|
+
console.log(BOLD("Risk flags"));
|
|
4866
|
+
if (checkSummary.riskFlags.length === 0) {
|
|
4867
|
+
console.log(chalk.white("No high-risk flags detected."));
|
|
4868
|
+
} else {
|
|
4869
|
+
for (const flag of checkSummary.riskFlags) console.log(chalk.white(`- ${flag}`));
|
|
4802
4870
|
}
|
|
4803
4871
|
console.log("");
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
console.log(
|
|
4807
|
-
}
|
|
4872
|
+
console.log(BOLD("Changed files"));
|
|
4873
|
+
if (changedFiles.length === 0) {
|
|
4874
|
+
console.log(chalk.white("No local changed files detected."));
|
|
4875
|
+
} else {
|
|
4876
|
+
for (const file of changedPreview) console.log(chalk.white(`- ${file}`));
|
|
4877
|
+
if (extraCount > 0) console.log(chalk.white(`+${extraCount} more`));
|
|
4808
4878
|
}
|
|
4809
4879
|
console.log("");
|
|
4880
|
+
console.log(BOLD("Next safe action"));
|
|
4881
|
+
console.log(chalk.white(checkSummary.nextSafeAction));
|
|
4882
|
+
console.log("");
|
|
4810
4883
|
});
|
|
4811
4884
|
program.command("sync").description("Sync local RunTrim metadata to dashboard").action(async () => {
|
|
4812
4885
|
var _a2, _b;
|
|
@@ -5029,23 +5102,25 @@ program.command("panel").description("Open local RunTrim browser panel").option(
|
|
|
5029
5102
|
cwd
|
|
5030
5103
|
});
|
|
5031
5104
|
});
|
|
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;
|
|
5105
|
+
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) => {
|
|
5106
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
5034
5107
|
const cwd = process.cwd();
|
|
5035
5108
|
console.log("");
|
|
5036
5109
|
console.log(BOLD("RunTrim") + DIM(" memory"));
|
|
5037
5110
|
console.log("");
|
|
5111
|
+
const config = configExists(cwd) ? loadConfig(cwd) : DEFAULT_CONFIG;
|
|
5112
|
+
const audit = (_a2 = loadProjectAudit(cwd)) != null ? _a2 : performBaselineProjectAudit(cwd, null);
|
|
5113
|
+
const memoryPath = path9.join(getConfigDir(cwd), "memory.md");
|
|
5038
5114
|
const latestRun = loadLatestRun(cwd);
|
|
5039
5115
|
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
5116
|
let memory2 = readMemory(cwd);
|
|
5044
5117
|
if (!memory2) {
|
|
5118
|
+
const memoryDir = path9.dirname(memoryPath);
|
|
5119
|
+
if (!fs9.existsSync(memoryDir)) fs9.mkdirSync(memoryDir, { recursive: true });
|
|
5045
5120
|
memory2 = buildBaselineMemoryMarkdown(audit);
|
|
5046
5121
|
fs9.writeFileSync(memoryPath, memory2, "utf-8");
|
|
5047
5122
|
}
|
|
5048
|
-
const baselinePrompt = 'runtrim
|
|
5123
|
+
const baselinePrompt = 'runtrim go "your task"';
|
|
5049
5124
|
if (options.prompt) {
|
|
5050
5125
|
console.log(baselinePrompt);
|
|
5051
5126
|
await copyToClipboardSafe(baselinePrompt);
|
|
@@ -5054,9 +5129,37 @@ program.command("memory").description("Show project memory and latest next safe
|
|
|
5054
5129
|
console.log("");
|
|
5055
5130
|
return;
|
|
5056
5131
|
}
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5132
|
+
if (options.full) {
|
|
5133
|
+
console.log(memory2);
|
|
5134
|
+
console.log("");
|
|
5135
|
+
}
|
|
5136
|
+
console.log(BOLD("Project"));
|
|
5137
|
+
console.log(chalk.white(audit.projectName || cwd));
|
|
5138
|
+
console.log("");
|
|
5139
|
+
console.log(BOLD("Current state"));
|
|
5140
|
+
console.log(chalk.white("No runs recorded yet."));
|
|
5141
|
+
console.log("");
|
|
5142
|
+
console.log(BOLD("Latest run"));
|
|
5143
|
+
console.log(chalk.white("- Task: none"));
|
|
5144
|
+
console.log(chalk.white("- Status: baseline"));
|
|
5145
|
+
console.log(chalk.white("- Proof: needs check"));
|
|
5146
|
+
console.log(chalk.white(`- Next: ${baselinePrompt}`));
|
|
5147
|
+
console.log("");
|
|
5148
|
+
console.log(BOLD("Protected systems"));
|
|
5149
|
+
const protectedSystems2 = collectProtectedSystems(null, config, audit);
|
|
5150
|
+
console.log(chalk.white((protectedSystems2.length ? protectedSystems2 : ["auth", "middleware", "database", "env/secrets", "billing", "webhooks", "migrations"]).join(", ")));
|
|
5151
|
+
console.log("");
|
|
5152
|
+
console.log(BOLD("Recent context"));
|
|
5153
|
+
console.log(chalk.white("No recent memory items yet."));
|
|
5154
|
+
console.log("");
|
|
5155
|
+
console.log(BOLD("Continuation"));
|
|
5156
|
+
console.log(chalk.white("No continuation prompt yet. Run `runtrim continue --reason usage_limit` when context runs out."));
|
|
5157
|
+
console.log("");
|
|
5158
|
+
console.log(BOLD("Useful commands"));
|
|
5159
|
+
console.log(chalk.white('- runtrim go "your task"'));
|
|
5160
|
+
console.log(chalk.white("- runtrim panel --monitor"));
|
|
5161
|
+
console.log(chalk.white("- runtrim check"));
|
|
5162
|
+
console.log(chalk.white("- runtrim continue --reason usage_limit"));
|
|
5060
5163
|
console.log("");
|
|
5061
5164
|
if (config.baselineInitialized !== true) {
|
|
5062
5165
|
config.baselineInitialized = true;
|
|
@@ -5065,7 +5168,8 @@ program.command("memory").description("Show project memory and latest next safe
|
|
|
5065
5168
|
}
|
|
5066
5169
|
return;
|
|
5067
5170
|
}
|
|
5068
|
-
const
|
|
5171
|
+
const allRuns = loadAllRuns(cwd);
|
|
5172
|
+
const memory = writeMemoryFromRuns(latestRun, allRuns, config, cwd);
|
|
5069
5173
|
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
5174
|
if (options.prompt) {
|
|
5071
5175
|
if (!latestPrompt) {
|
|
@@ -5080,14 +5184,64 @@ program.command("memory").description("Show project memory and latest next safe
|
|
|
5080
5184
|
console.log("");
|
|
5081
5185
|
return;
|
|
5082
5186
|
}
|
|
5083
|
-
|
|
5187
|
+
if (options.full) {
|
|
5188
|
+
console.log(memory);
|
|
5189
|
+
console.log("");
|
|
5190
|
+
}
|
|
5191
|
+
const status = (_i = (_h = latestRun.evaluation) == null ? void 0 : _h.status) != null ? _i : latestRun.status;
|
|
5192
|
+
const checkSummary = latestRun.checkSummary;
|
|
5193
|
+
const protectedSystems = collectProtectedSystems(latestRun, config, audit);
|
|
5194
|
+
const recent = allRuns.slice(0, 3).map((r) => {
|
|
5195
|
+
var _a3, _b2;
|
|
5196
|
+
const s = (_b2 = (_a3 = r.evaluation) == null ? void 0 : _a3.status) != null ? _b2 : r.status;
|
|
5197
|
+
return `- ${truncate(r.task, 56)} (${s})`;
|
|
5198
|
+
});
|
|
5199
|
+
const nextAction = (_l = (_k = checkSummary == null ? void 0 : checkSummary.nextSafeAction) != null ? _k : (_j = latestRun.evaluation) == null ? void 0 : _j.nextSafeAction) != null ? _l : "runtrim check";
|
|
5200
|
+
const proofState = checkSummary ? checkSummary.verificationDebt.length > 0 ? "verification debt" : "checked" : latestRun.evaluation ? latestRun.evaluation.missingProofItems.length > 0 ? "verification debt" : "checked" : "needs check";
|
|
5201
|
+
console.log(BOLD("Project"));
|
|
5202
|
+
console.log(chalk.white(audit.projectName || cwd));
|
|
5203
|
+
console.log("");
|
|
5204
|
+
console.log(BOLD("Current state"));
|
|
5205
|
+
console.log(chalk.white(((_m = latestRun.evaluation) == null ? void 0 : _m.memorySummary) || `Latest run is ${status}.`));
|
|
5206
|
+
console.log("");
|
|
5207
|
+
console.log(BOLD("Latest run"));
|
|
5208
|
+
console.log(chalk.white(`- Task: ${truncate(latestRun.task, 72)}`));
|
|
5209
|
+
console.log(chalk.white(`- Status: ${status}`));
|
|
5210
|
+
console.log(chalk.white(`- Proof: ${proofState}`));
|
|
5211
|
+
console.log(chalk.white(`- Next: ${nextAction}`));
|
|
5212
|
+
console.log("");
|
|
5213
|
+
console.log(BOLD("Protected systems"));
|
|
5214
|
+
console.log(chalk.white((protectedSystems.length ? protectedSystems : ["auth", "middleware", "database", "env/secrets", "billing", "webhooks", "migrations"]).join(", ")));
|
|
5215
|
+
console.log("");
|
|
5216
|
+
console.log(BOLD("Recent context"));
|
|
5217
|
+
if (recent.length > 0) {
|
|
5218
|
+
for (const line of recent) console.log(chalk.white(line));
|
|
5219
|
+
} else {
|
|
5220
|
+
console.log(chalk.white("No recent memory items yet."));
|
|
5221
|
+
}
|
|
5222
|
+
console.log("");
|
|
5223
|
+
console.log(BOLD("Continuation"));
|
|
5084
5224
|
if (latestPrompt) {
|
|
5225
|
+
const compact = latestPrompt.replace(/\s+/g, " ").trim();
|
|
5226
|
+
const isDrift = /scope drift detected/i.test(compact);
|
|
5227
|
+
if (isDrift) {
|
|
5228
|
+
console.log(chalk.white("Scope drift detected. Run `runtrim check` before continuing."));
|
|
5229
|
+
} else if (compact.length > 160) {
|
|
5230
|
+
console.log(chalk.white(truncate(compact, 160)));
|
|
5231
|
+
} else {
|
|
5232
|
+
console.log(chalk.white(compact));
|
|
5233
|
+
}
|
|
5085
5234
|
await copyToClipboardSafe(latestPrompt);
|
|
5086
|
-
console.log(ACCENT.bold(" Project memory loaded. Latest next safe prompt copied."));
|
|
5087
5235
|
} else {
|
|
5088
|
-
console.log(
|
|
5236
|
+
console.log(chalk.white("No continuation prompt yet. Run `runtrim continue --reason usage_limit` when context runs out."));
|
|
5089
5237
|
}
|
|
5090
5238
|
console.log("");
|
|
5239
|
+
console.log(BOLD("Useful commands"));
|
|
5240
|
+
console.log(chalk.white('- runtrim go "your task"'));
|
|
5241
|
+
console.log(chalk.white("- runtrim panel --monitor"));
|
|
5242
|
+
console.log(chalk.white("- runtrim check"));
|
|
5243
|
+
console.log(chalk.white("- runtrim continue --reason usage_limit"));
|
|
5244
|
+
console.log("");
|
|
5091
5245
|
});
|
|
5092
5246
|
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
5247
|
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|