@a-company/paradigm 3.20.1 → 3.21.0

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.
@@ -263,22 +263,45 @@ function loadHabitsFresh(rootDir) {
263
263
  for (const seed of SEED_HABITS) {
264
264
  habitsById.set(seed.id, { ...seed });
265
265
  }
266
- const globalHabitsPath = path.join(
267
- process.env.HOME || process.env.USERPROFILE || "~",
268
- ".paradigm",
269
- "habits.yaml"
270
- );
271
- const globalConfig = loadHabitsYaml(globalHabitsPath);
266
+ const home = process.env.HOME || process.env.USERPROFILE || "~";
267
+ const globalConfig = loadHabitsYaml(path.join(home, ".paradigm", "habits.yaml"));
272
268
  if (globalConfig) {
273
269
  mergeHabits(habitsById, globalConfig);
274
270
  }
275
- const projectHabitsPath = path.join(rootDir, ".paradigm", "habits.yaml");
276
- const projectConfig = loadHabitsYaml(projectHabitsPath);
271
+ const globalHabitFiles = loadHabitFiles(path.join(home, ".paradigm", "habits"));
272
+ for (const habit of globalHabitFiles) {
273
+ habitsById.set(habit.id, habit);
274
+ }
275
+ const projectConfig = loadHabitsYaml(path.join(rootDir, ".paradigm", "habits.yaml"));
277
276
  if (projectConfig) {
278
277
  mergeHabits(habitsById, projectConfig);
279
278
  }
279
+ const projectHabitFiles = loadHabitFiles(path.join(rootDir, ".paradigm", "habits"));
280
+ for (const habit of projectHabitFiles) {
281
+ habitsById.set(habit.id, habit);
282
+ }
280
283
  return Array.from(habitsById.values());
281
284
  }
285
+ function loadHabitFiles(dir) {
286
+ if (!fs.existsSync(dir)) return [];
287
+ try {
288
+ const files = fs.readdirSync(dir).filter((f) => f.endsWith(".habit")).sort();
289
+ const habits = [];
290
+ for (const file of files) {
291
+ try {
292
+ const content = fs.readFileSync(path.join(dir, file), "utf8");
293
+ const habit = yaml.load(content);
294
+ if (habit?.id && habit?.name) {
295
+ habits.push(habit);
296
+ }
297
+ } catch {
298
+ }
299
+ }
300
+ return habits;
301
+ } catch {
302
+ return [];
303
+ }
304
+ }
282
305
  function loadHabitsYaml(filePath) {
283
306
  if (!fs.existsSync(filePath)) {
284
307
  return null;
package/dist/index.js CHANGED
@@ -657,48 +657,48 @@ loreCmd.command("timeline").description("Show lore timeline grouped by date with
657
657
  await loreTimelineCommand(options);
658
658
  });
659
659
  loreCmd.option("-p, --port <port>", "Port to run on", "3840").option("--no-open", "Don't open browser automatically").action(async (options) => {
660
- const { loreServeCommand } = await import("./serve-GUJ3L3IG.js");
660
+ const { loreServeCommand } = await import("./serve-DIALBCTU.js");
661
661
  await loreServeCommand(void 0, options);
662
662
  });
663
663
  var habitsCmd = program.command("habits").description("Behavioral habits - practice tracking and compliance");
664
664
  habitsCmd.command("list").alias("ls").description("List all configured habits").option("--trigger <trigger>", "Filter by trigger: preflight, postflight, on-stop, on-commit").option("--category <category>", "Filter by category: discovery, verification, testing, documentation, collaboration, security").option("--json", "Output as JSON").action(async (options) => {
665
- const { habitsListCommand } = await import("./habits-KD4RLIN2.js");
665
+ const { habitsListCommand } = await import("./habits-7BORPC2F.js");
666
666
  await habitsListCommand(options);
667
667
  });
668
668
  habitsCmd.command("status").description("Show practice profile with compliance rates").option("-p, --period <period>", "Time period: 7d, 30d, 90d, all", "30d").option("--json", "Output as JSON").action(async (options) => {
669
- const { habitsStatusCommand } = await import("./habits-KD4RLIN2.js");
669
+ const { habitsStatusCommand } = await import("./habits-7BORPC2F.js");
670
670
  await habitsStatusCommand(options);
671
671
  });
672
672
  habitsCmd.command("init").description("Initialize habits.yaml with seed habits").option("-f, --force", "Overwrite existing file").action(async (options) => {
673
- const { habitsInitCommand } = await import("./habits-KD4RLIN2.js");
673
+ const { habitsInitCommand } = await import("./habits-7BORPC2F.js");
674
674
  await habitsInitCommand(options);
675
675
  });
676
676
  habitsCmd.command("check").description("Evaluate habit compliance for a trigger point").requiredOption("-t, --trigger <trigger>", "Trigger: preflight, postflight, on-stop, on-commit").option("--record", "Record practice events to Sentinel").option("--json", "Output as JSON").option("--files <files>", "Comma-separated files modified (default: git diff)").option("--symbols <symbols>", "Comma-separated symbols touched").action(async (options) => {
677
- const { habitsCheckCommand } = await import("./habits-KD4RLIN2.js");
677
+ const { habitsCheckCommand } = await import("./habits-7BORPC2F.js");
678
678
  await habitsCheckCommand(options);
679
679
  });
680
680
  habitsCmd.command("add").description("Add a custom habit").requiredOption("--id <id>", "Habit ID (kebab-case)").requiredOption("--name <name>", "Human-readable name").requiredOption("--description <desc>", "What this habit enforces").requiredOption("--category <category>", "Category: discovery, verification, testing, documentation, collaboration, security").requiredOption("--trigger <trigger>", "Trigger: preflight, postflight, on-stop, on-commit").option("--severity <severity>", "Severity: advisory, warn, block", "advisory").option("--tools <tools>", "Comma-separated tools to check (for tool-called check type)").option("--check-type <type>", "Check type: tool-called, file-exists, file-modified, lore-recorded, symbols-registered, gates-declared, tests-exist, git-clean", "tool-called").option("--patterns <patterns>", "Comma-separated patterns (for file-exists, file-modified, tests-exist check types)").action(async (options) => {
681
- const { habitsAddCommand } = await import("./habits-KD4RLIN2.js");
681
+ const { habitsAddCommand } = await import("./habits-7BORPC2F.js");
682
682
  await habitsAddCommand({ ...options, checkType: options.checkType });
683
683
  });
684
684
  habitsCmd.command("edit <id>").description("Edit a habit (seed habits: only severity/enabled; custom: all fields)").option("--name <name>", "New name").option("--description <desc>", "New description").option("--category <category>", "New category").option("--trigger <trigger>", "New trigger").option("--severity <severity>", "New severity: advisory, warn, block").option("--enabled <bool>", "Enable or disable: true, false").option("--check-type <type>", "New check type").option("--patterns <patterns>", "Comma-separated patterns").option("--tools <tools>", "Comma-separated tools").action(async (id, options) => {
685
- const { habitsEditCommand } = await import("./habits-KD4RLIN2.js");
685
+ const { habitsEditCommand } = await import("./habits-7BORPC2F.js");
686
686
  await habitsEditCommand(id, { ...options, checkType: options.checkType });
687
687
  });
688
688
  habitsCmd.command("remove <id>").description("Remove a custom habit (seed habits cannot be removed, only disabled)").option("-y, --yes", "Skip confirmation").action(async (id, options) => {
689
- const { habitsRemoveCommand } = await import("./habits-KD4RLIN2.js");
689
+ const { habitsRemoveCommand } = await import("./habits-7BORPC2F.js");
690
690
  await habitsRemoveCommand(id, options);
691
691
  });
692
692
  habitsCmd.command("enable <id>").description("Enable a habit").action(async (id) => {
693
- const { habitsToggleCommand } = await import("./habits-KD4RLIN2.js");
693
+ const { habitsToggleCommand } = await import("./habits-7BORPC2F.js");
694
694
  await habitsToggleCommand(id, "enable");
695
695
  });
696
696
  habitsCmd.command("disable <id>").description("Disable a habit").action(async (id) => {
697
- const { habitsToggleCommand } = await import("./habits-KD4RLIN2.js");
697
+ const { habitsToggleCommand } = await import("./habits-7BORPC2F.js");
698
698
  await habitsToggleCommand(id, "disable");
699
699
  });
700
700
  habitsCmd.action(async () => {
701
- const { habitsListCommand } = await import("./habits-KD4RLIN2.js");
701
+ const { habitsListCommand } = await import("./habits-7BORPC2F.js");
702
702
  await habitsListCommand({});
703
703
  });
704
704
  var sentinelCmd = program.command("sentinel").description("Sentinel \u2014 semantic error monitoring");
@@ -23,7 +23,7 @@ function normalizeEntry(raw) {
23
23
  if (typeof author === "object" && author && !Array.isArray(author)) {
24
24
  const old = author;
25
25
  if (old.type === "agent") {
26
- raw.author = "unknown";
26
+ raw.author = old.id || "unknown";
27
27
  const model = old.model || old.id || "unknown";
28
28
  const lower = model.toLowerCase();
29
29
  let provider = "unknown";
@@ -34,6 +34,14 @@ function normalizeEntry(raw) {
34
34
  raw.author = old.id || "unknown";
35
35
  }
36
36
  delete raw.assistedBy;
37
+ } else if (typeof author !== "string") {
38
+ raw.author = "unknown";
39
+ }
40
+ if (raw.symbols_touched && !Array.isArray(raw.symbols_touched)) {
41
+ raw.symbols_touched = [String(raw.symbols_touched)];
42
+ }
43
+ if (raw.symbols_created && !Array.isArray(raw.symbols_created)) {
44
+ raw.symbols_created = [String(raw.symbols_created)];
37
45
  }
38
46
  return raw;
39
47
  }
@@ -266,7 +274,7 @@ function normalizeEntry2(raw) {
266
274
  if (typeof author === "object" && author && !Array.isArray(author)) {
267
275
  const old = author;
268
276
  if (old.type === "agent") {
269
- raw.author = "unknown";
277
+ raw.author = old.id || "unknown";
270
278
  const model = old.model || old.id || "unknown";
271
279
  const lower = model.toLowerCase();
272
280
  let provider = "unknown";
@@ -277,6 +285,14 @@ function normalizeEntry2(raw) {
277
285
  raw.author = old.id || "unknown";
278
286
  }
279
287
  delete raw.assistedBy;
288
+ } else if (typeof author !== "string") {
289
+ raw.author = "unknown";
290
+ }
291
+ if (raw.symbols_touched && !Array.isArray(raw.symbols_touched)) {
292
+ raw.symbols_touched = [String(raw.symbols_touched)];
293
+ }
294
+ if (raw.symbols_created && !Array.isArray(raw.symbols_created)) {
295
+ raw.symbols_created = [String(raw.symbols_created)];
280
296
  }
281
297
  return raw;
282
298
  }