@a-company/paradigm 3.0.3 → 3.1.2
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/{triage-RM5KNG5V.js → chunk-4LGLU2LO.js} +1035 -663
- package/dist/{chunk-4WR7X3FE.js → chunk-AQZSUGL3.js} +42 -6
- package/dist/{chunk-27OSFWHG.js → chunk-MVXJVRFI.js} +98 -1
- package/dist/{chunk-S65LENNL.js → chunk-VZ7CXFRZ.js} +248 -3
- package/dist/delete-W67IVTLJ.js +45 -0
- package/dist/dist-GPQ4LAY3.js +42 -0
- package/dist/edit-Y7XPYSMK.js +63 -0
- package/dist/habits-FA65W77Y.js +1153 -0
- package/dist/{hooks-7TQIRXXS.js → hooks-YXPQV4SP.js} +1 -1
- package/dist/index.js +84 -31
- package/dist/{list-QMUE7DPK.js → list-R3QWW4SC.js} +3 -1
- package/dist/{lore-server-3TAIUZ3Y.js → lore-server-RQH5REZV.js} +166 -41
- package/dist/mcp.js +1608 -117
- package/dist/{record-5CTCDFUO.js → record-OHQNWOUP.js} +7 -2
- package/dist/{review-QEDNQAIO.js → review-RUHX25A5.js} +1 -1
- package/dist/{sentinel-RSEXIRXM.js → sentinel-WB7GIK4V.js} +1 -1
- package/dist/{serve-WCIRW244.js → serve-H7ZBMODT.js} +1 -1
- package/dist/{server-NXG5N7JE.js → server-MV4HNFVF.js} +1 -1
- package/dist/{shift-NABNKPGL.js → shift-JDBRTHWO.js} +1 -1
- package/dist/{show-S653P3TO.js → show-WTOJXUTN.js} +1 -1
- package/dist/timeline-P7BARFLI.js +110 -0
- package/dist/triage-TBIWJA6R.js +671 -0
- package/dist/university-content/courses/para-401.json +1 -1
- package/dist/university-content/courses/para-501.json +486 -0
- package/dist/university-content/plsat/v3.0.json +233 -0
- package/dist/university-content/reference.json +61 -0
- package/lore-ui/dist/assets/index-BB3P4Cok.js +56 -0
- package/lore-ui/dist/assets/index-DI0Q6NmX.css +1 -0
- package/lore-ui/dist/index.html +2 -2
- package/package.json +1 -1
- package/lore-ui/dist/assets/index-DcT8TINz.js +0 -56
- package/lore-ui/dist/assets/index-DyJhpQ5w.css +0 -1
package/dist/index.js
CHANGED
|
@@ -109,7 +109,7 @@ ${chalk2.magenta("\u2569 ")}${chalk2.cyan("\u2534 \u2534\u2534\u2514\u2500\u253
|
|
|
109
109
|
program.name("paradigm").description("Unified developer tools ecosystem").version(VERSION).addHelpText("before", banner);
|
|
110
110
|
program.command("init").description("Initialize Paradigm in the current project").option("-f, --force", "Overwrite existing files").option("--name <name>", "Project name").option("--ide <ide>", "Target IDE: cursor, copilot, windsurf, claude").option("--migrate", "Output migration prompt for existing IDE files").option("--quick", "Non-interactive mode with smart defaults").option("--dry-run", "Show what would be created without creating").action(initCommand);
|
|
111
111
|
program.command("shift").description("Full project setup in one command (init + team init + scan + sync all IDEs + doctor)").option("-f, --force", "Reinitialize even if already setup").option("-q, --quick", "Skip slow operations (scan)").option("--verify", "Run health checks after setup").option("--ide <ide>", "Target specific IDE instead of all").option("--configure-models", "Force model configuration prompts for team agents").action(async (options) => {
|
|
112
|
-
const { shiftCommand } = await import("./shift-
|
|
112
|
+
const { shiftCommand } = await import("./shift-JDBRTHWO.js");
|
|
113
113
|
await shiftCommand(options);
|
|
114
114
|
});
|
|
115
115
|
program.command("setup [path]").description("Interactive setup wizard for Paradigm").option("-y, --yes", "Accept all defaults (non-interactive)").option("-f, --force", "Overwrite existing .paradigm config").action(async (path2, options) => {
|
|
@@ -470,118 +470,171 @@ historyCmd.option("--json", "Output as JSON").action(async (options) => {
|
|
|
470
470
|
});
|
|
471
471
|
var hooksCmd = program.command("hooks").description("Git hooks for automatic history capture");
|
|
472
472
|
hooksCmd.command("install").description("Install git hooks, Claude Code hooks, and Cursor hooks").option("-f, --force", "Overwrite existing hooks").option("--post-commit", "Only install post-commit hook").option("--pre-push", "Only install pre-push hook").option("--claude-code", "Only install Claude Code hooks (stop + pre-commit)").option("--cursor", "Only install Cursor hooks (.cursor/hooks.json)").action(async (options) => {
|
|
473
|
-
const { hooksInstallCommand } = await import("./hooks-
|
|
473
|
+
const { hooksInstallCommand } = await import("./hooks-YXPQV4SP.js");
|
|
474
474
|
await hooksInstallCommand(options);
|
|
475
475
|
});
|
|
476
476
|
hooksCmd.command("uninstall").description("Remove paradigm hooks (git hooks, or --cursor for Cursor hooks)").option("--cursor", "Remove Cursor hooks instead of git hooks").action(async (options) => {
|
|
477
|
-
const { hooksUninstallCommand } = await import("./hooks-
|
|
477
|
+
const { hooksUninstallCommand } = await import("./hooks-YXPQV4SP.js");
|
|
478
478
|
await hooksUninstallCommand(options);
|
|
479
479
|
});
|
|
480
480
|
hooksCmd.command("status").description("Check git hooks status").action(async () => {
|
|
481
|
-
const { hooksStatusCommand } = await import("./hooks-
|
|
481
|
+
const { hooksStatusCommand } = await import("./hooks-YXPQV4SP.js");
|
|
482
482
|
await hooksStatusCommand();
|
|
483
483
|
});
|
|
484
484
|
hooksCmd.action(async () => {
|
|
485
|
-
const { hooksStatusCommand } = await import("./hooks-
|
|
485
|
+
const { hooksStatusCommand } = await import("./hooks-YXPQV4SP.js");
|
|
486
486
|
await hooksStatusCommand();
|
|
487
487
|
});
|
|
488
488
|
var triageCmd = program.command("triage").description("Semantic error triage - incident management and pattern matching");
|
|
489
489
|
triageCmd.command("list").alias("ls").description("List recent incidents with matched patterns").option("-l, --limit <number>", "Maximum incidents to show", "10").option("-s, --status <status>", "Filter by status: open, investigating, resolved, wont-fix, all").option("--symbol <symbol>", "Filter by symbol (e.g., @checkout, ^auth)").option("-e, --env <environment>", "Filter by environment").option("--search <text>", "Search in error messages").option("--from <date>", "Filter from date (ISO format)").option("--to <date>", "Filter to date (ISO format)").option("--json", "Output as JSON").action(async (options) => {
|
|
490
|
-
const { triageListCommand } = await import("./triage-
|
|
490
|
+
const { triageListCommand } = await import("./triage-TBIWJA6R.js");
|
|
491
491
|
await triageListCommand(options);
|
|
492
492
|
});
|
|
493
493
|
triageCmd.command("show <id>").description("Show full incident details").option("--timeline", "Include flow timeline").option("--json", "Output as JSON").action(async (id, options) => {
|
|
494
|
-
const { triageShowCommand } = await import("./triage-
|
|
494
|
+
const { triageShowCommand } = await import("./triage-TBIWJA6R.js");
|
|
495
495
|
await triageShowCommand(id, options);
|
|
496
496
|
});
|
|
497
497
|
triageCmd.command("resolve <id>").description("Mark incident as resolved").option("-p, --pattern <patternId>", "Pattern that led to resolution").option("-c, --commit <hash>", "Git commit hash of fix").option("--pr <url>", "Pull request URL").option("-n, --notes <text>", "Resolution notes").option("--wont-fix", "Mark as will not fix").action(async (id, options) => {
|
|
498
|
-
const { triageResolveCommand } = await import("./triage-
|
|
498
|
+
const { triageResolveCommand } = await import("./triage-TBIWJA6R.js");
|
|
499
499
|
await triageResolveCommand(id, options);
|
|
500
500
|
});
|
|
501
501
|
triageCmd.command("note <id> <note>").description("Add a note to an incident").action(async (id, note) => {
|
|
502
|
-
const { triageNoteCommand } = await import("./triage-
|
|
502
|
+
const { triageNoteCommand } = await import("./triage-TBIWJA6R.js");
|
|
503
503
|
await triageNoteCommand(id, note);
|
|
504
504
|
});
|
|
505
505
|
triageCmd.command("link <id1> <id2>").description("Link two related incidents").action(async (id1, id2) => {
|
|
506
|
-
const { triageLinkCommand } = await import("./triage-
|
|
506
|
+
const { triageLinkCommand } = await import("./triage-TBIWJA6R.js");
|
|
507
507
|
await triageLinkCommand(id1, id2);
|
|
508
508
|
});
|
|
509
509
|
var triagePatternsCmd = triageCmd.command("patterns").description("Manage failure patterns");
|
|
510
510
|
triagePatternsCmd.command("list").alias("ls").description("List all patterns").option("--source <source>", "Filter by source: manual, suggested, imported, community").option("--min-confidence <score>", "Minimum confidence score").option("--json", "Output as JSON").action(async (options) => {
|
|
511
|
-
const { triagePatternsListCommand } = await import("./triage-
|
|
511
|
+
const { triagePatternsListCommand } = await import("./triage-TBIWJA6R.js");
|
|
512
512
|
await triagePatternsListCommand(options);
|
|
513
513
|
});
|
|
514
514
|
triagePatternsCmd.command("show <id>").description("Show pattern details").option("--json", "Output as JSON").action(async (id, options) => {
|
|
515
|
-
const { triagePatternsShowCommand } = await import("./triage-
|
|
515
|
+
const { triagePatternsShowCommand } = await import("./triage-TBIWJA6R.js");
|
|
516
516
|
await triagePatternsShowCommand(id, options);
|
|
517
517
|
});
|
|
518
518
|
triagePatternsCmd.command("add").description("Create a new pattern").requiredOption("--id <id>", "Pattern ID (kebab-case)").requiredOption("--name <name>", "Human-readable name").option("--description <text>", "Pattern description").option("--symbols <pairs>", 'Symbol criteria (e.g., "feature:@checkout,gate:^auth")').option("--error-contains <keywords>", "Error keywords (comma-separated)").option("--missing-signals <signals>", "Expected missing signals (comma-separated)").option("--strategy <strategy>", "Resolution strategy: retry, fallback, fix-data, fix-code, ignore, escalate", "fix-code").option("--priority <priority>", "Priority: low, medium, high, critical", "medium").option("--code-hint <text>", "Code hint for resolution").option("--tags <tags>", "Tags (comma-separated)").option("--from-incident <id>", "Generate suggestion from incident").action(async (options) => {
|
|
519
|
-
const { triagePatternsAddCommand } = await import("./triage-
|
|
519
|
+
const { triagePatternsAddCommand } = await import("./triage-TBIWJA6R.js");
|
|
520
520
|
await triagePatternsAddCommand(options);
|
|
521
521
|
});
|
|
522
522
|
triagePatternsCmd.command("delete <id>").alias("rm").description("Delete a pattern").action(async (id) => {
|
|
523
|
-
const { triagePatternsDeleteCommand } = await import("./triage-
|
|
523
|
+
const { triagePatternsDeleteCommand } = await import("./triage-TBIWJA6R.js");
|
|
524
524
|
await triagePatternsDeleteCommand(id);
|
|
525
525
|
});
|
|
526
526
|
triagePatternsCmd.command("test <id>").description("Test pattern against historical incidents").option("-l, --limit <number>", "Max incidents to test against", "100").option("--json", "Output as JSON").action(async (id, options) => {
|
|
527
|
-
const { triagePatternsTestCommand } = await import("./triage-
|
|
527
|
+
const { triagePatternsTestCommand } = await import("./triage-TBIWJA6R.js");
|
|
528
528
|
await triagePatternsTestCommand(id, options);
|
|
529
529
|
});
|
|
530
530
|
triagePatternsCmd.command("seed").description("Load built-in seed patterns").action(async () => {
|
|
531
|
-
const { triagePatternsSeedCommand } = await import("./triage-
|
|
531
|
+
const { triagePatternsSeedCommand } = await import("./triage-TBIWJA6R.js");
|
|
532
532
|
await triagePatternsSeedCommand();
|
|
533
533
|
});
|
|
534
534
|
triagePatternsCmd.action(async () => {
|
|
535
|
-
const { triagePatternsListCommand } = await import("./triage-
|
|
535
|
+
const { triagePatternsListCommand } = await import("./triage-TBIWJA6R.js");
|
|
536
536
|
await triagePatternsListCommand({});
|
|
537
537
|
});
|
|
538
538
|
triageCmd.command("export <type>").description("Export patterns or full backup (type: patterns, backup)").option("-o, --output <path>", "Output file path").option("--include-private", "Include private patterns").action(async (type, options) => {
|
|
539
|
-
const { triageExportCommand } = await import("./triage-
|
|
539
|
+
const { triageExportCommand } = await import("./triage-TBIWJA6R.js");
|
|
540
540
|
await triageExportCommand(type, options);
|
|
541
541
|
});
|
|
542
542
|
triageCmd.command("import <file>").description("Import patterns from JSON file").option("--overwrite", "Overwrite existing patterns").action(async (file, options) => {
|
|
543
|
-
const { triageImportCommand } = await import("./triage-
|
|
543
|
+
const { triageImportCommand } = await import("./triage-TBIWJA6R.js");
|
|
544
544
|
await triageImportCommand(file, options);
|
|
545
545
|
});
|
|
546
546
|
triageCmd.command("restore <file>").description("Restore from full backup").action(async (file) => {
|
|
547
|
-
const { triageRestoreCommand } = await import("./triage-
|
|
547
|
+
const { triageRestoreCommand } = await import("./triage-TBIWJA6R.js");
|
|
548
548
|
await triageRestoreCommand(file);
|
|
549
549
|
});
|
|
550
550
|
triageCmd.command("stats").description("Show statistics dashboard").option("-p, --period <period>", "Time period: 1d, 7d, 30d, 90d", "7d").option("--symbol <symbol>", "Show health for specific symbol").option("--json", "Output as JSON").action(async (options) => {
|
|
551
|
-
const { triageStatsCommand } = await import("./triage-
|
|
551
|
+
const { triageStatsCommand } = await import("./triage-TBIWJA6R.js");
|
|
552
552
|
await triageStatsCommand(options);
|
|
553
553
|
});
|
|
554
554
|
triageCmd.command("record").description("Manually record an incident").requiredOption("--error <message>", "Error message").requiredOption("-e, --env <environment>", "Environment").option("--feature <symbol>", "Feature symbol (@...)").option("--component <symbol>", "Component symbol (#...)").option("--flow <symbol>", "Flow symbol ($...)").option("--gate <symbol>", "Gate symbol (^...)").option("--signal <symbol>", "Signal symbol (!...)").option("--state <symbol>", "State symbol (%...)").option("--integration <symbol>", "Integration symbol (&...)").option("--service <name>", "Service name").option("--version <version>", "App version").option("--stack <trace>", "Stack trace").option("--json", "Output as JSON").action(async (options) => {
|
|
555
|
-
const { triageRecordCommand } = await import("./triage-
|
|
555
|
+
const { triageRecordCommand } = await import("./triage-TBIWJA6R.js");
|
|
556
556
|
await triageRecordCommand(options);
|
|
557
557
|
});
|
|
558
558
|
triageCmd.option("-l, --limit <number>", "Maximum incidents to show", "10").option("-s, --status <status>", "Filter by status").option("--json", "Output as JSON").action(async (options) => {
|
|
559
|
-
const { triageListCommand } = await import("./triage-
|
|
559
|
+
const { triageListCommand } = await import("./triage-TBIWJA6R.js");
|
|
560
560
|
await triageListCommand(options);
|
|
561
561
|
});
|
|
562
562
|
var loreCmd = program.command("lore").description("Project lore - timeline of everything that happened to this project");
|
|
563
|
-
loreCmd.command("list").alias("ls").description("List recent lore entries").option("--author <author>", "Filter by author").option("--type <type>", "Filter by type: agent-session, human-note, decision, review, incident, milestone").option("--symbol <symbol>", "Filter by symbol").option("--tags <tags>", "Filter by tags (comma-separated)").option("-l, --limit <number>", "Number of entries", "20").option("--json", "Output as JSON").action(async (options) => {
|
|
564
|
-
const { loreListCommand } = await import("./list-
|
|
563
|
+
loreCmd.command("list").alias("ls").description("List recent lore entries").option("--author <author>", "Filter by author").option("--type <type>", "Filter by type: agent-session, human-note, decision, review, incident, milestone").option("--symbol <symbol>", "Filter by symbol").option("--tags <tags>", "Filter by tags (comma-separated)").option("--from <date>", "Filter from date (ISO format, e.g., 2026-02-20)").option("--to <date>", "Filter to date (ISO format)").option("-l, --limit <number>", "Number of entries", "20").option("--json", "Output as JSON").action(async (options) => {
|
|
564
|
+
const { loreListCommand } = await import("./list-R3QWW4SC.js");
|
|
565
565
|
await loreListCommand(options);
|
|
566
566
|
});
|
|
567
567
|
loreCmd.command("show <id>").description("Show full detail for a lore entry").option("--json", "Output as JSON").action(async (id, options) => {
|
|
568
|
-
const { loreShowCommand } = await import("./show-
|
|
568
|
+
const { loreShowCommand } = await import("./show-WTOJXUTN.js");
|
|
569
569
|
await loreShowCommand(id, options);
|
|
570
570
|
});
|
|
571
|
-
loreCmd.command("record").description("Record a new lore entry (human note, milestone, etc.)").option("--type <type>", "Entry type: human-note, decision, milestone", "human-note").option("--author <author>", "Author name").option("--title <title>", "Entry title").option("--summary <summary>", "Entry summary").option("--symbols <symbols>", "Comma-separated symbols").option("--tags <tags>", "Comma-separated tags").action(async (options) => {
|
|
572
|
-
const { loreRecordCommand } = await import("./record-
|
|
571
|
+
loreCmd.command("record").description("Record a new lore entry (human note, milestone, etc.)").option("--type <type>", "Entry type: human-note, decision, milestone", "human-note").option("--author <author>", "Author name").option("--title <title>", "Entry title").option("--summary <summary>", "Entry summary").option("--symbols <symbols>", "Comma-separated symbols").option("--tags <tags>", "Comma-separated tags").option("--files-modified <files>", "Comma-separated files modified").option("--files-created <files>", "Comma-separated files created").option("--commit <hash>", "Git commit hash").option("--learnings <items>", "Comma-separated learnings").option("--duration <minutes>", "Duration in minutes").action(async (options) => {
|
|
572
|
+
const { loreRecordCommand } = await import("./record-OHQNWOUP.js");
|
|
573
573
|
await loreRecordCommand(options);
|
|
574
574
|
});
|
|
575
575
|
loreCmd.command("review <id>").description("Add a review to a lore entry").option("--reviewer <name>", "Reviewer name").option("--completeness <n>", "Completeness score (1-5)", "3").option("--quality <n>", "Quality score (1-5)", "3").option("--notes <text>", "Review notes").action(async (id, options) => {
|
|
576
|
-
const { loreReviewCommand } = await import("./review-
|
|
576
|
+
const { loreReviewCommand } = await import("./review-RUHX25A5.js");
|
|
577
577
|
await loreReviewCommand(id, options);
|
|
578
578
|
});
|
|
579
|
+
loreCmd.command("edit <id>").description("Edit an existing lore entry").option("--title <title>", "New title").option("--summary <summary>", "New summary").option("--type <type>", "New type: agent-session, human-note, decision, review, incident, milestone").option("--symbols <symbols>", "Comma-separated symbols").option("--tags <tags>", "Comma-separated tags").option("--learnings <items>", "Comma-separated learnings").action(async (id, options) => {
|
|
580
|
+
const { loreEditCommand } = await import("./edit-Y7XPYSMK.js");
|
|
581
|
+
await loreEditCommand(id, options);
|
|
582
|
+
});
|
|
583
|
+
loreCmd.command("delete <id>").description("Delete a lore entry").option("-y, --yes", "Skip confirmation").action(async (id, options) => {
|
|
584
|
+
const { loreDeleteCommand } = await import("./delete-W67IVTLJ.js");
|
|
585
|
+
await loreDeleteCommand(id, options);
|
|
586
|
+
});
|
|
587
|
+
loreCmd.command("timeline").description("Show lore timeline grouped by date with hot symbols and authors").option("-l, --limit <number>", "Number of entries", "20").option("--json", "Output as JSON").action(async (options) => {
|
|
588
|
+
const { loreTimelineCommand } = await import("./timeline-P7BARFLI.js");
|
|
589
|
+
await loreTimelineCommand(options);
|
|
590
|
+
});
|
|
579
591
|
loreCmd.option("-p, --port <port>", "Port to run on", "3840").option("--no-open", "Don't open browser automatically").action(async (options) => {
|
|
580
|
-
const { loreServeCommand } = await import("./serve-
|
|
592
|
+
const { loreServeCommand } = await import("./serve-H7ZBMODT.js");
|
|
581
593
|
await loreServeCommand(void 0, options);
|
|
582
594
|
});
|
|
595
|
+
var habitsCmd = program.command("habits").description("Behavioral habits - practice tracking and compliance");
|
|
596
|
+
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) => {
|
|
597
|
+
const { habitsListCommand } = await import("./habits-FA65W77Y.js");
|
|
598
|
+
await habitsListCommand(options);
|
|
599
|
+
});
|
|
600
|
+
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) => {
|
|
601
|
+
const { habitsStatusCommand } = await import("./habits-FA65W77Y.js");
|
|
602
|
+
await habitsStatusCommand(options);
|
|
603
|
+
});
|
|
604
|
+
habitsCmd.command("init").description("Initialize habits.yaml with seed habits").option("-f, --force", "Overwrite existing file").action(async (options) => {
|
|
605
|
+
const { habitsInitCommand } = await import("./habits-FA65W77Y.js");
|
|
606
|
+
await habitsInitCommand(options);
|
|
607
|
+
});
|
|
608
|
+
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) => {
|
|
609
|
+
const { habitsCheckCommand } = await import("./habits-FA65W77Y.js");
|
|
610
|
+
await habitsCheckCommand(options);
|
|
611
|
+
});
|
|
612
|
+
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) => {
|
|
613
|
+
const { habitsAddCommand } = await import("./habits-FA65W77Y.js");
|
|
614
|
+
await habitsAddCommand({ ...options, checkType: options.checkType });
|
|
615
|
+
});
|
|
616
|
+
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) => {
|
|
617
|
+
const { habitsEditCommand } = await import("./habits-FA65W77Y.js");
|
|
618
|
+
await habitsEditCommand(id, { ...options, checkType: options.checkType });
|
|
619
|
+
});
|
|
620
|
+
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) => {
|
|
621
|
+
const { habitsRemoveCommand } = await import("./habits-FA65W77Y.js");
|
|
622
|
+
await habitsRemoveCommand(id, options);
|
|
623
|
+
});
|
|
624
|
+
habitsCmd.command("enable <id>").description("Enable a habit").action(async (id) => {
|
|
625
|
+
const { habitsToggleCommand } = await import("./habits-FA65W77Y.js");
|
|
626
|
+
await habitsToggleCommand(id, "enable");
|
|
627
|
+
});
|
|
628
|
+
habitsCmd.command("disable <id>").description("Disable a habit").action(async (id) => {
|
|
629
|
+
const { habitsToggleCommand } = await import("./habits-FA65W77Y.js");
|
|
630
|
+
await habitsToggleCommand(id, "disable");
|
|
631
|
+
});
|
|
632
|
+
habitsCmd.action(async () => {
|
|
633
|
+
const { habitsListCommand } = await import("./habits-FA65W77Y.js");
|
|
634
|
+
await habitsListCommand({});
|
|
635
|
+
});
|
|
583
636
|
program.command("sentinel [path]").description("Launch the Sentinel UI - unified codebase intelligence visualizer").option("-p, --port <port>", "Port to run on", "3838").option("--no-open", "Don't open browser automatically").action(async (path2, options) => {
|
|
584
|
-
const { sentinelCommand } = await import("./sentinel-
|
|
637
|
+
const { sentinelCommand } = await import("./sentinel-WB7GIK4V.js");
|
|
585
638
|
await sentinelCommand(path2, options);
|
|
586
639
|
});
|
|
587
640
|
program.command("university").description("Launch Paradigm University - interactive learning platform & PLSAT certification").option("-p, --port <port>", "Port to run on", "3839").option("--no-open", "Don't open browser automatically").action(async (options) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
loadLoreEntries
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-MVXJVRFI.js";
|
|
5
5
|
import "./chunk-MO4EEYFW.js";
|
|
6
6
|
|
|
7
7
|
// src/commands/lore/list.ts
|
|
@@ -13,6 +13,8 @@ async function loreListCommand(options) {
|
|
|
13
13
|
if (options.type) filter.type = options.type;
|
|
14
14
|
if (options.symbol) filter.symbol = options.symbol;
|
|
15
15
|
if (options.tags) filter.tags = options.tags.split(",");
|
|
16
|
+
if (options.from) filter.dateFrom = options.from;
|
|
17
|
+
if (options.to) filter.dateTo = options.to;
|
|
16
18
|
filter.limit = parseInt(options.limit || "20", 10);
|
|
17
19
|
const entries = await loadLoreEntries(rootDir, filter);
|
|
18
20
|
if (options.json) {
|
|
@@ -3,8 +3,8 @@ import "./chunk-MO4EEYFW.js";
|
|
|
3
3
|
|
|
4
4
|
// src/lore-server/index.ts
|
|
5
5
|
import express from "express";
|
|
6
|
-
import * as
|
|
7
|
-
import * as
|
|
6
|
+
import * as path4 from "path";
|
|
7
|
+
import * as fs4 from "fs";
|
|
8
8
|
import { fileURLToPath } from "url";
|
|
9
9
|
import chalk from "chalk";
|
|
10
10
|
|
|
@@ -79,39 +79,6 @@ function createLoreRouter(projectDir) {
|
|
|
79
79
|
entries = entries.slice(off, off + lim);
|
|
80
80
|
res.json({ total, offset: off, limit: lim, entries });
|
|
81
81
|
});
|
|
82
|
-
router.get("/:id", (req, res) => {
|
|
83
|
-
const entries = loadAllEntries(projectDir);
|
|
84
|
-
const entry = entries.find((e) => e.id === req.params.id);
|
|
85
|
-
if (!entry) {
|
|
86
|
-
res.status(404).json({ error: "Entry not found" });
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
res.json(entry);
|
|
90
|
-
});
|
|
91
|
-
router.put("/:id/review", (req, res) => {
|
|
92
|
-
const entryId = req.params.id;
|
|
93
|
-
const entries = loadAllEntries(projectDir);
|
|
94
|
-
const entry = entries.find((e) => e.id === entryId);
|
|
95
|
-
if (!entry) {
|
|
96
|
-
res.status(404).json({ error: "Entry not found" });
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
const dateStr = entry.timestamp.slice(0, 10);
|
|
100
|
-
const entryPath = path.join(projectDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
|
|
101
|
-
if (!fs.existsSync(entryPath)) {
|
|
102
|
-
res.status(404).json({ error: "Entry file not found" });
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
entry.review = {
|
|
106
|
-
reviewer: req.body.reviewer || "anonymous",
|
|
107
|
-
completeness: req.body.completeness || 3,
|
|
108
|
-
quality: req.body.quality || 3,
|
|
109
|
-
notes: req.body.notes,
|
|
110
|
-
reviewed_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
111
|
-
};
|
|
112
|
-
fs.writeFileSync(entryPath, yaml.dump(entry, { lineWidth: -1, noRefs: true }));
|
|
113
|
-
res.json({ success: true, entry });
|
|
114
|
-
});
|
|
115
82
|
router.get("/timeline", (_req, res) => {
|
|
116
83
|
const timelinePath = path.join(projectDir, LORE_DIR, "timeline.yaml");
|
|
117
84
|
if (!fs.existsSync(timelinePath)) {
|
|
@@ -157,6 +124,39 @@ function createLoreRouter(projectDir) {
|
|
|
157
124
|
const authors = Object.entries(authorMap).map(([id, info]) => ({ id, ...info })).sort((a, b) => b.count - a.count);
|
|
158
125
|
res.json({ authors });
|
|
159
126
|
});
|
|
127
|
+
router.get("/:id", (req, res) => {
|
|
128
|
+
const entries = loadAllEntries(projectDir);
|
|
129
|
+
const entry = entries.find((e) => e.id === req.params.id);
|
|
130
|
+
if (!entry) {
|
|
131
|
+
res.status(404).json({ error: "Entry not found" });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
res.json(entry);
|
|
135
|
+
});
|
|
136
|
+
router.put("/:id/review", (req, res) => {
|
|
137
|
+
const entryId = req.params.id;
|
|
138
|
+
const entries = loadAllEntries(projectDir);
|
|
139
|
+
const entry = entries.find((e) => e.id === entryId);
|
|
140
|
+
if (!entry) {
|
|
141
|
+
res.status(404).json({ error: "Entry not found" });
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const dateStr = entry.timestamp.slice(0, 10);
|
|
145
|
+
const entryPath = path.join(projectDir, LORE_DIR, ENTRIES_DIR, dateStr, `${entryId}.yaml`);
|
|
146
|
+
if (!fs.existsSync(entryPath)) {
|
|
147
|
+
res.status(404).json({ error: "Entry file not found" });
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
entry.review = {
|
|
151
|
+
reviewer: req.body.reviewer || "anonymous",
|
|
152
|
+
completeness: req.body.completeness || 3,
|
|
153
|
+
quality: req.body.quality || 3,
|
|
154
|
+
notes: req.body.notes,
|
|
155
|
+
reviewed_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
156
|
+
};
|
|
157
|
+
fs.writeFileSync(entryPath, yaml.dump(entry, { lineWidth: -1, noRefs: true }));
|
|
158
|
+
res.json({ success: true, entry });
|
|
159
|
+
});
|
|
160
160
|
return router;
|
|
161
161
|
}
|
|
162
162
|
|
|
@@ -186,9 +186,133 @@ function createInfoRouter(projectDir) {
|
|
|
186
186
|
return router;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
// src/lore-server/routes/sessions.ts
|
|
190
|
+
import { Router as Router3 } from "express";
|
|
191
|
+
import * as fs3 from "fs";
|
|
192
|
+
import * as path3 from "path";
|
|
193
|
+
import * as yaml3 from "js-yaml";
|
|
194
|
+
import * as os from "os";
|
|
195
|
+
var LORE_DIR2 = ".paradigm/lore";
|
|
196
|
+
var ENTRIES_DIR2 = "entries";
|
|
197
|
+
var SESSION_GAP_MS = 4 * 60 * 60 * 1e3;
|
|
198
|
+
function loadAllEntries2(projectDir) {
|
|
199
|
+
const entriesPath = path3.join(projectDir, LORE_DIR2, ENTRIES_DIR2);
|
|
200
|
+
if (!fs3.existsSync(entriesPath)) {
|
|
201
|
+
return [];
|
|
202
|
+
}
|
|
203
|
+
const entries = [];
|
|
204
|
+
const dateDirs = fs3.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d)).sort().reverse();
|
|
205
|
+
for (const dateDir of dateDirs) {
|
|
206
|
+
const dirPath = path3.join(entriesPath, dateDir);
|
|
207
|
+
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".yaml")).sort();
|
|
208
|
+
for (const file of files) {
|
|
209
|
+
try {
|
|
210
|
+
const content = fs3.readFileSync(path3.join(dirPath, file), "utf8");
|
|
211
|
+
const entry = yaml3.load(content);
|
|
212
|
+
entries.push(entry);
|
|
213
|
+
} catch {
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return entries;
|
|
218
|
+
}
|
|
219
|
+
function loadBreadcrumbs(projectDir) {
|
|
220
|
+
const localPath = path3.join(projectDir, ".paradigm", "session-breadcrumbs.json");
|
|
221
|
+
if (fs3.existsSync(localPath)) {
|
|
222
|
+
try {
|
|
223
|
+
return JSON.parse(fs3.readFileSync(localPath, "utf8"));
|
|
224
|
+
} catch {
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const globalDir = path3.join(os.homedir(), ".paradigm", "sessions");
|
|
228
|
+
if (fs3.existsSync(globalDir)) {
|
|
229
|
+
try {
|
|
230
|
+
const dirs = fs3.readdirSync(globalDir).sort().reverse();
|
|
231
|
+
for (const dir of dirs.slice(0, 5)) {
|
|
232
|
+
const bcPath = path3.join(globalDir, dir, "breadcrumbs.json");
|
|
233
|
+
if (fs3.existsSync(bcPath)) {
|
|
234
|
+
return JSON.parse(fs3.readFileSync(bcPath, "utf8"));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
} catch {
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return [];
|
|
241
|
+
}
|
|
242
|
+
function deriveSessionsFromEntries(entries, breadcrumbs) {
|
|
243
|
+
if (entries.length === 0) return [];
|
|
244
|
+
const sorted = [...entries].sort(
|
|
245
|
+
(a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
|
|
246
|
+
);
|
|
247
|
+
const sessions = [];
|
|
248
|
+
let currentGroup = [sorted[0]];
|
|
249
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
250
|
+
const prev = sorted[i - 1];
|
|
251
|
+
const curr = sorted[i];
|
|
252
|
+
const gap = new Date(curr.timestamp).getTime() - new Date(prev.timestamp).getTime();
|
|
253
|
+
const sameAuthor = curr.author.id === prev.author.id;
|
|
254
|
+
if (gap <= SESSION_GAP_MS && sameAuthor) {
|
|
255
|
+
currentGroup.push(curr);
|
|
256
|
+
} else {
|
|
257
|
+
sessions.push(groupToSession(currentGroup));
|
|
258
|
+
currentGroup = [curr];
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
sessions.push(groupToSession(currentGroup));
|
|
262
|
+
if (breadcrumbs.length > 0 && sessions.length > 0) {
|
|
263
|
+
sessions[sessions.length - 1].breadcrumbs = breadcrumbs;
|
|
264
|
+
}
|
|
265
|
+
sessions.sort((a, b) => new Date(b.startTime).getTime() - new Date(a.startTime).getTime());
|
|
266
|
+
return sessions;
|
|
267
|
+
}
|
|
268
|
+
function groupToSession(group) {
|
|
269
|
+
const allSymbols = /* @__PURE__ */ new Set();
|
|
270
|
+
for (const entry of group) {
|
|
271
|
+
for (const sym of entry.symbols_touched) allSymbols.add(sym);
|
|
272
|
+
if (entry.symbols_created) {
|
|
273
|
+
for (const sym of entry.symbols_created) allSymbols.add(sym);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
const startTime = group[0].timestamp;
|
|
277
|
+
const endTime = group[group.length - 1].timestamp;
|
|
278
|
+
const date = startTime.slice(0, 10);
|
|
279
|
+
return {
|
|
280
|
+
id: `session-${date}-${group[0].author.id}-${group[0].id.slice(0, 8)}`,
|
|
281
|
+
date,
|
|
282
|
+
author: { type: group[0].author.type, id: group[0].author.id },
|
|
283
|
+
startTime,
|
|
284
|
+
endTime,
|
|
285
|
+
entryCount: group.length,
|
|
286
|
+
symbolsTouched: Array.from(allSymbols),
|
|
287
|
+
entryIds: group.map((e) => e.id)
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function createSessionsRouter(projectDir) {
|
|
291
|
+
const router = Router3();
|
|
292
|
+
router.get("/", (_req, res) => {
|
|
293
|
+
const entries = loadAllEntries2(projectDir);
|
|
294
|
+
const breadcrumbs = loadBreadcrumbs(projectDir);
|
|
295
|
+
const sessions = deriveSessionsFromEntries(entries, breadcrumbs);
|
|
296
|
+
res.json({ sessions });
|
|
297
|
+
});
|
|
298
|
+
router.get("/:id", (req, res) => {
|
|
299
|
+
const entries = loadAllEntries2(projectDir);
|
|
300
|
+
const breadcrumbs = loadBreadcrumbs(projectDir);
|
|
301
|
+
const sessions = deriveSessionsFromEntries(entries, breadcrumbs);
|
|
302
|
+
const session = sessions.find((s) => s.id === req.params.id);
|
|
303
|
+
if (!session) {
|
|
304
|
+
res.status(404).json({ error: "Session not found" });
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const sessionEntries = entries.filter((e) => session.entryIds.includes(e.id));
|
|
308
|
+
res.json({ ...session, entries: sessionEntries });
|
|
309
|
+
});
|
|
310
|
+
return router;
|
|
311
|
+
}
|
|
312
|
+
|
|
189
313
|
// src/lore-server/index.ts
|
|
190
314
|
var __filename = fileURLToPath(import.meta.url);
|
|
191
|
-
var __dirname =
|
|
315
|
+
var __dirname = path4.dirname(__filename);
|
|
192
316
|
var log = {
|
|
193
317
|
component(name) {
|
|
194
318
|
const symbol = chalk.magenta(`#${name}`);
|
|
@@ -227,18 +351,19 @@ function createLoreApp(options) {
|
|
|
227
351
|
});
|
|
228
352
|
app.use("/api/lore", createLoreRouter(options.projectDir));
|
|
229
353
|
app.use("/api/info", createInfoRouter(options.projectDir));
|
|
354
|
+
app.use("/api/sessions", createSessionsRouter(options.projectDir));
|
|
230
355
|
app.get("/api/health", (_req, res) => {
|
|
231
356
|
res.json({ status: "ok", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
232
357
|
});
|
|
233
|
-
let uiDistPath =
|
|
234
|
-
if (!
|
|
235
|
-
uiDistPath =
|
|
358
|
+
let uiDistPath = path4.join(__dirname, "..", "lore-ui", "dist");
|
|
359
|
+
if (!fs4.existsSync(uiDistPath)) {
|
|
360
|
+
uiDistPath = path4.join(__dirname, "..", "..", "lore-ui", "dist");
|
|
236
361
|
}
|
|
237
|
-
if (
|
|
362
|
+
if (fs4.existsSync(uiDistPath)) {
|
|
238
363
|
app.use(express.static(uiDistPath));
|
|
239
364
|
app.get("{*path}", (req, res) => {
|
|
240
365
|
if (!req.path.startsWith("/api")) {
|
|
241
|
-
res.sendFile(
|
|
366
|
+
res.sendFile(path4.join(uiDistPath, "index.html"));
|
|
242
367
|
}
|
|
243
368
|
});
|
|
244
369
|
} else {
|