@sonnechasser/ntrp 0.1.7 → 0.1.8

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.
@@ -221,12 +221,15 @@ function getInstallId() {
221
221
  return ensureInstall().install_id;
222
222
  }
223
223
  function invalidateInstall() {
224
- cachedInstall = null;
224
+ clearInstallCache();
225
225
  const path = installPath();
226
226
  if (existsSync2(path)) {
227
227
  unlinkSync(path);
228
228
  }
229
229
  }
230
+ function clearInstallCache() {
231
+ cachedInstall = null;
232
+ }
230
233
  var cachedInstall;
231
234
  var init_install = __esm({
232
235
  "src/config/install.ts"() {
@@ -465,12 +468,20 @@ function saveProgress(state) {
465
468
  function invalidateProgress() {
466
469
  installMismatchWarned = false;
467
470
  invalidateInstall();
471
+ wipeProgressFiles();
472
+ }
473
+ function wipeProgressFiles() {
474
+ installMismatchWarned = false;
468
475
  for (const path of [progressPath2(), legacyStatePath2(), legacyStateBackupPath2()]) {
469
476
  if (existsSync4(path)) {
470
477
  unlinkSync2(path);
471
478
  }
472
479
  }
473
480
  }
481
+ function resetProgress() {
482
+ ensureInstall();
483
+ wipeProgressFiles();
484
+ }
474
485
  function appendCredit(state, credit) {
475
486
  const credits = [...state.credits, credit];
476
487
  if (credits.length > CREDIT_HISTORY_CAP) {
@@ -678,7 +689,7 @@ var init_connection = __esm({
678
689
  // src/services/scratch-wipe.ts
679
690
  import { existsSync as existsSync6, rmSync as rmSync2, unlinkSync as unlinkSync3 } from "fs";
680
691
  import { join as join6 } from "path";
681
- async function performScratchWipe() {
692
+ async function performScratchWipe(opts = {}) {
682
693
  const home = ntrpHome();
683
694
  const removed = [];
684
695
  try {
@@ -697,6 +708,13 @@ async function performScratchWipe() {
697
708
  { path: join6(home, "sessions"), kind: "dir" },
698
709
  { path: join6(home, "datasets"), kind: "dir" }
699
710
  ];
711
+ if (opts.includeProgress) {
712
+ targets.push(
713
+ { path: join6(home, "install.json"), kind: "file" },
714
+ { path: join6(home, "progress.json"), kind: "file" },
715
+ { path: join6(home, "state.json"), kind: "file" }
716
+ );
717
+ }
700
718
  for (const { path, kind } of targets) {
701
719
  if (!existsSync6(path)) continue;
702
720
  try {
@@ -709,12 +727,18 @@ async function performScratchWipe() {
709
727
  } catch {
710
728
  }
711
729
  }
730
+ if (opts.includeProgress) {
731
+ wipeProgressFiles();
732
+ clearInstallCache();
733
+ }
712
734
  resetConfigCache();
713
735
  return { removed };
714
736
  }
715
737
  var init_scratch_wipe = __esm({
716
738
  "src/services/scratch-wipe.ts"() {
717
739
  "use strict";
740
+ init_install();
741
+ init_progress();
718
742
  init_store();
719
743
  }
720
744
  });
@@ -18939,15 +18963,22 @@ __export(scratch_exports, {
18939
18963
  handler: () => handler18
18940
18964
  });
18941
18965
  import chalk33 from "chalk";
18942
- function printScratchPreamble() {
18966
+ function printScratchPreamble(includeProgress) {
18943
18967
  console.log();
18944
18968
  console.log(" " + chalk33.yellow.bold("This will permanently remove:"));
18945
18969
  console.log(" " + chalk33.dim(" \u2022 API key and all config.json settings"));
18946
18970
  console.log(" " + chalk33.dim(" \u2022 Company profile (you'll re-onboard on next use)"));
18947
18971
  console.log(" " + chalk33.dim(" \u2022 All sessions and datasets"));
18948
18972
  console.log(" " + chalk33.dim(" \u2022 Demo taxonomy cache"));
18973
+ if (includeProgress) {
18974
+ console.log(" " + chalk33.dim(" \u2022 Progress (hours saved) and install identity"));
18975
+ }
18949
18976
  console.log();
18950
- console.log(" " + chalk33.dim("Preserved: progress (hours saved), memory, strategies, wins, knowledge, exports, audit"));
18977
+ if (includeProgress) {
18978
+ console.log(" " + chalk33.dim("Preserved: memory, strategies, wins, knowledge, exports, audit"));
18979
+ } else {
18980
+ console.log(" " + chalk33.dim("Preserved: progress (hours saved), memory, strategies, wins, knowledge, exports, audit"));
18981
+ }
18951
18982
  console.log();
18952
18983
  }
18953
18984
  function resetContextAfterScratch(ctx) {
@@ -18969,24 +19000,26 @@ function resetContextAfterScratch(ctx) {
18969
19000
  ctx.lastExchange = void 0;
18970
19001
  }
18971
19002
  async function handler18(args, ctx) {
18972
- const { flags } = parseArgs(args, ["confirm"]);
19003
+ const { flags } = parseArgs(args, ["confirm", "include-progress"]);
18973
19004
  const confirmedFlag = getBool(flags, "confirm");
19005
+ const includeProgress = getBool(flags, "include-progress");
18974
19006
  const ok = await requireTypedWord(ctx, {
18975
- title: "Factory reset",
19007
+ title: includeProgress ? "Factory reset (including progress)" : "Factory reset",
18976
19008
  word: "scratch",
18977
19009
  confirmedFlag,
18978
- preamble: printScratchPreamble
19010
+ preamble: () => printScratchPreamble(includeProgress)
18979
19011
  });
18980
19012
  if (!ok) {
18981
19013
  printAdminCancelled("Scratch", 'Type "scratch" exactly to confirm.');
18982
19014
  return "Scratch cancelled";
18983
19015
  }
18984
- await performScratchWipe();
19016
+ await performScratchWipe({ includeProgress });
18985
19017
  resetContextAfterScratch(ctx);
18986
19018
  await rotateToFreshSession(ctx);
18987
19019
  await initSchema();
18988
19020
  console.log();
18989
- console.log(" " + paint("accent", "\u2713 Scratch complete") + chalk33.dim(" \u2014 local config and data wiped."));
19021
+ const detail = includeProgress ? " \u2014 local config, data, and progress wiped." : " \u2014 local config and data wiped.";
19022
+ console.log(" " + paint("accent", "\u2713 Scratch complete") + chalk33.dim(detail));
18990
19023
  console.log();
18991
19024
  if (ctx.oneShot) {
18992
19025
  console.log(
@@ -23089,7 +23122,18 @@ var progress_exports = {};
23089
23122
  __export(progress_exports, {
23090
23123
  handler: () => handler44
23091
23124
  });
23092
- async function handler44(_args, _ctx) {
23125
+ import chalk62 from "chalk";
23126
+ function printProgressResetPreamble() {
23127
+ console.log();
23128
+ console.log(" " + chalk62.yellow.bold("This will permanently remove:"));
23129
+ console.log(" " + chalk62.dim(" \u2022 Hours saved and milestone unlocks"));
23130
+ console.log(" " + chalk62.dim(" \u2022 Usage counters and weekly activity rollups"));
23131
+ console.log(" " + chalk62.dim(" \u2022 Credit history used for dedup"));
23132
+ console.log();
23133
+ console.log(" " + chalk62.dim("Preserved: install identity (install.json)"));
23134
+ console.log();
23135
+ }
23136
+ function showProgress() {
23093
23137
  const bank = getTimeBankSummary();
23094
23138
  if (bank.total_minutes <= 0) {
23095
23139
  console.log();
@@ -23100,10 +23144,53 @@ async function handler44(_args, _ctx) {
23100
23144
  renderProgressReport();
23101
23145
  return `Progress: ${bank.total_hours.toFixed(1)}h saved`;
23102
23146
  }
23147
+ async function handleReset(ctx, confirmedFlag) {
23148
+ const bank = getTimeBankSummary();
23149
+ if (bank.total_minutes <= 0) {
23150
+ console.log();
23151
+ console.log(" " + chalk62.dim("No progress to reset."));
23152
+ console.log();
23153
+ return "No progress to reset";
23154
+ }
23155
+ const ok = await requireTypedWord(ctx, {
23156
+ title: "Reset progress",
23157
+ word: "reset",
23158
+ confirmedFlag,
23159
+ preamble: printProgressResetPreamble,
23160
+ oneShotHint: "Re-run with: ntrp progress reset --confirm"
23161
+ });
23162
+ if (!ok) {
23163
+ printAdminCancelled("Progress reset", 'Type "reset" exactly to confirm.');
23164
+ return "Progress reset cancelled";
23165
+ }
23166
+ resetProgress();
23167
+ console.log();
23168
+ console.log(" " + paint("accent", "\u2713 Progress reset") + chalk62.dim(" \u2014 hours and milestones cleared."));
23169
+ console.log();
23170
+ return "Progress reset";
23171
+ }
23172
+ async function handler44(args, ctx) {
23173
+ const { positional, flags } = parseArgs(args, ["confirm"]);
23174
+ const sub = positional[0]?.toLowerCase();
23175
+ if (sub === "reset") {
23176
+ return handleReset(ctx, getBool(flags, "confirm"));
23177
+ }
23178
+ if (sub && sub !== "reset") {
23179
+ console.log();
23180
+ console.log(" " + chalk62.dim("Unknown subcommand. Try ") + paint("accent", "/progress") + chalk62.dim(" or ") + paint("accent", "/progress reset") + chalk62.dim("."));
23181
+ console.log();
23182
+ return;
23183
+ }
23184
+ return showProgress();
23185
+ }
23103
23186
  var init_progress2 = __esm({
23104
23187
  "src/commands/progress.ts"() {
23105
23188
  "use strict";
23189
+ init_argparse();
23190
+ init_admin_confirm();
23191
+ init_progress();
23106
23192
  init_progress_report();
23193
+ init_theme();
23107
23194
  init_time_bank();
23108
23195
  }
23109
23196
  });
@@ -23667,11 +23754,13 @@ Export the most recent diagnosis as terminal output, markdown, or JSON. Use
23667
23754
  name: progress
23668
23755
  description: Usage stats and milestone ladder
23669
23756
  section: Navigation
23757
+ args: [reset] [--confirm]
23670
23758
  handler: ../commands/progress.ts
23671
23759
  ---
23672
23760
 
23673
23761
  Hours saved, weekly activity trend, session counts, AI token usage, and the
23674
- full milestone ladder with progress bars.`
23762
+ full milestone ladder with progress bars. Use reset (type "reset" to confirm)
23763
+ to clear hours and milestones while keeping this install's identity.`
23675
23764
  },
23676
23765
  {
23677
23766
  name: "status",
@@ -23691,15 +23780,17 @@ diagnosis, if any.`
23691
23780
  name: scratch
23692
23781
  description: Wipe config, profile, and all datasets
23693
23782
  section: Admin
23694
- args: [--confirm]
23783
+ args: [--confirm] [--include-progress]
23695
23784
  handler: ../commands/scratch.ts
23696
23785
  hidden: true
23697
23786
  ---
23698
23787
 
23699
23788
  Minimal factory reset: removes API key, config, company profile, all sessions,
23700
- per-session datasets, and demo taxonomy cache. Preserves progress (hours saved), memory, strategies,
23701
- wins, knowledge, exports, and audit. Requires typing \`scratch\` in the REPL
23702
- or passing \`--confirm\` one-shot. Triggers onboarding on next interactive use.`
23789
+ per-session datasets, and demo taxonomy cache. Preserves progress (hours saved)
23790
+ by default. Pass \`--include-progress\` to also wipe install identity and hours.
23791
+ Also preserves memory, strategies, wins, knowledge, exports, and audit. Requires
23792
+ typing \`scratch\` in the REPL or passing \`--confirm\` one-shot. Triggers
23793
+ onboarding on next interactive use.`
23703
23794
  },
23704
23795
  {
23705
23796
  name: "cleanup",
@@ -24135,6 +24226,29 @@ function testInstallIdStable() {
24135
24226
  assert(id1 === id2, "install_id stable across loads");
24136
24227
  });
24137
24228
  }
24229
+ function testResetProgressKeepsInstall() {
24230
+ withTempHome(() => {
24231
+ const ctx = mockCtx();
24232
+ recordTimeCredit("diagnose", ctx, { silent: true });
24233
+ const installId = getInstallId();
24234
+ resetProgress();
24235
+ assert(loadProgress().total_minutes_saved === 0, "reset should clear hours");
24236
+ assert(getInstallId() === installId, "reset should keep install_id");
24237
+ assert(existsSync21(join28(ntrpHome(), "install.json")), "install.json should remain");
24238
+ });
24239
+ }
24240
+ async function testScratchIncludeProgressWipesHours() {
24241
+ await withTempHomeAsync(async () => {
24242
+ const ctx = mockCtx();
24243
+ recordTimeCredit("diagnose", ctx, { silent: true });
24244
+ const installId = getInstallId();
24245
+ await performScratchWipe({ includeProgress: true });
24246
+ assert(!existsSync21(join28(ntrpHome(), "install.json")), "include-progress should remove install.json");
24247
+ const state = loadProgress();
24248
+ assert(state.total_minutes_saved === 0, "include-progress should clear hours");
24249
+ assert(state.install_id !== installId, "include-progress should issue new install_id");
24250
+ });
24251
+ }
24138
24252
  testCreditDedup();
24139
24253
  testMilestoneBoundary();
24140
24254
  testNextMilestone();
@@ -24150,12 +24264,14 @@ testUsageBackfillFromCredits();
24150
24264
  testInstallCreatedOnFirstLoad();
24151
24265
  testLegacyStateMigration();
24152
24266
  testInstallIdStable();
24267
+ testResetProgressKeepsInstall();
24153
24268
  async function testProgressCommandRegistered() {
24154
24269
  assert(hasCommand("progress"), "/progress should be in workflow registry");
24155
24270
  const handler45 = await resolveHandler("progress");
24156
24271
  assert(typeof handler45 === "function", "progress handler should load from importHandler map");
24157
24272
  }
24158
24273
  await testProgressSurvivesScratchWipe();
24274
+ await testScratchIncludeProgressWipesHours();
24159
24275
  await testProgressCommandRegistered();
24160
24276
  console.log("time bank smoke passed");
24161
24277
  //# sourceMappingURL=time-bank-smoke.js.map