decision-memory 0.1.2 → 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.
@@ -1,20 +1,34 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- __commonJS,
4
- __require,
5
- __toESM,
6
- appendDecision,
7
- formatContextSummaryAsToon,
8
- initDecisionFile,
9
- parseDecisionFile,
10
- resolveDecisionFilePath,
11
- searchDecisions,
12
- serializeDecisionRow
13
- } from "./chunk-5VFZ3YOK.js";
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
14
28
 
15
29
  // node_modules/commander/lib/error.js
16
30
  var require_error = __commonJS({
17
- "node_modules/commander/lib/error.js"(exports) {
31
+ "node_modules/commander/lib/error.js"(exports2) {
18
32
  var CommanderError2 = class extends Error {
19
33
  /**
20
34
  * Constructs the CommanderError class
@@ -42,14 +56,14 @@ var require_error = __commonJS({
42
56
  this.name = this.constructor.name;
43
57
  }
44
58
  };
45
- exports.CommanderError = CommanderError2;
46
- exports.InvalidArgumentError = InvalidArgumentError2;
59
+ exports2.CommanderError = CommanderError2;
60
+ exports2.InvalidArgumentError = InvalidArgumentError2;
47
61
  }
48
62
  });
49
63
 
50
64
  // node_modules/commander/lib/argument.js
51
65
  var require_argument = __commonJS({
52
- "node_modules/commander/lib/argument.js"(exports) {
66
+ "node_modules/commander/lib/argument.js"(exports2) {
53
67
  var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
54
68
  var Argument2 = class {
55
69
  /**
@@ -169,14 +183,14 @@ var require_argument = __commonJS({
169
183
  const nameOutput = arg.name() + (arg.variadic === true ? "..." : "");
170
184
  return arg.required ? "<" + nameOutput + ">" : "[" + nameOutput + "]";
171
185
  }
172
- exports.Argument = Argument2;
173
- exports.humanReadableArgName = humanReadableArgName;
186
+ exports2.Argument = Argument2;
187
+ exports2.humanReadableArgName = humanReadableArgName;
174
188
  }
175
189
  });
176
190
 
177
191
  // node_modules/commander/lib/help.js
178
192
  var require_help = __commonJS({
179
- "node_modules/commander/lib/help.js"(exports) {
193
+ "node_modules/commander/lib/help.js"(exports2) {
180
194
  var { humanReadableArgName } = require_argument();
181
195
  var Help2 = class {
182
196
  constructor() {
@@ -584,13 +598,13 @@ var require_help = __commonJS({
584
598
  }).join("\n");
585
599
  }
586
600
  };
587
- exports.Help = Help2;
601
+ exports2.Help = Help2;
588
602
  }
589
603
  });
590
604
 
591
605
  // node_modules/commander/lib/option.js
592
606
  var require_option = __commonJS({
593
- "node_modules/commander/lib/option.js"(exports) {
607
+ "node_modules/commander/lib/option.js"(exports2) {
594
608
  var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
595
609
  var Option2 = class {
596
610
  /**
@@ -855,14 +869,14 @@ var require_option = __commonJS({
855
869
  }
856
870
  return { shortFlag, longFlag };
857
871
  }
858
- exports.Option = Option2;
859
- exports.DualOptions = DualOptions;
872
+ exports2.Option = Option2;
873
+ exports2.DualOptions = DualOptions;
860
874
  }
861
875
  });
862
876
 
863
877
  // node_modules/commander/lib/suggestSimilar.js
864
878
  var require_suggestSimilar = __commonJS({
865
- "node_modules/commander/lib/suggestSimilar.js"(exports) {
879
+ "node_modules/commander/lib/suggestSimilar.js"(exports2) {
866
880
  var maxDistance = 3;
867
881
  function editDistance(a, b) {
868
882
  if (Math.abs(a.length - b.length) > maxDistance)
@@ -936,18 +950,18 @@ var require_suggestSimilar = __commonJS({
936
950
  }
937
951
  return "";
938
952
  }
939
- exports.suggestSimilar = suggestSimilar;
953
+ exports2.suggestSimilar = suggestSimilar;
940
954
  }
941
955
  });
942
956
 
943
957
  // node_modules/commander/lib/command.js
944
958
  var require_command = __commonJS({
945
- "node_modules/commander/lib/command.js"(exports) {
946
- var EventEmitter = __require("events").EventEmitter;
947
- var childProcess = __require("child_process");
948
- var path2 = __require("path");
949
- var fs4 = __require("fs");
950
- var process2 = __require("process");
959
+ "node_modules/commander/lib/command.js"(exports2) {
960
+ var EventEmitter = require("events").EventEmitter;
961
+ var childProcess = require("child_process");
962
+ var path3 = require("path");
963
+ var fs5 = require("fs");
964
+ var process2 = require("process");
951
965
  var { Argument: Argument2, humanReadableArgName } = require_argument();
952
966
  var { CommanderError: CommanderError2 } = require_error();
953
967
  var { Help: Help2 } = require_help();
@@ -1879,11 +1893,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1879
1893
  let launchWithNode = false;
1880
1894
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1881
1895
  function findFile(baseDir, baseName) {
1882
- const localBin = path2.resolve(baseDir, baseName);
1883
- if (fs4.existsSync(localBin)) return localBin;
1884
- if (sourceExt.includes(path2.extname(baseName))) return void 0;
1896
+ const localBin = path3.resolve(baseDir, baseName);
1897
+ if (fs5.existsSync(localBin)) return localBin;
1898
+ if (sourceExt.includes(path3.extname(baseName))) return void 0;
1885
1899
  const foundExt = sourceExt.find(
1886
- (ext) => fs4.existsSync(`${localBin}${ext}`)
1900
+ (ext) => fs5.existsSync(`${localBin}${ext}`)
1887
1901
  );
1888
1902
  if (foundExt) return `${localBin}${foundExt}`;
1889
1903
  return void 0;
@@ -1895,21 +1909,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
1895
1909
  if (this._scriptPath) {
1896
1910
  let resolvedScriptPath;
1897
1911
  try {
1898
- resolvedScriptPath = fs4.realpathSync(this._scriptPath);
1912
+ resolvedScriptPath = fs5.realpathSync(this._scriptPath);
1899
1913
  } catch (err) {
1900
1914
  resolvedScriptPath = this._scriptPath;
1901
1915
  }
1902
- executableDir = path2.resolve(
1903
- path2.dirname(resolvedScriptPath),
1916
+ executableDir = path3.resolve(
1917
+ path3.dirname(resolvedScriptPath),
1904
1918
  executableDir
1905
1919
  );
1906
1920
  }
1907
1921
  if (executableDir) {
1908
1922
  let localFile = findFile(executableDir, executableFile);
1909
1923
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1910
- const legacyName = path2.basename(
1924
+ const legacyName = path3.basename(
1911
1925
  this._scriptPath,
1912
- path2.extname(this._scriptPath)
1926
+ path3.extname(this._scriptPath)
1913
1927
  );
1914
1928
  if (legacyName !== this._name) {
1915
1929
  localFile = findFile(
@@ -1920,7 +1934,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1920
1934
  }
1921
1935
  executableFile = localFile || executableFile;
1922
1936
  }
1923
- launchWithNode = sourceExt.includes(path2.extname(executableFile));
1937
+ launchWithNode = sourceExt.includes(path3.extname(executableFile));
1924
1938
  let proc;
1925
1939
  if (process2.platform !== "win32") {
1926
1940
  if (launchWithNode) {
@@ -2762,7 +2776,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2762
2776
  * @return {Command}
2763
2777
  */
2764
2778
  nameFromFilename(filename) {
2765
- this._name = path2.basename(filename, path2.extname(filename));
2779
+ this._name = path3.basename(filename, path3.extname(filename));
2766
2780
  return this;
2767
2781
  }
2768
2782
  /**
@@ -2776,9 +2790,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2776
2790
  * @param {string} [path]
2777
2791
  * @return {(string|null|Command)}
2778
2792
  */
2779
- executableDir(path3) {
2780
- if (path3 === void 0) return this._executableDir;
2781
- this._executableDir = path3;
2793
+ executableDir(path4) {
2794
+ if (path4 === void 0) return this._executableDir;
2795
+ this._executableDir = path4;
2782
2796
  return this;
2783
2797
  }
2784
2798
  /**
@@ -2983,29 +2997,29 @@ Expecting one of '${allowedValues.join("', '")}'`);
2983
2997
  return arg;
2984
2998
  });
2985
2999
  }
2986
- exports.Command = Command2;
3000
+ exports2.Command = Command2;
2987
3001
  }
2988
3002
  });
2989
3003
 
2990
3004
  // node_modules/commander/index.js
2991
3005
  var require_commander = __commonJS({
2992
- "node_modules/commander/index.js"(exports) {
3006
+ "node_modules/commander/index.js"(exports2) {
2993
3007
  var { Argument: Argument2 } = require_argument();
2994
3008
  var { Command: Command2 } = require_command();
2995
3009
  var { CommanderError: CommanderError2, InvalidArgumentError: InvalidArgumentError2 } = require_error();
2996
3010
  var { Help: Help2 } = require_help();
2997
3011
  var { Option: Option2 } = require_option();
2998
- exports.program = new Command2();
2999
- exports.createCommand = (name) => new Command2(name);
3000
- exports.createOption = (flags, description) => new Option2(flags, description);
3001
- exports.createArgument = (name, description) => new Argument2(name, description);
3002
- exports.Command = Command2;
3003
- exports.Option = Option2;
3004
- exports.Argument = Argument2;
3005
- exports.Help = Help2;
3006
- exports.CommanderError = CommanderError2;
3007
- exports.InvalidArgumentError = InvalidArgumentError2;
3008
- exports.InvalidOptionArgumentError = InvalidArgumentError2;
3012
+ exports2.program = new Command2();
3013
+ exports2.createCommand = (name) => new Command2(name);
3014
+ exports2.createOption = (flags, description) => new Option2(flags, description);
3015
+ exports2.createArgument = (name, description) => new Argument2(name, description);
3016
+ exports2.Command = Command2;
3017
+ exports2.Option = Option2;
3018
+ exports2.Argument = Argument2;
3019
+ exports2.Help = Help2;
3020
+ exports2.CommanderError = CommanderError2;
3021
+ exports2.InvalidArgumentError = InvalidArgumentError2;
3022
+ exports2.InvalidOptionArgumentError = InvalidArgumentError2;
3009
3023
  }
3010
3024
  });
3011
3025
 
@@ -3027,26 +3041,404 @@ var {
3027
3041
  } = import_index.default;
3028
3042
 
3029
3043
  // packages/cli/src/commands/init.ts
3030
- import * as fs from "fs";
3031
- import * as path from "path";
3044
+ var fs2 = __toESM(require("fs"));
3045
+ var path2 = __toESM(require("path"));
3046
+
3047
+ // packages/core/src/idgen.ts
3048
+ var ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
3049
+ function encodeBase36(n) {
3050
+ if (n === 0) return "0";
3051
+ let result = "";
3052
+ while (n > 0) {
3053
+ result = ALPHABET[n % 36] + result;
3054
+ n = Math.floor(n / 36);
3055
+ }
3056
+ return result;
3057
+ }
3058
+ function generateNextId(currentCount) {
3059
+ const next = currentCount + 1;
3060
+ if (next <= 999) {
3061
+ return `D${String(next).padStart(3, "0")}`;
3062
+ }
3063
+ const encoded = encodeBase36(next).padStart(4, "0");
3064
+ return `D${encoded}`;
3065
+ }
3066
+
3067
+ // packages/core/src/parser.ts
3068
+ function splitCsvRow(line) {
3069
+ const fields = [];
3070
+ let current = "";
3071
+ let inQuote = false;
3072
+ let i = 0;
3073
+ while (i < line.length) {
3074
+ const ch = line[i];
3075
+ if (inQuote) {
3076
+ if (ch === "\\") {
3077
+ const next = line[i + 1];
3078
+ if (next === '"') {
3079
+ current += '"';
3080
+ i += 2;
3081
+ continue;
3082
+ } else if (next === "n") {
3083
+ current += "\n";
3084
+ i += 2;
3085
+ continue;
3086
+ } else if (next === "\\") {
3087
+ current += "\\";
3088
+ i += 2;
3089
+ continue;
3090
+ }
3091
+ current += ch;
3092
+ } else if (ch === '"') {
3093
+ inQuote = false;
3094
+ } else {
3095
+ current += ch;
3096
+ }
3097
+ } else {
3098
+ if (ch === '"') {
3099
+ inQuote = true;
3100
+ } else if (ch === ",") {
3101
+ fields.push(current);
3102
+ current = "";
3103
+ } else {
3104
+ current += ch;
3105
+ }
3106
+ }
3107
+ i++;
3108
+ }
3109
+ fields.push(current);
3110
+ return fields;
3111
+ }
3112
+ function parseTableHeader(line) {
3113
+ const match = line.match(/^decisions\[(\d+)\]\{([^}]+)\}:$/);
3114
+ if (!match) return null;
3115
+ return {
3116
+ count: parseInt(match[1], 10),
3117
+ fields: match[2].split(",")
3118
+ };
3119
+ }
3120
+ function isSummaryLine(line) {
3121
+ return line.startsWith("summary{");
3122
+ }
3123
+ function parseDecisionRow(fields, values) {
3124
+ const get = (name) => {
3125
+ const idx = fields.indexOf(name);
3126
+ return idx >= 0 ? values[idx] ?? "" : "";
3127
+ };
3128
+ const impactRaw = get("impact");
3129
+ const validImpacts = ["low", "medium", "high", "critical"];
3130
+ const impact = validImpacts.includes(impactRaw) ? impactRaw : "medium";
3131
+ const tagsRaw = get("tags");
3132
+ const tags = tagsRaw ? tagsRaw.split("|").filter(Boolean) : [];
3133
+ return {
3134
+ id: get("id"),
3135
+ ts: get("ts"),
3136
+ topic: get("topic"),
3137
+ decision: get("decision"),
3138
+ rationale: get("rationale"),
3139
+ impact,
3140
+ tags
3141
+ };
3142
+ }
3143
+ function parseDecisionFile(content) {
3144
+ const lines = content.split("\n");
3145
+ const meta = {
3146
+ project: "unknown",
3147
+ version: "1",
3148
+ created: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
3149
+ updated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
3150
+ };
3151
+ const decisions = [];
3152
+ let tableFields = [];
3153
+ let inTable = false;
3154
+ let inSummary = false;
3155
+ for (const rawLine of lines) {
3156
+ const line = rawLine.trimEnd();
3157
+ if (!line || line.startsWith("#")) continue;
3158
+ if (isSummaryLine(line)) {
3159
+ inTable = false;
3160
+ inSummary = true;
3161
+ continue;
3162
+ }
3163
+ if (inSummary) continue;
3164
+ const tableHeader = parseTableHeader(line);
3165
+ if (tableHeader) {
3166
+ tableFields = tableHeader.fields;
3167
+ inTable = true;
3168
+ continue;
3169
+ }
3170
+ if (inTable && tableFields.length > 0) {
3171
+ const values = splitCsvRow(line);
3172
+ if (values.length >= tableFields.length) {
3173
+ decisions.push(parseDecisionRow(tableFields, values));
3174
+ }
3175
+ continue;
3176
+ }
3177
+ const colonIdx = line.indexOf(":");
3178
+ if (colonIdx > 0) {
3179
+ const key = line.slice(0, colonIdx).trim();
3180
+ const value = line.slice(colonIdx + 1).trim();
3181
+ if (key === "project") meta.project = value;
3182
+ else if (key === "version") meta.version = value;
3183
+ else if (key === "created") meta.created = value;
3184
+ else if (key === "updated") meta.updated = value;
3185
+ }
3186
+ }
3187
+ return { meta, decisions };
3188
+ }
3189
+ function serializeDecisionRow(d) {
3190
+ const escapeField = (s) => {
3191
+ if (s.includes(",") || s.includes('"') || s.includes("\n")) {
3192
+ return '"' + s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n") + '"';
3193
+ }
3194
+ return s;
3195
+ };
3196
+ const tags = d.tags.join("|");
3197
+ return [
3198
+ d.id,
3199
+ d.ts,
3200
+ d.topic,
3201
+ escapeField(d.decision),
3202
+ escapeField(d.rationale),
3203
+ d.impact,
3204
+ tags
3205
+ ].join(",");
3206
+ }
3207
+
3208
+ // packages/core/src/searcher.ts
3209
+ var IMPACT_WEIGHT = {
3210
+ critical: 4,
3211
+ high: 3,
3212
+ medium: 2,
3213
+ low: 1
3214
+ };
3215
+ function computeMatchedFields(d, keywords, tags) {
3216
+ const matched = [];
3217
+ const kws = keywords.map((k) => k.toLowerCase());
3218
+ if (tags.length > 0 && tags.some((t) => d.tags.map((dt) => dt.toLowerCase()).includes(t))) {
3219
+ matched.push("tags");
3220
+ }
3221
+ if (kws.some((k) => d.topic.toLowerCase().includes(k))) matched.push("topic");
3222
+ if (kws.some((k) => d.decision.toLowerCase().includes(k))) matched.push("decision");
3223
+ if (kws.some((k) => d.rationale.toLowerCase().includes(k))) matched.push("rationale");
3224
+ return matched;
3225
+ }
3226
+ function searchDecisions(file, query) {
3227
+ const keywords = (query.keywords ?? []).map((k) => k.toLowerCase());
3228
+ const tags = (query.tags ?? []).map((t) => t.toLowerCase());
3229
+ const impactFilter = query.impact;
3230
+ const limit = query.limit ?? 5;
3231
+ if (keywords.length === 0 && tags.length === 0 && !impactFilter) {
3232
+ return file.decisions.slice(-limit).reverse().map((d) => ({ decision: d, matchedFields: [] }));
3233
+ }
3234
+ const results = [];
3235
+ for (const d of file.decisions) {
3236
+ if (impactFilter && d.impact !== impactFilter) continue;
3237
+ const decisionLower = d.decision.toLowerCase();
3238
+ const rationaleLower = d.rationale.toLowerCase();
3239
+ const topicLower = d.topic.toLowerCase();
3240
+ const tagsLower = d.tags.map((t) => t.toLowerCase());
3241
+ const matchesTag = tags.length === 0 || tags.some((t) => tagsLower.includes(t));
3242
+ const matchesKeyword = keywords.length === 0 || keywords.some(
3243
+ (k) => topicLower.includes(k) || decisionLower.includes(k) || rationaleLower.includes(k) || tagsLower.some((t) => t.includes(k))
3244
+ );
3245
+ if (matchesTag && matchesKeyword) {
3246
+ results.push({
3247
+ decision: d,
3248
+ matchedFields: computeMatchedFields(d, keywords, tags)
3249
+ });
3250
+ }
3251
+ }
3252
+ results.sort((a, b) => {
3253
+ const weightDiff = IMPACT_WEIGHT[b.decision.impact] - IMPACT_WEIGHT[a.decision.impact];
3254
+ if (weightDiff !== 0) return weightDiff;
3255
+ return b.decision.ts.localeCompare(a.decision.ts);
3256
+ });
3257
+ return results.slice(0, limit);
3258
+ }
3259
+
3260
+ // packages/core/src/summary.ts
3261
+ var HIGH_IMPACT = ["high", "critical"];
3262
+ function topTopics(decisions, n = 5) {
3263
+ const counts = /* @__PURE__ */ new Map();
3264
+ for (const d of decisions) {
3265
+ counts.set(d.topic, (counts.get(d.topic) ?? 0) + 1);
3266
+ }
3267
+ return [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, n).map(([topic]) => topic);
3268
+ }
3269
+ function buildContextSummary(file, options = {}) {
3270
+ const { includeRecent = true } = options;
3271
+ const { decisions } = file;
3272
+ const highImpactCount = decisions.filter(
3273
+ (d) => HIGH_IMPACT.includes(d.impact)
3274
+ ).length;
3275
+ const lastUpdated = decisions.length > 0 ? decisions[decisions.length - 1].ts.slice(0, 10) : file.meta.updated;
3276
+ const recentDecisions = includeRecent ? decisions.filter((d) => HIGH_IMPACT.includes(d.impact)).slice(-5).reverse() : [];
3277
+ return {
3278
+ total: decisions.length,
3279
+ highImpactCount,
3280
+ lastUpdated,
3281
+ topTopics: topTopics(decisions),
3282
+ recentDecisions
3283
+ };
3284
+ }
3285
+ function buildSummaryBlock(file) {
3286
+ const summary = buildContextSummary(file, { includeRecent: false });
3287
+ const topics = summary.topTopics.join("|");
3288
+ return `summary{total,high_impact,last_updated,top_topics}:
3289
+ ${summary.total},${summary.highImpactCount},${summary.lastUpdated},${topics}`;
3290
+ }
3291
+ function formatContextSummaryAsToon(file, includeRecent = true) {
3292
+ const summary = buildContextSummary(file, { includeRecent });
3293
+ const topics = summary.topTopics.join("|");
3294
+ let output2 = `summary{total,high_impact,last_updated,top_topics}:
3295
+ `;
3296
+ output2 += `${summary.total},${summary.highImpactCount},${summary.lastUpdated},${topics}`;
3297
+ if (includeRecent && summary.recentDecisions.length > 0) {
3298
+ output2 += `
3299
+
3300
+ recent_high_impact[${summary.recentDecisions.length}]{id,ts,topic,decision,impact}:
3301
+ `;
3302
+ for (const d of summary.recentDecisions) {
3303
+ const decisionField = d.decision.includes(",") ? `"${d.decision}"` : d.decision;
3304
+ output2 += `${d.id},${d.ts},${d.topic},${decisionField},${d.impact}
3305
+ `;
3306
+ }
3307
+ }
3308
+ return output2.trimEnd();
3309
+ }
3310
+
3311
+ // packages/core/src/writer.ts
3312
+ var fs = __toESM(require("fs"), 1);
3313
+ var path = __toESM(require("path"), 1);
3314
+ var os = __toESM(require("os"), 1);
3315
+ function initDecisionFile(filePath, projectName) {
3316
+ if (fs.existsSync(filePath)) {
3317
+ throw new Error(`Dosya zaten var: ${filePath}`);
3318
+ }
3319
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3320
+ const content = `# decision-memory v1
3321
+ project: ${projectName}
3322
+ version: 1
3323
+ created: ${today}
3324
+ updated: ${today}
3325
+
3326
+ decisions[0]{id,ts,topic,decision,rationale,impact,tags}:
3327
+
3328
+ summary{total,high_impact,last_updated,top_topics}:
3329
+ 0,0,${today},
3330
+ `;
3331
+ fs.writeFileSync(filePath, content, "utf-8");
3332
+ }
3333
+ function updateDecisionCount(filePath, newCount) {
3334
+ const content = fs.readFileSync(filePath, "utf-8");
3335
+ const updated = content.replace(
3336
+ /^decisions\[(\d+)\]\{/m,
3337
+ `decisions[${newCount}]{`
3338
+ );
3339
+ const tmpPath = filePath + ".tmp";
3340
+ fs.writeFileSync(tmpPath, updated, "utf-8");
3341
+ fs.renameSync(tmpPath, filePath);
3342
+ }
3343
+ function updateSummaryBlock(filePath) {
3344
+ const content = fs.readFileSync(filePath, "utf-8");
3345
+ const file = parseDecisionFile(content);
3346
+ const summaryBlock = buildSummaryBlock(file);
3347
+ const summaryStart = content.indexOf("\nsummary{");
3348
+ let base;
3349
+ if (summaryStart >= 0) {
3350
+ base = content.slice(0, summaryStart);
3351
+ } else {
3352
+ base = content.trimEnd();
3353
+ }
3354
+ const newContent = base + "\n" + summaryBlock + "\n";
3355
+ const tmpPath = filePath + ".tmp";
3356
+ fs.writeFileSync(tmpPath, newContent, "utf-8");
3357
+ fs.renameSync(tmpPath, filePath);
3358
+ }
3359
+ function appendDecision(filePath, input2) {
3360
+ if (!fs.existsSync(filePath)) {
3361
+ throw new Error(`DECISIONS.toon dosyas\u0131 bulunamad\u0131: ${filePath}
3362
+ \xD6nce 'decision-memory init' komutunu \xE7al\u0131\u015Ft\u0131r\u0131n.`);
3363
+ }
3364
+ const content = fs.readFileSync(filePath, "utf-8");
3365
+ const countMatch = content.match(/^decisions\[(\d+)\]/m);
3366
+ const currentCount = countMatch ? parseInt(countMatch[1], 10) : 0;
3367
+ const id = generateNextId(currentCount);
3368
+ const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z").replace(/:\d{2}Z$/, "Z");
3369
+ const decision = {
3370
+ id,
3371
+ ts,
3372
+ topic: input2.topic,
3373
+ decision: input2.decision,
3374
+ rationale: input2.rationale,
3375
+ impact: input2.impact,
3376
+ tags: input2.tags
3377
+ };
3378
+ const row = serializeDecisionRow(decision);
3379
+ const lines = content.split("\n");
3380
+ let tableEnd = -1;
3381
+ let inTable = false;
3382
+ for (let i = 0; i < lines.length; i++) {
3383
+ if (/^decisions\[\d+\]\{/.test(lines[i])) {
3384
+ inTable = true;
3385
+ tableEnd = i;
3386
+ continue;
3387
+ }
3388
+ if (inTable) {
3389
+ if (lines[i].startsWith("summary{") || lines[i] === "" && tableEnd >= 0) {
3390
+ if (lines[i].startsWith("summary{")) {
3391
+ tableEnd = i - 1;
3392
+ } else {
3393
+ tableEnd = i - 1;
3394
+ }
3395
+ break;
3396
+ }
3397
+ if (lines[i] !== "") {
3398
+ tableEnd = i;
3399
+ }
3400
+ }
3401
+ }
3402
+ lines.splice(tableEnd + 1, 0, row);
3403
+ const newContent = lines.join("\n");
3404
+ const tmpPath = filePath + ".tmp";
3405
+ fs.writeFileSync(tmpPath, newContent, "utf-8");
3406
+ fs.renameSync(tmpPath, filePath);
3407
+ updateDecisionCount(filePath, currentCount + 1);
3408
+ updateSummaryBlock(filePath);
3409
+ return decision;
3410
+ }
3411
+ function resolveDecisionFilePath(cwd) {
3412
+ if (process.env.DECISION_MEMORY_FILE) {
3413
+ return process.env.DECISION_MEMORY_FILE;
3414
+ }
3415
+ const dir = cwd ?? process.cwd();
3416
+ const local = path.join(dir, "DECISIONS.toon");
3417
+ if (fs.existsSync(local)) return local;
3418
+ const globalDir = path.join(os.homedir(), ".decision-memory");
3419
+ fs.mkdirSync(globalDir, { recursive: true });
3420
+ return path.join(globalDir, "global.toon");
3421
+ }
3422
+
3423
+ // packages/cli/src/commands/init.ts
3032
3424
  function initCommand(options) {
3033
3425
  const dir = options.dir ?? process.cwd();
3034
- const filePath = path.join(dir, "DECISIONS.toon");
3035
- if (fs.existsSync(filePath)) {
3426
+ const filePath = path2.join(dir, "DECISIONS.toon");
3427
+ if (fs2.existsSync(filePath)) {
3036
3428
  console.error(`Hata: ${filePath} zaten mevcut.`);
3037
3429
  process.exit(1);
3038
3430
  }
3039
- const projectName = options.project ?? path.basename(dir);
3431
+ const projectName = options.project ?? path2.basename(dir);
3040
3432
  initDecisionFile(filePath, projectName);
3041
- const gitattributes = path.join(dir, ".gitattributes");
3433
+ const gitattributes = path2.join(dir, ".gitattributes");
3042
3434
  const entry = "DECISIONS.toon text eol=lf\n";
3043
- if (fs.existsSync(gitattributes)) {
3044
- const content = fs.readFileSync(gitattributes, "utf-8");
3435
+ if (fs2.existsSync(gitattributes)) {
3436
+ const content = fs2.readFileSync(gitattributes, "utf-8");
3045
3437
  if (!content.includes("DECISIONS.toon")) {
3046
- fs.appendFileSync(gitattributes, entry);
3438
+ fs2.appendFileSync(gitattributes, entry);
3047
3439
  }
3048
3440
  } else {
3049
- fs.writeFileSync(gitattributes, entry);
3441
+ fs2.writeFileSync(gitattributes, entry);
3050
3442
  }
3051
3443
  console.log(`\u2713 ${filePath} olu\u015Fturuldu.`);
3052
3444
  console.log(`\u2713 .gitattributes g\xFCncellendi.`);
@@ -3057,8 +3449,8 @@ Ba\u015Flamak i\xE7in:`);
3057
3449
  }
3058
3450
 
3059
3451
  // packages/cli/src/commands/log.ts
3060
- import * as readline from "readline/promises";
3061
- import { stdin as input, stdout as output } from "process";
3452
+ var readline = __toESM(require("readline/promises"));
3453
+ var import_node_process = require("process");
3062
3454
  async function logCommand(options) {
3063
3455
  if (options.topic && options.decision && options.rationale && options.impact) {
3064
3456
  const inp = buildInput(options);
@@ -3067,7 +3459,7 @@ async function logCommand(options) {
3067
3459
  console.log(`\u2713 Karar kaydedildi: ${entry.id} \u2014 ${entry.decision}`);
3068
3460
  return;
3069
3461
  }
3070
- const rl = readline.createInterface({ input, output });
3462
+ const rl = readline.createInterface({ input: import_node_process.stdin, output: import_node_process.stdout });
3071
3463
  try {
3072
3464
  const topic = options.topic ?? await rl.question("Konu (\xF6rn: auth, database): ");
3073
3465
  const decision = options.decision ?? await rl.question("Al\u0131nan karar: ");
@@ -3108,14 +3500,14 @@ function buildInput(options) {
3108
3500
  }
3109
3501
 
3110
3502
  // packages/cli/src/commands/search.ts
3111
- import * as fs2 from "fs";
3503
+ var fs3 = __toESM(require("fs"));
3112
3504
  function searchCommand(options) {
3113
3505
  const filePath = options.file ?? resolveDecisionFilePath();
3114
- if (!fs2.existsSync(filePath)) {
3506
+ if (!fs3.existsSync(filePath)) {
3115
3507
  console.error(`Hata: ${filePath} bulunamad\u0131. \xD6nce 'decision-memory init' \xE7al\u0131\u015Ft\u0131r\u0131n.`);
3116
3508
  process.exit(1);
3117
3509
  }
3118
- const content = fs2.readFileSync(filePath, "utf-8");
3510
+ const content = fs3.readFileSync(filePath, "utf-8");
3119
3511
  const file = parseDecisionFile(content);
3120
3512
  const keywords = options.keywords ? options.keywords.split(",").map((k) => k.trim()).filter(Boolean) : [];
3121
3513
  const tags = options.tags ? options.tags.split(",").map((t) => t.trim()).filter(Boolean) : [];
@@ -3134,14 +3526,14 @@ function searchCommand(options) {
3134
3526
  }
3135
3527
 
3136
3528
  // packages/cli/src/commands/summary.ts
3137
- import * as fs3 from "fs";
3529
+ var fs4 = __toESM(require("fs"));
3138
3530
  function summaryCommand(options) {
3139
3531
  const filePath = options.file ?? resolveDecisionFilePath();
3140
- if (!fs3.existsSync(filePath)) {
3532
+ if (!fs4.existsSync(filePath)) {
3141
3533
  console.error(`Hata: ${filePath} bulunamad\u0131. \xD6nce 'decision-memory init' \xE7al\u0131\u015Ft\u0131r\u0131n.`);
3142
3534
  process.exit(1);
3143
3535
  }
3144
- const content = fs3.readFileSync(filePath, "utf-8");
3536
+ const content = fs4.readFileSync(filePath, "utf-8");
3145
3537
  const file = parseDecisionFile(content);
3146
3538
  const output2 = formatContextSummaryAsToon(file, !options.noRecent);
3147
3539
  console.log(output2);