@cleocode/cleo 2026.4.131 → 2026.4.133

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/dist/cli/index.js CHANGED
@@ -5148,6 +5148,43 @@ var init_registry = __esm({
5148
5148
  }
5149
5149
  ]
5150
5150
  },
5151
+ // T1147 W7 — BRAIN noise sweep (shadow-write envelope, self-healing gate)
5152
+ {
5153
+ gateway: "query",
5154
+ domain: "memory",
5155
+ operation: "sweep",
5156
+ description: "memory.sweep (query/mutate) \u2014 T1147 W7 BRAIN noise sweep. dry-run: detect noise candidates and write sample JSON to agent-outputs. approve <runId>: apply sweep to live brain tables (sets killSwitch during tx). status: list all noise-sweep-2440 runs. rollback <runId>: discard a staged run without applying changes.",
5157
+ tier: 0,
5158
+ idempotent: false,
5159
+ sessionRequired: false,
5160
+ requiredParams: [],
5161
+ params: [
5162
+ {
5163
+ name: "dry-run",
5164
+ type: "boolean",
5165
+ required: false,
5166
+ description: "Detect noise candidates without staging DB writes."
5167
+ },
5168
+ {
5169
+ name: "approve",
5170
+ type: "string",
5171
+ required: false,
5172
+ description: "Run ID to approve and apply to live tables."
5173
+ },
5174
+ {
5175
+ name: "status",
5176
+ type: "boolean",
5177
+ required: false,
5178
+ description: "List recent noise-sweep-2440 runs."
5179
+ },
5180
+ {
5181
+ name: "rollback",
5182
+ type: "string",
5183
+ required: false,
5184
+ description: "Run ID to roll back without applying changes."
5185
+ }
5186
+ ]
5187
+ },
5151
5188
  // T791 — LLM extraction backend status
5152
5189
  {
5153
5190
  gateway: "query",
@@ -19015,19 +19052,141 @@ var init_memory2 = __esm({
19015
19052
  const { scanBrainNoise } = await import("@cleocode/core/memory/brain-doctor.js");
19016
19053
  const result = await scanBrainNoise(projectRoot);
19017
19054
  const assertClean = params?.["assert-clean"];
19018
- if (assertClean && !result.isClean) {
19019
- return errorResult(
19055
+ if (assertClean) {
19056
+ let pendingCandidates = 0;
19057
+ try {
19058
+ const { getBrainNativeDb: _getDoctorNativeDb } = await import("@cleocode/core/store/memory-sqlite.js");
19059
+ const doctorNativeDb = _getDoctorNativeDb();
19060
+ if (doctorNativeDb) {
19061
+ const tableExists = doctorNativeDb.prepare(
19062
+ `SELECT name FROM sqlite_master WHERE type='table' AND name='brain_v2_candidate'`
19063
+ ).get();
19064
+ if (tableExists) {
19065
+ const countRow = doctorNativeDb.prepare(
19066
+ `SELECT COUNT(*) AS cnt FROM brain_v2_candidate WHERE validation_status = 'pending'`
19067
+ ).get();
19068
+ pendingCandidates = countRow?.cnt ?? 0;
19069
+ }
19070
+ }
19071
+ } catch {
19072
+ }
19073
+ if (!result.isClean) {
19074
+ return errorResult(
19075
+ "query",
19076
+ "memory",
19077
+ operation,
19078
+ "E_BRAIN_NOISE_DETECTED",
19079
+ `Brain noise detected: ${result.findings.length} pattern(s) across ${result.totalScanned} entries. ` + result.findings.map((f) => `${f.pattern}(${f.count})`).join(", ") + ". Run `cleo memory doctor` for details. Fix noise before enabling Sentient v1 (M7 gate).",
19080
+ startTime
19081
+ );
19082
+ }
19083
+ if (pendingCandidates > 0) {
19084
+ return errorResult(
19085
+ "query",
19086
+ "memory",
19087
+ operation,
19088
+ "E_SWEEP_PENDING",
19089
+ `Staged sweep has ${pendingCandidates} pending brain_v2_candidate rows. Run \`cleo memory sweep --status\` to review, then \`cleo memory sweep --approve <runId>\` to apply.`,
19090
+ startTime
19091
+ );
19092
+ }
19093
+ } else if (!result.isClean) {
19094
+ }
19095
+ return wrapResult(
19096
+ { success: true, data: { ...result, pendingCandidates: 0 } },
19097
+ "query",
19098
+ "memory",
19099
+ operation,
19100
+ startTime
19101
+ );
19102
+ }
19103
+ // T1147 W7 — BRAIN noise sweep (shadow-write envelope, self-healing gate)
19104
+ case "sweep": {
19105
+ const dryRun = params?.["dry-run"] === true || params?.dryRun === true;
19106
+ const approveRunId = params?.approve;
19107
+ const statusQuery = params?.status === true;
19108
+ const rollbackRunId = params?.rollback;
19109
+ if (statusQuery) {
19110
+ const { getBrainDb: _getBrainDb2, getBrainNativeDb: _getNativeDb2 } = await import("@cleocode/core/store/memory-sqlite.js");
19111
+ const sweepDb = await _getBrainDb2(projectRoot);
19112
+ const nativeDb2 = _getNativeDb2();
19113
+ if (!nativeDb2) {
19114
+ return errorResult(
19115
+ "query",
19116
+ "memory",
19117
+ operation,
19118
+ "E_DB_UNAVAILABLE",
19119
+ "brain.db not available",
19120
+ startTime
19121
+ );
19122
+ }
19123
+ const rows = nativeDb2.prepare(
19124
+ `SELECT id, status, rows_affected, created_at, approved_at, approved_by
19125
+ FROM brain_backfill_runs
19126
+ WHERE kind = 'noise-sweep-2440'
19127
+ ORDER BY created_at DESC
19128
+ LIMIT 20`
19129
+ ).all();
19130
+ void sweepDb;
19131
+ return wrapResult(
19132
+ { success: true, data: { runs: rows } },
19020
19133
  "query",
19021
19134
  "memory",
19022
19135
  operation,
19023
- "E_BRAIN_NOISE_DETECTED",
19024
- `Brain noise detected: ${result.findings.length} pattern(s) across ${result.totalScanned} entries. ` + result.findings.map((f) => `${f.pattern}(${f.count})`).join(", ") + ". Run `cleo memory doctor` for details. Fix noise before enabling Sentient v1 (M7 gate).",
19025
19136
  startTime
19026
19137
  );
19027
19138
  }
19139
+ if (approveRunId) {
19140
+ const { executeSweep } = await import("@cleocode/core/memory/brain-sweep-executor.js");
19141
+ const result = await executeSweep({
19142
+ projectRoot,
19143
+ runId: approveRunId,
19144
+ approvedBy: "cleo-cli"
19145
+ });
19146
+ if (!result.success) {
19147
+ return errorResult(
19148
+ "mutate",
19149
+ "memory",
19150
+ operation,
19151
+ "E_SWEEP_FAILED",
19152
+ result.errorMessage ?? "Sweep failed",
19153
+ startTime
19154
+ );
19155
+ }
19156
+ return wrapResult(
19157
+ { success: true, data: result },
19158
+ "mutate",
19159
+ "memory",
19160
+ operation,
19161
+ startTime
19162
+ );
19163
+ }
19164
+ if (rollbackRunId) {
19165
+ const { rollbackSweep } = await import("@cleocode/core/memory/brain-sweep-executor.js");
19166
+ const rolled = await rollbackSweep(projectRoot, rollbackRunId);
19167
+ if (!rolled) {
19168
+ return errorResult(
19169
+ "mutate",
19170
+ "memory",
19171
+ operation,
19172
+ "E_SWEEP_ROLLBACK_FAILED",
19173
+ `Run '${rollbackRunId}' not found or not in staged status`,
19174
+ startTime
19175
+ );
19176
+ }
19177
+ return wrapResult(
19178
+ { success: true, data: { rolledBack: rollbackRunId } },
19179
+ "mutate",
19180
+ "memory",
19181
+ operation,
19182
+ startTime
19183
+ );
19184
+ }
19185
+ const { detectNoiseCandidates } = await import("@cleocode/core/memory/brain-noise-detector.js");
19186
+ const detectResult = await detectNoiseCandidates(projectRoot, { dryRun });
19028
19187
  return wrapResult(
19029
- { success: true, data: result },
19030
- "query",
19188
+ { success: true, data: detectResult },
19189
+ dryRun ? "query" : "mutate",
19031
19190
  "memory",
19032
19191
  operation,
19033
19192
  startTime
@@ -20131,8 +20290,10 @@ var init_memory2 = __esm({
20131
20290
  "code.links",
20132
20291
  "code.memories-for-code",
20133
20292
  "code.for-memory",
20134
- // T1262 — brain noise detector (E1-parallel, read-only)
20293
+ // T1262 — brain noise detector (E1-parallel, read-only) + assert-clean gate
20135
20294
  "doctor",
20295
+ // T1147 W7 — sweep status query (dry-run mode)
20296
+ "sweep",
20136
20297
  // T791 — LLM extraction backend status
20137
20298
  "llm-status",
20138
20299
  // T792 — pending verification queue
@@ -29465,8 +29626,31 @@ var init_sentient = __esm({
29465
29626
  }
29466
29627
  /**
29467
29628
  * Enable or disable Tier-2 proposal generation.
29629
+ *
29630
+ * When `enabled=true`, enforces the M7 gate (T-COUNCIL-RECONCILIATION-2026-04-24):
29631
+ * `cleo memory doctor --assert-clean` must pass before Tier-2 is activated.
29632
+ * Returns `E_M7_GATE_FAILED` if the brain corpus is not clean.
29633
+ *
29634
+ * @task T1148 W8-7
29468
29635
  */
29469
29636
  async setTier2Enabled(projectRoot, enabled) {
29637
+ if (enabled) {
29638
+ try {
29639
+ const { scanBrainNoise } = await import("@cleocode/core/memory/brain-doctor.js");
29640
+ const doctorResult = await scanBrainNoise(projectRoot);
29641
+ if (!doctorResult.isClean) {
29642
+ return {
29643
+ success: false,
29644
+ error: {
29645
+ code: "E_M7_GATE_FAILED",
29646
+ message: `M7 gate blocked: brain corpus has ${doctorResult.findings.length} noise pattern(s) across ${doctorResult.totalScanned} entries. Run \`cleo memory doctor\` for details, then \`cleo memory sweep --approve\` to clean before enabling Sentient v1.`,
29647
+ details: { findings: doctorResult.findings, totalScanned: doctorResult.totalScanned }
29648
+ }
29649
+ };
29650
+ }
29651
+ } catch {
29652
+ }
29653
+ }
29470
29654
  const { patchSentientState: patchSentientState2 } = await import("@cleocode/core/sentient/state.js");
29471
29655
  const { SENTIENT_STATE_FILE: SENTIENT_STATE_FILE2 } = await import("@cleocode/core/sentient/daemon.js");
29472
29656
  const statePath = join6(projectRoot, SENTIENT_STATE_FILE2);
@@ -47171,6 +47355,51 @@ var tierCommand = defineCommand({
47171
47355
  demote: tierDemoteCommand
47172
47356
  }
47173
47357
  });
47358
+ var sweepCommand = defineCommand({
47359
+ meta: {
47360
+ name: "sweep",
47361
+ description: "T1147 W7 BRAIN noise sweep. --dry-run: detect noise candidates. --approve <runId>: apply to live tables. --status: list runs. --rollback <runId>: discard staged run."
47362
+ },
47363
+ args: {
47364
+ "dry-run": {
47365
+ type: "boolean",
47366
+ description: "Detect noise candidates without staging DB writes."
47367
+ },
47368
+ approve: {
47369
+ type: "string",
47370
+ description: "Run ID to approve and apply to live tables."
47371
+ },
47372
+ status: {
47373
+ type: "boolean",
47374
+ description: "List recent noise-sweep-2440 runs."
47375
+ },
47376
+ rollback: {
47377
+ type: "string",
47378
+ description: "Run ID to roll back without applying changes."
47379
+ },
47380
+ json: {
47381
+ type: "boolean",
47382
+ description: "Output as JSON"
47383
+ }
47384
+ },
47385
+ async run({
47386
+ args
47387
+ }) {
47388
+ const gateway = args.approve || args.rollback ? "mutate" : "query";
47389
+ await dispatchFromCli(
47390
+ gateway,
47391
+ "memory",
47392
+ "sweep",
47393
+ {
47394
+ "dry-run": args["dry-run"],
47395
+ approve: args.approve,
47396
+ status: args.status,
47397
+ rollback: args.rollback
47398
+ },
47399
+ { command: "memory-sweep", operation: "memory.sweep" }
47400
+ );
47401
+ }
47402
+ });
47174
47403
  var memoryCommand = defineCommand({
47175
47404
  meta: { name: "memory", description: "BRAIN memory operations (patterns, learnings)" },
47176
47405
  subCommands: {
@@ -47214,7 +47443,9 @@ var memoryCommand = defineCommand({
47214
47443
  digest: digestCommand,
47215
47444
  recent: recentCommand,
47216
47445
  diary: diaryCommand,
47217
- watch: watchCommand2
47446
+ watch: watchCommand2,
47447
+ // T1147 W7 — BRAIN noise sweep
47448
+ sweep: sweepCommand
47218
47449
  },
47219
47450
  async run({ cmd, rawArgs }) {
47220
47451
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));