@driftless-sh/cli 0.1.31 → 0.1.33

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/index.js CHANGED
@@ -6,16 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __esm = (fn, res) => function __init() {
10
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
- };
12
9
  var __commonJS = (cb, mod) => function __require() {
13
10
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
14
11
  };
15
- var __export = (target, all) => {
16
- for (var name in all)
17
- __defProp(target, name, { get: all[name], enumerable: true });
18
- };
19
12
  var __copyProps = (to, from, except, desc) => {
20
13
  if (from && typeof from === "object" || typeof from === "function") {
21
14
  for (let key of __getOwnPropNames(from))
@@ -33,101 +26,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
33
26
  mod
34
27
  ));
35
28
 
36
- // src/git.ts
37
- var git_exports = {};
38
- __export(git_exports, {
39
- getAuthorName: () => getAuthorName,
40
- getChangedFilesFromDiff: () => getChangedFilesFromDiff,
41
- getChangedFilesList: () => getChangedFilesList,
42
- getGitRemote: () => getGitRemote,
43
- getLastCommitHash: () => getLastCommitHash,
44
- getStagedDiff: () => getStagedDiff,
45
- getUncommittedDiff: () => getUncommittedDiff,
46
- isGitRepo: () => isGitRepo
47
- });
48
- function getGitRemote() {
49
- try {
50
- const url = (0, import_node_child_process.execSync)("git config --get remote.origin.url", {
51
- encoding: "utf8",
52
- cwd: process.cwd()
53
- }).trim();
54
- const match = url.match(/[:/]([^/]+)\/([^/]+?)(?:\.git)?$/);
55
- if (match) {
56
- return { org: match[1], repo: match[2] };
57
- }
58
- return null;
59
- } catch {
60
- return null;
61
- }
62
- }
63
- function isGitRepo() {
64
- return (0, import_node_fs2.existsSync)((0, import_node_path2.resolve)(process.cwd(), ".git"));
65
- }
66
- function getUncommittedDiff() {
67
- try {
68
- return (0, import_node_child_process.execSync)("git diff", { encoding: "utf8", cwd: process.cwd() }).trim();
69
- } catch {
70
- return "";
71
- }
72
- }
73
- function getStagedDiff() {
74
- try {
75
- return (0, import_node_child_process.execSync)("git diff --staged", { encoding: "utf8", cwd: process.cwd() }).trim();
76
- } catch {
77
- return "";
78
- }
79
- }
80
- function getLastCommitHash() {
81
- try {
82
- return (0, import_node_child_process.execSync)("git rev-parse HEAD", { encoding: "utf8", cwd: process.cwd() }).trim();
83
- } catch {
84
- return "unknown";
85
- }
86
- }
87
- function getChangedFilesFromDiff(diff) {
88
- const text = diff ?? getUncommittedDiff();
89
- if (!text) return [];
90
- const files = /* @__PURE__ */ new Set();
91
- for (const line of text.split("\n")) {
92
- if (line.startsWith("+++ b/")) {
93
- files.add(line.slice(6));
94
- } else if (line.startsWith("--- a/")) {
95
- } else if (line.startsWith("diff --git ")) {
96
- const match = line.match(/diff --git a\/(.+?) b\/(.+)$/);
97
- if (match) files.add(match[2]);
98
- }
99
- }
100
- return [...files];
101
- }
102
- function getChangedFilesList() {
103
- try {
104
- const unstaged = (0, import_node_child_process.execSync)("git diff --name-only HEAD", { encoding: "utf8", cwd: process.cwd() }).trim();
105
- const staged = (0, import_node_child_process.execSync)("git diff --staged --name-only", { encoding: "utf8", cwd: process.cwd() }).trim();
106
- const files = /* @__PURE__ */ new Set();
107
- if (unstaged) unstaged.split("\n").forEach((f) => files.add(f));
108
- if (staged) staged.split("\n").forEach((f) => files.add(f));
109
- return [...files].filter(Boolean);
110
- } catch {
111
- return [];
112
- }
113
- }
114
- function getAuthorName() {
115
- try {
116
- return (0, import_node_child_process.execSync)("git config user.name", { encoding: "utf8", cwd: process.cwd() }).trim();
117
- } catch {
118
- return "unknown";
119
- }
120
- }
121
- var import_node_child_process, import_node_fs2, import_node_path2;
122
- var init_git = __esm({
123
- "src/git.ts"() {
124
- "use strict";
125
- import_node_child_process = require("node:child_process");
126
- import_node_fs2 = require("node:fs");
127
- import_node_path2 = require("node:path");
128
- }
129
- });
130
-
131
29
  // ../../libs/scanner/dist/identity/identity.js
132
30
  var require_identity = __commonJS({
133
31
  "../../libs/scanner/dist/identity/identity.js"(exports2) {
@@ -2538,7 +2436,7 @@ var require_typescript = __commonJS({
2538
2436
  var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
2539
2437
  var __getOwnPropNames2 = Object.getOwnPropertyNames;
2540
2438
  var __hasOwnProp2 = Object.prototype.hasOwnProperty;
2541
- var __export2 = (target, all) => {
2439
+ var __export = (target, all) => {
2542
2440
  for (var name in all)
2543
2441
  __defProp2(target, name, { get: all[name], enumerable: true });
2544
2442
  };
@@ -2552,7 +2450,7 @@ var require_typescript = __commonJS({
2552
2450
  };
2553
2451
  var __toCommonJS = (mod) => (__copyProps2, mod);
2554
2452
  var typescript_exports = {};
2555
- __export2(typescript_exports, {
2453
+ __export(typescript_exports, {
2556
2454
  ANONYMOUS: () => ANONYMOUS,
2557
2455
  AccessFlags: () => AccessFlags,
2558
2456
  AssertionLevel: () => AssertionLevel,
@@ -7639,7 +7537,7 @@ ${lanes.join("\n")}
7639
7537
  }
7640
7538
  var timestamp = nativePerformanceTime ? () => nativePerformanceTime.now() : Date.now;
7641
7539
  var ts_performance_exports = {};
7642
- __export2(ts_performance_exports, {
7540
+ __export(ts_performance_exports, {
7643
7541
  clearMarks: () => clearMarks,
7644
7542
  clearMeasures: () => clearMeasures,
7645
7543
  createTimer: () => createTimer,
@@ -55942,7 +55840,7 @@ ${lanes.join("\n")}
55942
55840
  }
55943
55841
  }
55944
55842
  var ts_moduleSpecifiers_exports = {};
55945
- __export2(ts_moduleSpecifiers_exports, {
55843
+ __export(ts_moduleSpecifiers_exports, {
55946
55844
  RelativePreference: () => RelativePreference,
55947
55845
  countPathComponents: () => countPathComponents,
55948
55846
  forEachFileNameOfModule: () => forEachFileNameOfModule,
@@ -126242,7 +126140,7 @@ ${lanes.join("\n")}
126242
126140
  }
126243
126141
  }
126244
126142
  function createImportCallExpressionAMD(arg, containsLexicalThis) {
126245
- const resolve9 = factory2.createUniqueName("resolve");
126143
+ const resolve8 = factory2.createUniqueName("resolve");
126246
126144
  const reject = factory2.createUniqueName("reject");
126247
126145
  const parameters = [
126248
126146
  factory2.createParameterDeclaration(
@@ -126251,7 +126149,7 @@ ${lanes.join("\n")}
126251
126149
  /*dotDotDotToken*/
126252
126150
  void 0,
126253
126151
  /*name*/
126254
- resolve9
126152
+ resolve8
126255
126153
  ),
126256
126154
  factory2.createParameterDeclaration(
126257
126155
  /*modifiers*/
@@ -126268,7 +126166,7 @@ ${lanes.join("\n")}
126268
126166
  factory2.createIdentifier("require"),
126269
126167
  /*typeArguments*/
126270
126168
  void 0,
126271
- [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve9, reject]
126169
+ [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve8, reject]
126272
126170
  )
126273
126171
  )
126274
126172
  ]);
@@ -150742,7 +150640,7 @@ ${lanes.join("\n")}
150742
150640
  }
150743
150641
  }
150744
150642
  var ts_JsTyping_exports = {};
150745
- __export2(ts_JsTyping_exports, {
150643
+ __export(ts_JsTyping_exports, {
150746
150644
  NameValidationResult: () => NameValidationResult,
150747
150645
  discoverTypings: () => discoverTypings,
150748
150646
  isTypingUpToDate: () => isTypingUpToDate,
@@ -157788,7 +157686,7 @@ interface Symbol {
157788
157686
  return options;
157789
157687
  }
157790
157688
  var ts_NavigateTo_exports = {};
157791
- __export2(ts_NavigateTo_exports, {
157689
+ __export(ts_NavigateTo_exports, {
157792
157690
  getNavigateToItems: () => getNavigateToItems
157793
157691
  });
157794
157692
  function getNavigateToItems(sourceFiles, checker, cancellationToken, searchValue, maxResultCount, excludeDtsFiles, excludeLibFiles) {
@@ -157893,7 +157791,7 @@ interface Symbol {
157893
157791
  };
157894
157792
  }
157895
157793
  var ts_NavigationBar_exports = {};
157896
- __export2(ts_NavigationBar_exports, {
157794
+ __export(ts_NavigationBar_exports, {
157897
157795
  getNavigationBarItems: () => getNavigationBarItems,
157898
157796
  getNavigationTree: () => getNavigationTree
157899
157797
  });
@@ -158681,7 +158579,7 @@ interface Symbol {
158681
158579
  return text.replace(/\\?(?:\r?\n|[\r\u2028\u2029])/g, "");
158682
158580
  }
158683
158581
  var ts_refactor_exports = {};
158684
- __export2(ts_refactor_exports, {
158582
+ __export(ts_refactor_exports, {
158685
158583
  addExportsInOldFile: () => addExportsInOldFile,
158686
158584
  addImportsForMovedSymbols: () => addImportsForMovedSymbols,
158687
158585
  addNewFileToTsconfig: () => addNewFileToTsconfig,
@@ -162224,7 +162122,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
162224
162122
  }
162225
162123
  }
162226
162124
  var ts_refactor_extractSymbol_exports = {};
162227
- __export2(ts_refactor_extractSymbol_exports, {
162125
+ __export(ts_refactor_extractSymbol_exports, {
162228
162126
  Messages: () => Messages,
162229
162127
  RangeFacts: () => RangeFacts,
162230
162128
  getRangeToExtract: () => getRangeToExtract2,
@@ -166803,7 +166701,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
166803
166701
  return result;
166804
166702
  }
166805
166703
  var ts_BreakpointResolver_exports = {};
166806
- __export2(ts_BreakpointResolver_exports, {
166704
+ __export(ts_BreakpointResolver_exports, {
166807
166705
  spanInSourceFileAtLocation: () => spanInSourceFileAtLocation
166808
166706
  });
166809
166707
  function spanInSourceFileAtLocation(sourceFile, position) {
@@ -167309,7 +167207,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
167309
167207
  }
167310
167208
  }
167311
167209
  var ts_CallHierarchy_exports = {};
167312
- __export2(ts_CallHierarchy_exports, {
167210
+ __export(ts_CallHierarchy_exports, {
167313
167211
  createCallHierarchyItem: () => createCallHierarchyItem,
167314
167212
  getIncomingCalls: () => getIncomingCalls,
167315
167213
  getOutgoingCalls: () => getOutgoingCalls,
@@ -167758,11 +167656,11 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
167758
167656
  return group(collectCallSites(program, declaration), getCallSiteGroupKey, (entries) => convertCallSiteGroupToOutgoingCall(program, entries));
167759
167657
  }
167760
167658
  var ts_classifier_exports = {};
167761
- __export2(ts_classifier_exports, {
167659
+ __export(ts_classifier_exports, {
167762
167660
  v2020: () => ts_classifier_v2020_exports
167763
167661
  });
167764
167662
  var ts_classifier_v2020_exports = {};
167765
- __export2(ts_classifier_v2020_exports, {
167663
+ __export(ts_classifier_v2020_exports, {
167766
167664
  TokenEncodingConsts: () => TokenEncodingConsts,
167767
167665
  TokenModifier: () => TokenModifier,
167768
167666
  TokenType: () => TokenType,
@@ -167770,7 +167668,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
167770
167668
  getSemanticClassifications: () => getSemanticClassifications2
167771
167669
  });
167772
167670
  var ts_codefix_exports = {};
167773
- __export2(ts_codefix_exports, {
167671
+ __export(ts_codefix_exports, {
167774
167672
  PreserveOptionalFlags: () => PreserveOptionalFlags,
167775
167673
  addNewNodeForMemberSymbol: () => addNewNodeForMemberSymbol,
167776
167674
  codeFixAll: () => codeFixAll,
@@ -179691,7 +179589,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
179691
179589
  }
179692
179590
  }
179693
179591
  var ts_Completions_exports = {};
179694
- __export2(ts_Completions_exports, {
179592
+ __export(ts_Completions_exports, {
179695
179593
  CompletionKind: () => CompletionKind,
179696
179594
  CompletionSource: () => CompletionSource,
179697
179595
  SortText: () => SortText,
@@ -183947,7 +183845,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
183947
183845
  return keyword === "abstract" || keyword === "async" || keyword === "await" || keyword === "declare" || keyword === "module" || keyword === "namespace" || keyword === "type" || keyword === "satisfies" || keyword === "as";
183948
183846
  }
183949
183847
  var ts_Completions_StringCompletions_exports = {};
183950
- __export2(ts_Completions_StringCompletions_exports, {
183848
+ __export(ts_Completions_StringCompletions_exports, {
183951
183849
  getStringLiteralCompletionDetails: () => getStringLiteralCompletionDetails,
183952
183850
  getStringLiteralCompletions: () => getStringLiteralCompletions
183953
183851
  });
@@ -185015,7 +184913,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
185015
184913
  return isCallExpression(node.parent) && firstOrUndefined(node.parent.arguments) === node && isIdentifier(node.parent.expression) && node.parent.expression.escapedText === "require";
185016
184914
  }
185017
184915
  var ts_FindAllReferences_exports = {};
185018
- __export2(ts_FindAllReferences_exports, {
184916
+ __export(ts_FindAllReferences_exports, {
185019
184917
  Core: () => Core,
185020
184918
  DefinitionKind: () => DefinitionKind,
185021
184919
  EntryKind: () => EntryKind,
@@ -187599,7 +187497,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
187599
187497
  }
187600
187498
  })(Core || (Core = {}));
187601
187499
  var ts_GoToDefinition_exports = {};
187602
- __export2(ts_GoToDefinition_exports, {
187500
+ __export(ts_GoToDefinition_exports, {
187603
187501
  createDefinitionInfo: () => createDefinitionInfo,
187604
187502
  getDefinitionAndBoundSpan: () => getDefinitionAndBoundSpan,
187605
187503
  getDefinitionAtPosition: () => getDefinitionAtPosition,
@@ -188171,7 +188069,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
188171
188069
  }
188172
188070
  }
188173
188071
  var ts_InlayHints_exports = {};
188174
- __export2(ts_InlayHints_exports, {
188072
+ __export(ts_InlayHints_exports, {
188175
188073
  provideInlayHints: () => provideInlayHints
188176
188074
  });
188177
188075
  var leadingParameterNameCommentRegexFactory = (name) => {
@@ -188972,7 +188870,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
188972
188870
  }
188973
188871
  }
188974
188872
  var ts_JsDoc_exports = {};
188975
- __export2(ts_JsDoc_exports, {
188873
+ __export(ts_JsDoc_exports, {
188976
188874
  getDocCommentTemplateAtPosition: () => getDocCommentTemplateAtPosition,
188977
188875
  getJSDocParameterNameCompletionDetails: () => getJSDocParameterNameCompletionDetails,
188978
188876
  getJSDocParameterNameCompletions: () => getJSDocParameterNameCompletions,
@@ -189409,7 +189307,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
189409
189307
  }
189410
189308
  }
189411
189309
  var ts_MapCode_exports = {};
189412
- __export2(ts_MapCode_exports, {
189310
+ __export(ts_MapCode_exports, {
189413
189311
  mapCode: () => mapCode
189414
189312
  });
189415
189313
  function mapCode(sourceFile, contents, focusLocations, host, formatContext, preferences) {
@@ -189613,7 +189511,7 @@ ${content}
189613
189511
  node.forEachChild(resetNodePositions);
189614
189512
  }
189615
189513
  var ts_OrganizeImports_exports = {};
189616
- __export2(ts_OrganizeImports_exports, {
189514
+ __export(ts_OrganizeImports_exports, {
189617
189515
  compareImportsOrRequireStatements: () => compareImportsOrRequireStatements,
189618
189516
  compareModuleSpecifiers: () => compareModuleSpecifiers2,
189619
189517
  getImportDeclarationInsertionIndex: () => getImportDeclarationInsertionIndex,
@@ -190273,7 +190171,7 @@ ${content}
190273
190171
  return compareModuleSpecifiersWorker(m1, m2, comparer);
190274
190172
  }
190275
190173
  var ts_OutliningElementsCollector_exports = {};
190276
- __export2(ts_OutliningElementsCollector_exports, {
190174
+ __export(ts_OutliningElementsCollector_exports, {
190277
190175
  collectElements: () => collectElements
190278
190176
  });
190279
190177
  function collectElements(sourceFile, cancellationToken) {
@@ -190692,7 +190590,7 @@ ${content}
190692
190590
  return findChildOfKind(body, 19, sourceFile);
190693
190591
  }
190694
190592
  var ts_Rename_exports = {};
190695
- __export2(ts_Rename_exports, {
190593
+ __export(ts_Rename_exports, {
190696
190594
  getRenameInfo: () => getRenameInfo,
190697
190595
  nodeIsEligibleForRename: () => nodeIsEligibleForRename
190698
190596
  });
@@ -190848,7 +190746,7 @@ ${content}
190848
190746
  }
190849
190747
  }
190850
190748
  var ts_SignatureHelp_exports = {};
190851
- __export2(ts_SignatureHelp_exports, {
190749
+ __export(ts_SignatureHelp_exports, {
190852
190750
  getArgumentInfoForCompletions: () => getArgumentInfoForCompletions,
190853
190751
  getSignatureHelpItems: () => getSignatureHelpItems
190854
190752
  });
@@ -191394,7 +191292,7 @@ ${content}
191394
191292
  return { name: typeParameter.symbol.name, documentation: typeParameter.symbol.getDocumentationComment(checker), displayParts, isOptional: false, isRest: false };
191395
191293
  }
191396
191294
  var ts_SmartSelectionRange_exports = {};
191397
- __export2(ts_SmartSelectionRange_exports, {
191295
+ __export(ts_SmartSelectionRange_exports, {
191398
191296
  getSmartSelectionRange: () => getSmartSelectionRange
191399
191297
  });
191400
191298
  function getSmartSelectionRange(pos, sourceFile) {
@@ -191625,7 +191523,7 @@ ${content}
191625
191523
  }
191626
191524
  }
191627
191525
  var ts_SymbolDisplay_exports = {};
191628
- __export2(ts_SymbolDisplay_exports, {
191526
+ __export(ts_SymbolDisplay_exports, {
191629
191527
  getSymbolDisplayPartsDocumentationAndSymbolKind: () => getSymbolDisplayPartsDocumentationAndSymbolKind,
191630
191528
  getSymbolKind: () => getSymbolKind,
191631
191529
  getSymbolModifiers: () => getSymbolModifiers
@@ -192593,7 +192491,7 @@ ${content}
192593
192491
  });
192594
192492
  }
192595
192493
  var ts_textChanges_exports = {};
192596
- __export2(ts_textChanges_exports, {
192494
+ __export(ts_textChanges_exports, {
192597
192495
  ChangeTracker: () => ChangeTracker,
192598
192496
  LeadingTriviaOption: () => LeadingTriviaOption,
192599
192497
  TrailingTriviaOption: () => TrailingTriviaOption,
@@ -194010,7 +193908,7 @@ ${options.prefix}` : "\n" : options.prefix
194010
193908
  });
194011
193909
  }
194012
193910
  var ts_formatting_exports = {};
194013
- __export2(ts_formatting_exports, {
193911
+ __export(ts_formatting_exports, {
194014
193912
  FormattingContext: () => FormattingContext,
194015
193913
  FormattingRequestKind: () => FormattingRequestKind,
194016
193914
  RuleAction: () => RuleAction,
@@ -197910,7 +197808,7 @@ ${options.prefix}` : "\n" : options.prefix
197910
197808
  }
197911
197809
  })(SmartIndenter || (SmartIndenter = {}));
197912
197810
  var ts_preparePasteEdits_exports = {};
197913
- __export2(ts_preparePasteEdits_exports, {
197811
+ __export(ts_preparePasteEdits_exports, {
197914
197812
  preparePasteEdits: () => preparePasteEdits
197915
197813
  });
197916
197814
  function preparePasteEdits(sourceFile, copiedFromRange, checker) {
@@ -197948,7 +197846,7 @@ ${options.prefix}` : "\n" : options.prefix
197948
197846
  return shouldProvidePasteEdits;
197949
197847
  }
197950
197848
  var ts_PasteEdits_exports = {};
197951
- __export2(ts_PasteEdits_exports, {
197849
+ __export(ts_PasteEdits_exports, {
197952
197850
  pasteEditsProvider: () => pasteEditsProvider
197953
197851
  });
197954
197852
  var fixId55 = "providePostPasteEdits";
@@ -198055,7 +197953,7 @@ ${options.prefix}` : "\n" : options.prefix
198055
197953
  };
198056
197954
  }
198057
197955
  var ts_exports2 = {};
198058
- __export2(ts_exports2, {
197956
+ __export(ts_exports2, {
198059
197957
  ANONYMOUS: () => ANONYMOUS,
198060
197958
  AccessFlags: () => AccessFlags,
198061
197959
  AssertionLevel: () => AssertionLevel,
@@ -200406,7 +200304,7 @@ ${options.prefix}` : "\n" : options.prefix
200406
200304
  };
200407
200305
  }
200408
200306
  var ts_server_exports3 = {};
200409
- __export2(ts_server_exports3, {
200307
+ __export(ts_server_exports3, {
200410
200308
  ActionInvalidate: () => ActionInvalidate,
200411
200309
  ActionPackageInstalled: () => ActionPackageInstalled,
200412
200310
  ActionSet: () => ActionSet,
@@ -200504,7 +200402,7 @@ ${options.prefix}` : "\n" : options.prefix
200504
200402
  updateProjectIfDirty: () => updateProjectIfDirty
200505
200403
  });
200506
200404
  var ts_server_typingsInstaller_exports = {};
200507
- __export2(ts_server_typingsInstaller_exports, {
200405
+ __export(ts_server_typingsInstaller_exports, {
200508
200406
  TypingsInstaller: () => TypingsInstaller,
200509
200407
  getNpmCommandForInstallation: () => getNpmCommandForInstallation,
200510
200408
  installNpmPackages: () => installNpmPackages,
@@ -201071,7 +200969,7 @@ ${options.prefix}` : "\n" : options.prefix
201071
200969
  return base === "tsconfig.json" || base === "jsconfig.json" ? base : void 0;
201072
200970
  }
201073
200971
  var ts_server_protocol_exports = {};
201074
- __export2(ts_server_protocol_exports, {
200972
+ __export(ts_server_protocol_exports, {
201075
200973
  ClassificationType: () => ClassificationType,
201076
200974
  CommandTypes: () => CommandTypes,
201077
200975
  CompletionTriggerKind: () => CompletionTriggerKind,
@@ -212986,8 +212884,8 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
212986
212884
  installPackage(options) {
212987
212885
  this.packageInstallId++;
212988
212886
  const request2 = { kind: "installPackage", ...options, id: this.packageInstallId };
212989
- const promise = new Promise((resolve9, reject) => {
212990
- (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve9, reject });
212887
+ const promise = new Promise((resolve8, reject) => {
212888
+ (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve8, reject });
212991
212889
  });
212992
212890
  this.installer.send(request2);
212993
212891
  return promise;
@@ -213145,7 +213043,7 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
213145
213043
  _TypingsInstallerAdapter.requestDelayMillis = 100;
213146
213044
  var TypingsInstallerAdapter = _TypingsInstallerAdapter;
213147
213045
  var ts_server_exports4 = {};
213148
- __export2(ts_server_exports4, {
213046
+ __export(ts_server_exports4, {
213149
213047
  ActionInvalidate: () => ActionInvalidate,
213150
213048
  ActionPackageInstalled: () => ActionPackageInstalled,
213151
213049
  ActionSet: () => ActionSet,
@@ -214373,7 +214271,7 @@ function parseError(e) {
214373
214271
  return msg;
214374
214272
  }
214375
214273
  function request(method, path, body) {
214376
- return new Promise((resolve9, reject) => {
214274
+ return new Promise((resolve8, reject) => {
214377
214275
  const baseUrl = getBaseUrl();
214378
214276
  const fullUrl = `${baseUrl}${path}`;
214379
214277
  const url = new URL(fullUrl);
@@ -214399,9 +214297,9 @@ function request(method, path, body) {
214399
214297
  return;
214400
214298
  }
214401
214299
  try {
214402
- resolve9(JSON.parse(data));
214300
+ resolve8(JSON.parse(data));
214403
214301
  } catch {
214404
- resolve9(data);
214302
+ resolve8(data);
214405
214303
  }
214406
214304
  });
214407
214305
  }
@@ -214428,8 +214326,78 @@ function formatError(e) {
214428
214326
  return parseError(e);
214429
214327
  }
214430
214328
 
214329
+ // src/git.ts
214330
+ var import_node_child_process = require("node:child_process");
214331
+ var import_node_fs2 = require("node:fs");
214332
+ var import_node_path2 = require("node:path");
214333
+ function isGitInstalled() {
214334
+ try {
214335
+ (0, import_node_child_process.execSync)("git --version", { stdio: "ignore" });
214336
+ return true;
214337
+ } catch {
214338
+ return false;
214339
+ }
214340
+ }
214341
+ function getGitRemote() {
214342
+ try {
214343
+ const url = (0, import_node_child_process.execSync)("git config --get remote.origin.url", {
214344
+ encoding: "utf8",
214345
+ cwd: process.cwd()
214346
+ }).trim();
214347
+ const match = url.match(/[:/]([^/]+)\/([^/]+?)(?:\.git)?$/);
214348
+ if (match) {
214349
+ return { org: match[1], repo: match[2] };
214350
+ }
214351
+ return null;
214352
+ } catch {
214353
+ return null;
214354
+ }
214355
+ }
214356
+ function isGitRepo() {
214357
+ return (0, import_node_fs2.existsSync)((0, import_node_path2.resolve)(process.cwd(), ".git"));
214358
+ }
214359
+ function getUncommittedDiff() {
214360
+ try {
214361
+ return (0, import_node_child_process.execSync)("git diff", { encoding: "utf8", cwd: process.cwd() }).trim();
214362
+ } catch {
214363
+ return "";
214364
+ }
214365
+ }
214366
+ function getStagedDiff() {
214367
+ try {
214368
+ return (0, import_node_child_process.execSync)("git diff --staged", { encoding: "utf8", cwd: process.cwd() }).trim();
214369
+ } catch {
214370
+ return "";
214371
+ }
214372
+ }
214373
+ function getLastCommitHash() {
214374
+ try {
214375
+ return (0, import_node_child_process.execSync)("git rev-parse HEAD", { encoding: "utf8", cwd: process.cwd() }).trim();
214376
+ } catch {
214377
+ return "unknown";
214378
+ }
214379
+ }
214380
+ function getChangedFilesList() {
214381
+ try {
214382
+ const unstaged = (0, import_node_child_process.execSync)("git diff --name-only HEAD", { encoding: "utf8", cwd: process.cwd() }).trim();
214383
+ const staged = (0, import_node_child_process.execSync)("git diff --staged --name-only", { encoding: "utf8", cwd: process.cwd() }).trim();
214384
+ const files = /* @__PURE__ */ new Set();
214385
+ if (unstaged) unstaged.split("\n").forEach((f) => files.add(f));
214386
+ if (staged) staged.split("\n").forEach((f) => files.add(f));
214387
+ return [...files].filter(Boolean);
214388
+ } catch {
214389
+ return [];
214390
+ }
214391
+ }
214392
+ function getAuthorName() {
214393
+ try {
214394
+ return (0, import_node_child_process.execSync)("git config user.name", { encoding: "utf8", cwd: process.cwd() }).trim();
214395
+ } catch {
214396
+ return "unknown";
214397
+ }
214398
+ }
214399
+
214431
214400
  // src/commands/init.ts
214432
- init_git();
214433
214401
  var import_scanner = __toESM(require_dist());
214434
214402
  var import_node_fs4 = require("node:fs");
214435
214403
  var import_node_path4 = require("node:path");
@@ -214539,7 +214507,7 @@ async function installSkillCommand() {
214539
214507
  // src/commands/init.ts
214540
214508
  function getVersion() {
214541
214509
  try {
214542
- return "0.1.31";
214510
+ return "0.1.33";
214543
214511
  } catch {
214544
214512
  return "0.0.0";
214545
214513
  }
@@ -214846,13 +214814,17 @@ async function initCommand(args) {
214846
214814
  console.log("");
214847
214815
  console.log(DIVIDER);
214848
214816
  console.log("");
214817
+ if (!isGitInstalled()) {
214818
+ console.error("Error: git is not installed. Install git and try again.");
214819
+ process.exit(1);
214820
+ }
214849
214821
  if (!isGitRepo()) {
214850
- console.error("Error: not a git repository.");
214822
+ console.error("Error: not a git repository. Run `git init` first.");
214851
214823
  process.exit(1);
214852
214824
  }
214853
214825
  const remote = getGitRemote();
214854
214826
  if (!remote) {
214855
- console.error("Error: no git remote found.");
214827
+ console.error("Error: no git remote configured. Run `git remote add origin <url>` first.");
214856
214828
  process.exit(1);
214857
214829
  }
214858
214830
  let workspace;
@@ -214975,7 +214947,8 @@ async function initCommand(args) {
214975
214947
  gotchas: watcher.gotchas,
214976
214948
  ownership: watcher.ownership,
214977
214949
  where_repos: [repo.id],
214978
- created_by: "driftless-init"
214950
+ created_by: "driftless-init",
214951
+ suggested: true
214979
214952
  });
214980
214953
  watchersCreated++;
214981
214954
  } catch {
@@ -215010,7 +214983,6 @@ async function initCommand(args) {
215010
214983
  }
215011
214984
 
215012
214985
  // src/commands/scan.ts
215013
- init_git();
215014
214986
  function emitJSON(data) {
215015
214987
  console.log(JSON.stringify(data, null, 2));
215016
214988
  }
@@ -215121,7 +215093,6 @@ ${result.violations.length} violation(s) found (${rulesEvaluated} rule(s) evalua
215121
215093
  }
215122
215094
 
215123
215095
  // src/commands/context.ts
215124
- init_git();
215125
215096
  var import_node_fs5 = require("node:fs");
215126
215097
  var import_node_path5 = require("node:path");
215127
215098
  function parseArgs(args) {
@@ -215314,14 +215285,20 @@ async function contextCommand(args) {
215314
215285
  if (flags["auto"]) query.push("auto=true");
215315
215286
  if (flags["manual"]) query.push("manual=true");
215316
215287
  if (flags["repo"]) query.push(`repo=${encodeURIComponent(flags["repo"])}`);
215288
+ if (flags["suggested"]) query.push("suggested=true");
215289
+ else query.push("suggested=false");
215317
215290
  const qs = query.length > 0 ? `?${query.join("&")}` : "";
215318
215291
  try {
215319
215292
  const summaries = await api.get(`/workspaces/${workspaceSlug}/watchers${qs}`);
215320
215293
  if (summaries.length === 0 && !isJSON) {
215321
- console.log("No context topics yet.");
215322
- console.log("\nNext:");
215323
- console.log(' driftless context add "auth-boundaries" --what "..." --how "..." --pattern "src/auth/**"');
215324
- console.log(" driftless init # auto-generate topics from your codebase");
215294
+ if (flags["suggested"]) {
215295
+ console.log("No suggested topics. Run `driftless init` to generate suggestions.");
215296
+ } else {
215297
+ console.log("No context topics yet.");
215298
+ console.log("\nNext:");
215299
+ console.log(' driftless context add "auth-boundaries" --what "..." --how "..." --pattern "src/auth/**"');
215300
+ console.log(" driftless init # generate topic suggestions from your codebase");
215301
+ }
215325
215302
  }
215326
215303
  if (isJSON) {
215327
215304
  emitJSON2(summaries);
@@ -215514,12 +215491,22 @@ async function contextCommand(args) {
215514
215491
  console.error('PR 3: --gotcha, --invariant, --check, --enforce "<rule-description>"');
215515
215492
  process.exit(1);
215516
215493
  }
215494
+ const currentRemote = getGitRemote();
215495
+ if (currentRemote) {
215496
+ try {
215497
+ const repos = await api.get(`/workspaces/${workspaceSlug}/repos`);
215498
+ const match = repos.find((r) => r.github_org === currentRemote.org && r.github_repo === currentRemote.repo);
215499
+ if (match) updates._add_repo = match.id;
215500
+ } catch {
215501
+ }
215502
+ }
215517
215503
  if (flags["dry-run"]) {
215518
215504
  console.log(`Would update topic '${slug}':`);
215519
215505
  for (const [key, value] of Object.entries(updates)) {
215520
215506
  if (key.startsWith("_")) continue;
215521
215507
  console.log(` ${key}: ${value}`);
215522
215508
  }
215509
+ if (updates._add_repo) console.log(` _add_repo: ${updates._add_repo} (${currentRemote?.org}/${currentRemote?.repo})`);
215523
215510
  if (!isJSON) {
215524
215511
  console.log("\n(Dry run \u2014 no changes written to Driftless Cloud)");
215525
215512
  }
@@ -215887,13 +215874,9 @@ Done: ${created} created, ${updated} updated.`);
215887
215874
  Run 'driftless help context' for full reference.`);
215888
215875
  }
215889
215876
 
215890
- // src/commands/session.ts
215891
- init_git();
215892
- var import_node_fs6 = require("node:fs");
215893
- var import_node_path6 = require("node:path");
215877
+ // src/commands/sync.ts
215894
215878
  function parseArgs2(args) {
215895
215879
  const flags = {};
215896
- const positional = [];
215897
215880
  for (let i = 0; i < args.length; i++) {
215898
215881
  if (args[i].startsWith("--")) {
215899
215882
  const key = args[i].slice(2);
@@ -215901,14 +215884,10 @@ function parseArgs2(args) {
215901
215884
  if (next && !next.startsWith("--")) {
215902
215885
  flags[key] = next;
215903
215886
  i++;
215904
- } else {
215905
- flags[key] = true;
215906
- }
215907
- } else {
215908
- positional.push(args[i]);
215887
+ } else flags[key] = true;
215909
215888
  }
215910
215889
  }
215911
- return { flags, positional };
215890
+ return { flags };
215912
215891
  }
215913
215892
  function emitJSON3(data) {
215914
215893
  console.log(JSON.stringify(data, null, 2));
@@ -215926,250 +215905,115 @@ async function resolveWorkspaceSlug2() {
215926
215905
  }
215927
215906
  return remote.org;
215928
215907
  }
215929
- async function sessionCommand(args) {
215908
+ async function syncCommand(args) {
215930
215909
  if (!isGitRepo()) {
215931
215910
  console.error("Error: not a git repository.");
215932
215911
  process.exit(1);
215933
215912
  }
215934
- const workspaceSlug = await resolveWorkspaceSlug2();
215935
- const { flags, positional } = parseArgs2(args);
215936
- const subCommand = positional[0];
215913
+ const { flags } = parseArgs2(args);
215937
215914
  const isJSON = !!flags["json"];
215938
- if (subCommand === "start") {
215939
- const filesFlag = flags["files"];
215940
- let files = [];
215941
- if (filesFlag) {
215942
- files = filesFlag.split(",").map((f) => f.trim()).filter(Boolean);
215915
+ const remote = getGitRemote();
215916
+ if (!remote) {
215917
+ console.error("Error: no git remote configured.");
215918
+ process.exit(1);
215919
+ }
215920
+ const workspaceSlug = await resolveWorkspaceSlug2();
215921
+ let repoId = null;
215922
+ try {
215923
+ const repos = await api.get(`/workspaces/${workspaceSlug}/repos`);
215924
+ const match = repos.find((r) => r.github_org === remote.org && r.github_repo === remote.repo);
215925
+ if (match) repoId = match.id;
215926
+ } catch {
215927
+ }
215928
+ if (!repoId) {
215929
+ if (!isJSON) {
215930
+ console.log(`Repo '${remote.org}/${remote.repo}' not found in workspace.`);
215931
+ console.log("Run driftless init to register this repo first.");
215943
215932
  } else {
215944
- files = getChangedFilesList();
215933
+ emitJSON3({ error: "repo_not_found", repo: `${remote.org}/${remote.repo}` });
215945
215934
  }
215946
- if (files.length === 0) {
215947
- if (!isJSON) {
215948
- console.log("No files specified and no local changes detected.");
215949
- console.log('Usage: driftless session start --files "src/auth/**"');
215950
- } else {
215951
- emitJSON3({ files: [], topics: [], docs: [], rules: [], gotchas: [] });
215952
- }
215953
- process.exit(0);
215954
- }
215955
- const missingFiles = files.filter((f) => !(0, import_node_fs6.existsSync)((0, import_node_path6.resolve)(process.cwd(), f)));
215956
- if (missingFiles.length > 0 && !isJSON) {
215957
- console.error(`Warning: ${missingFiles.length} file(s) not found locally \u2014 matching by pattern only.`);
215958
- }
215959
- try {
215960
- const results = await api.post(
215961
- `/workspaces/${workspaceSlug}/watchers/match-files`,
215962
- { files }
215963
- );
215964
- const topics = [];
215965
- const docs = [];
215966
- const rules = [];
215967
- const gotchas = [];
215968
- const allWhat = [];
215969
- const allHow = [];
215970
- for (const r of results) {
215971
- const ctx = r.context;
215972
- topics.push(ctx.topic);
215973
- if (ctx.description.what) allWhat.push(ctx.description.what);
215974
- if (ctx.description.how) allHow.push(ctx.description.how);
215975
- if (ctx.description.gotchas) gotchas.push(...ctx.description.gotchas);
215976
- if (ctx.anchors.docs) {
215977
- for (const d of ctx.anchors.docs) {
215978
- if (d.path) docs.push(d.path);
215979
- }
215980
- }
215981
- if (ctx.rules) {
215982
- for (const rule of ctx.rules) {
215983
- rules.push(rule.name);
215984
- }
215985
- }
215986
- }
215987
- if (isJSON) {
215988
- emitJSON3({
215989
- files,
215990
- missing_files: missingFiles,
215991
- topics,
215992
- docs: [...new Set(docs)],
215993
- rules,
215994
- gotchas,
215995
- context_summary: {
215996
- what: allWhat,
215997
- how: allHow
215998
- }
215999
- });
216000
- } else {
216001
- console.log(`Session started for ${files.length} file(s):
215935
+ process.exit(0);
215936
+ }
215937
+ const [eventsRes, staleTopics, violations, suggestedTopics] = await Promise.allSettled([
215938
+ api.get(`/workspaces/${workspaceSlug}/watchers/events?repo_id=${repoId}&limit=20`),
215939
+ api.get(`/workspaces/${workspaceSlug}/watchers?stale=true&repo=${repoId}`),
215940
+ api.get(`/workspaces/${workspaceSlug}/violations?repo_id=${repoId}&status=open&limit=20`),
215941
+ api.get(`/workspaces/${workspaceSlug}/watchers?suggested=true`)
215942
+ ]);
215943
+ const events = eventsRes.status === "fulfilled" ? eventsRes.value.events ?? [] : [];
215944
+ const stale = staleTopics.status === "fulfilled" ? staleTopics.value : [];
215945
+ const rawViolations = violations.status === "fulfilled" ? violations.value : [];
215946
+ const openViolations = Array.isArray(rawViolations) ? rawViolations : rawViolations.violations ?? rawViolations.items ?? [];
215947
+ const suggested = suggestedTopics.status === "fulfilled" ? suggestedTopics.value : [];
215948
+ if (isJSON) {
215949
+ emitJSON3({
215950
+ repo: `${remote.org}/${remote.repo}`,
215951
+ stale_topics: stale.map((t) => ({ topic: t.topic, reason: t.stale?.reason ?? null })),
215952
+ recent_events: events.slice(0, 10).map((e) => ({
215953
+ type: e.event_type,
215954
+ topic: e.watcher_slug,
215955
+ detail: e.detail,
215956
+ created_at: e.created_at
215957
+ })),
215958
+ open_violations: openViolations.map((v) => ({
215959
+ id: v.id,
215960
+ rule_id: v.rule_id,
215961
+ status: v.status,
215962
+ author: v.author
215963
+ })),
215964
+ suggested_pending: suggested.length
215965
+ });
215966
+ process.exit(0);
215967
+ }
215968
+ console.log(`\u258C ${remote.org}/${remote.repo}
216002
215969
  `);
216003
- for (const f of files) {
216004
- const exists = (0, import_node_fs6.existsSync)((0, import_node_path6.resolve)(process.cwd(), f));
216005
- console.log(` ${exists ? "\u2713" : "\u2717"} ${f}`);
216006
- }
216007
- if (missingFiles.length > 0) {
216008
- console.log(`
216009
- Warning: ${missingFiles.length} file(s) not found locally.`);
216010
- }
216011
- if (topics.length > 0) {
216012
- console.log(`
216013
- Matched ${topics.length} context topic(s):`);
216014
- for (const r of results) {
216015
- console.log(` \u258C ${r.context.topic} (${r.match_reason})`);
216016
- if (r.context.description.what) {
216017
- console.log(` ${r.context.description.what}`);
216018
- }
216019
- }
216020
- } else {
216021
- console.log("\nNo context topics match these files.");
216022
- }
216023
- if (docs.length > 0) {
216024
- console.log(`
216025
- Anchored docs:`);
216026
- for (const d of [...new Set(docs)]) {
216027
- console.log(` \u{1F4C4} ${d}`);
216028
- }
216029
- }
216030
- if (gotchas.length > 0) {
216031
- console.log(`
216032
- Gotchas:`);
216033
- for (const g of gotchas) {
216034
- console.log(` ! ${g}`);
216035
- }
216036
- }
216037
- if (rules.length > 0) {
216038
- console.log(`
216039
- Rules that will be evaluated:`);
216040
- for (const r of rules) {
216041
- console.log(` \u2713 ${r}`);
216042
- }
216043
- }
216044
- console.log("\nBefore finishing:");
216045
- console.log(" driftless scan --diff");
216046
- console.log(" driftless session end");
216047
- }
216048
- } catch (e) {
216049
- console.error(`Session start failed: ${formatError(e)}`);
216050
- process.exit(1);
215970
+ if (stale.length > 0) {
215971
+ console.log(`\u26A0 ${stale.length} stale topic${stale.length === 1 ? "" : "s"} \u2014 code changed, context not updated:`);
215972
+ for (const t of stale) {
215973
+ console.log(` ${t.topic}`);
215974
+ if (t.stale?.reason) console.log(` reason: ${t.stale.reason}`);
215975
+ console.log(` \u2192 driftless context update ${t.topic} --what "..." --how "..."`);
216051
215976
  }
216052
- return;
215977
+ console.log("");
216053
215978
  }
216054
- if (subCommand === "end") {
216055
- const files = getChangedFilesList();
216056
- if (files.length === 0 && !isJSON) {
216057
- console.log("No local changes detected. Session clean.");
216058
- process.exit(0);
215979
+ if (events.length > 0) {
215980
+ console.log(`Recent activity (${events.length}):`);
215981
+ for (const e of events.slice(0, 10)) {
215982
+ const topic = e.watcher_slug ? `[${e.watcher_slug}]` : "";
215983
+ const detail = e.detail ? ` ${e.detail.slice(0, 80)}` : "";
215984
+ console.log(` ${e.event_type.padEnd(14)} ${topic}${detail}`);
216059
215985
  }
216060
- try {
216061
- const remote = getGitRemote();
216062
- if (!remote) {
216063
- console.error("Error: no git remote found.");
216064
- process.exit(1);
216065
- }
216066
- const me = await api.get("/me");
216067
- const repos = await api.get(`/workspaces/${me.slug}/repos`);
216068
- const repo = repos.find((r) => r.github_org === remote.org && r.github_repo === remote.repo);
216069
- if (!repo) {
216070
- console.error(`Repo '${remote.repo}' not found. Run 'driftless init' first.`);
216071
- process.exit(1);
216072
- }
216073
- const { getUncommittedDiff: getUncommittedDiff2, getStagedDiff: getStagedDiff2, getLastCommitHash: getLastCommitHash2, getAuthorName: getAuthorName2 } = await Promise.resolve().then(() => (init_git(), git_exports));
216074
- const staged = getStagedDiff2();
216075
- const unstaged = getUncommittedDiff2();
216076
- const diff = [staged, unstaged].filter(Boolean).join("\n");
216077
- if (!diff && !isJSON) {
216078
- console.log("No changes to scan. Session clean.");
216079
- process.exit(0);
216080
- }
216081
- const scanResult = await api.post("/scan", {
216082
- workspace_id: me.workspace_id,
216083
- repo_id: repo.id,
216084
- diff,
216085
- commit_hash: getLastCommitHash2(),
216086
- author: getAuthorName2()
216087
- });
216088
- const rulesEvaluated = scanResult.rules_evaluated || 0;
216089
- const violations = scanResult.violations || [];
216090
- const contextResults = files.length > 0 ? await api.post(
216091
- `/workspaces/${me.slug}/watchers/match-files`,
216092
- { files }
216093
- ) : [];
216094
- const staleTopics = contextResults.filter((r) => r.context.stale?.is_stale);
216095
- if (isJSON) {
216096
- emitJSON3({
216097
- files,
216098
- rules_evaluated: rulesEvaluated,
216099
- violations,
216100
- stale_topics: staleTopics.map((r) => ({ topic: r.context.topic, reason: r.context.stale.reason })),
216101
- context_matched: contextResults.map((r) => r.context.topic)
216102
- });
216103
- } else {
216104
- console.log(`Session end \u2014 ${files.length} file(s) changed:
216105
- `);
216106
- for (const f of files) {
216107
- console.log(` \u270E ${f}`);
216108
- }
216109
- console.log(`
216110
- ${rulesEvaluated} rule(s) evaluated.`);
216111
- if (violations.length > 0) {
216112
- console.log(`
216113
- ${violations.length} violation(s) found:`);
216114
- for (const v of violations) {
216115
- console.log(` \u2717 [${v.severity.toUpperCase()}] ${v.rule_name}`);
216116
- console.log(` ${v.file_path}:${v.line_number} \u2014 ${v.explanation}`);
216117
- }
216118
- console.log("\nFix violations before pushing.");
216119
- } else {
216120
- console.log("No violations.");
216121
- }
216122
- if (staleTopics.length > 0) {
216123
- console.log(`
216124
- \u26A0 ${staleTopics.length} stale context topic(s):`);
216125
- for (const s of staleTopics) {
216126
- console.log(` ${s.context.topic} \u2014 ${s.context.stale.reason}`);
216127
- console.log(` \u2192 driftless context update ${s.context.topic} --what "..." --how "..."`);
216128
- }
216129
- }
216130
- if (contextResults.length > 0) {
216131
- console.log(`
216132
- Context touched:`);
216133
- for (const r of contextResults) {
216134
- console.log(` \u258C ${r.context.topic}`);
216135
- }
216136
- }
216137
- console.log("\nLearned something? Update context:");
216138
- console.log(' driftless context update <topic> --gotchas "..."');
216139
- console.log(' driftless context add <new-topic> --what "..." --pattern "..."');
216140
- }
216141
- if (violations.length > 0) {
216142
- process.exit(1);
216143
- }
216144
- } catch (e) {
216145
- console.error(`Session end failed: ${formatError(e)}`);
216146
- process.exit(1);
215986
+ console.log("");
215987
+ }
215988
+ if (openViolations.length > 0) {
215989
+ console.log(`\u2717 ${openViolations.length} open violation${openViolations.length === 1 ? "" : "s"}:`);
215990
+ for (const v of openViolations.slice(0, 5)) {
215991
+ console.log(` ${v.rule_id} ${v.author ? `(${v.author})` : ""}`);
216147
215992
  }
216148
- return;
215993
+ if (openViolations.length > 5) console.log(` ... and ${openViolations.length - 5} more`);
215994
+ console.log("");
216149
215995
  }
216150
- console.log(`Usage: driftless session <start|end> [args]
216151
-
216152
- start \u2014 Show relevant context before editing
216153
- --files "path1,path2" Files to check (default: local changes)
216154
- --json Output as JSON
216155
-
216156
- end \u2014 Scan changes, check violations, suggest context updates
216157
- --json Output as JSON
216158
-
216159
- Examples:
216160
- driftless session start --files "src/auth/**"
216161
- driftless session start # uses local changes
216162
- driftless session end # scan + context report`);
215996
+ if (suggested.length > 0) {
215997
+ console.log(`${suggested.length} suggested topic${suggested.length === 1 ? "" : "s"} from init \u2014 review and confirm:`);
215998
+ console.log(` driftless context list --suggested`);
215999
+ console.log("");
216000
+ }
216001
+ if (stale.length === 0 && events.length === 0 && openViolations.length === 0 && suggested.length === 0) {
216002
+ console.log("Cloud context is up to date. Nothing to sync.");
216003
+ } else {
216004
+ console.log("Review stale topics, then update context before touching code.");
216005
+ }
216006
+ process.exit(0);
216163
216007
  }
216164
216008
 
216165
216009
  // src/commands/login.ts
216166
- var import_node_fs7 = require("node:fs");
216167
- var import_node_path7 = require("node:path");
216010
+ var import_node_fs6 = require("node:fs");
216011
+ var import_node_path6 = require("node:path");
216168
216012
  var import_node_readline = require("node:readline");
216169
216013
  var import_node_child_process2 = require("node:child_process");
216170
216014
  var import_node_os2 = require("node:os");
216171
- var CONFIG_DIR = (0, import_node_path7.resolve)((0, import_node_os2.homedir)(), ".driftless");
216172
- var CONFIG_PATH2 = (0, import_node_path7.resolve)(CONFIG_DIR, "config.json");
216015
+ var CONFIG_DIR = (0, import_node_path6.resolve)((0, import_node_os2.homedir)(), ".driftless");
216016
+ var CONFIG_PATH2 = (0, import_node_path6.resolve)(CONFIG_DIR, "config.json");
216173
216017
  function openBrowser(url) {
216174
216018
  const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
216175
216019
  const child = (0, import_node_child_process2.spawn)(cmd, [url], { stdio: "ignore", detached: true });
@@ -216199,10 +216043,10 @@ async function loginCommand(args) {
216199
216043
  input: process.stdin,
216200
216044
  output: process.stdout
216201
216045
  });
216202
- const apiKey = await new Promise((resolve9) => {
216046
+ const apiKey = await new Promise((resolve8) => {
216203
216047
  rl.question("Paste your API key: ", (answer) => {
216204
216048
  rl.close();
216205
- resolve9(answer.trim());
216049
+ resolve8(answer.trim());
216206
216050
  });
216207
216051
  });
216208
216052
  if (!apiKey.startsWith("drift_")) {
@@ -216215,10 +216059,10 @@ async function loginCommand(args) {
216215
216059
  function saveConfig(apiKey, apiUrl) {
216216
216060
  const url = apiUrl || "https://api.driftless.icu/api/v1";
216217
216061
  try {
216218
- if (!(0, import_node_fs7.existsSync)(CONFIG_DIR)) {
216219
- (0, import_node_fs7.mkdirSync)(CONFIG_DIR, { recursive: true });
216062
+ if (!(0, import_node_fs6.existsSync)(CONFIG_DIR)) {
216063
+ (0, import_node_fs6.mkdirSync)(CONFIG_DIR, { recursive: true });
216220
216064
  }
216221
- (0, import_node_fs7.writeFileSync)(
216065
+ (0, import_node_fs6.writeFileSync)(
216222
216066
  CONFIG_PATH2,
216223
216067
  JSON.stringify({ api_key: apiKey, api_url: url }, null, 2) + "\n"
216224
216068
  );
@@ -216235,9 +216079,8 @@ function saveConfig(apiKey, apiUrl) {
216235
216079
  }
216236
216080
 
216237
216081
  // src/commands/doctor.ts
216238
- init_git();
216239
- var import_node_fs8 = require("node:fs");
216240
- var import_node_path8 = require("node:path");
216082
+ var import_node_fs7 = require("node:fs");
216083
+ var import_node_path7 = require("node:path");
216241
216084
  async function doctorCommand() {
216242
216085
  const checks = [];
216243
216086
  const apiKey = getApiKey();
@@ -216323,9 +216166,9 @@ async function doctorCommand() {
216323
216166
  } else {
216324
216167
  checks.push({ name: "Baseline", status: "warn", detail: "Skipped (no git remote)" });
216325
216168
  }
216326
- const agentsPath = (0, import_node_path8.resolve)(process.cwd(), "AGENTS.md");
216327
- if ((0, import_node_fs8.existsSync)(agentsPath)) {
216328
- const content = (0, import_node_fs8.readFileSync)(agentsPath, "utf-8");
216169
+ const agentsPath = (0, import_node_path7.resolve)(process.cwd(), "AGENTS.md");
216170
+ if ((0, import_node_fs7.existsSync)(agentsPath)) {
216171
+ const content = (0, import_node_fs7.readFileSync)(agentsPath, "utf-8");
216329
216172
  if (content.includes("driftless")) {
216330
216173
  checks.push({ name: "AGENTS.md", status: "ok", detail: "Driftless skill installed" });
216331
216174
  } else {
@@ -216381,7 +216224,7 @@ function pad2(s, n) {
216381
216224
  }
216382
216225
 
216383
216226
  // src/index.ts
216384
- var VERSION = "0.1.31";
216227
+ var VERSION = "0.1.33";
216385
216228
  var HELP_TEXT = `Driftless CLI v${VERSION} \u2014 Living repo context for humans and coding agents
216386
216229
 
216387
216230
  Install: npm install -g @driftless-sh/cli
@@ -216389,8 +216232,7 @@ Docs: https://driftless.icu/docs
216389
216232
  API: https://api.driftless.icu/api/v1
216390
216233
 
216391
216234
  Agent loop:
216392
- driftless session start Show context before editing
216393
- driftless session end Scan changes + context report
216235
+ driftless sync Load context + scan changes in one shot
216394
216236
  driftless context list List all context topics
216395
216237
  driftless context get <topic> Live view of one topic before editing
216396
216238
  driftless context get --diff What context matters for my local changes?
@@ -216405,9 +216247,9 @@ Setup:
216405
216247
  Commands:
216406
216248
  login Authenticate with API key
216407
216249
  init Smart init: scan \u2192 detect patterns \u2192 create topics + rules + anchor docs
216250
+ sync Load context for current changes + scan in one shot
216408
216251
  scan Evaluate staged + uncommitted changes against rules
216409
216252
  scan --diff Evaluate uncommitted changes only
216410
- session Agent session: start (context) \u2192 end (scan + report)
216411
216253
  context Live repo context (topics, search, anchors)
216412
216254
  install-skill Install AGENTS.md into current repo
216413
216255
  doctor Check environment health (auth, API, git, workspace, repo, baseline)
@@ -216429,10 +216271,6 @@ Context subcommands:
216429
216271
  delete <topic> Delete a topic
216430
216272
  load --files "p1,p2" Match topics by file paths
216431
216273
 
216432
- Session subcommands:
216433
- start [--files "p1,p2"] Show relevant context before editing
216434
- end Scan changes, check violations, suggest updates
216435
-
216436
216274
  Flags:
216437
216275
  --json Output as JSON (default is human-readable)
216438
216276
  --dry-run Preview changes without writing to Driftless Cloud
@@ -216450,8 +216288,8 @@ Output format:
216450
216288
  Use --json flag for machine-readable output (agents, CI).
216451
216289
 
216452
216290
  Examples:
216453
- driftless session start --files "src/auth/**"
216454
- driftless session end
216291
+ driftless sync # context + scan for current changes
216292
+ driftless sync --json # machine-readable output
216455
216293
 
216456
216294
  driftless context add "b2b-guard" \\
216457
216295
  --what "Guard que protege endpoints B2B" \\
@@ -216485,8 +216323,8 @@ Smart initialization \u2014 zero friction:
216485
216323
  3. Analyzes code patterns: guard enforcement, multi-tenant, large files, legacy
216486
216324
  4. Uploads baseline + components + relations to Cloud
216487
216325
  5. Creates specific rules from detected patterns (not generic ones)
216488
- 6. Creates context watchers for each detected module with smart gotchas
216489
- 7. Auto-anchors existing docs (AGENTS.md, ARCHITECTURE.md, docs/*.md)
216326
+ 6. Creates context topics for each detected module with smart gotchas
216327
+ 7. Detects existing docs (not auto-synced \u2014 ask your agent to sync them)
216490
216328
 
216491
216329
  Must be run from a git repository root.
216492
216330
 
@@ -216597,8 +216435,8 @@ async function main() {
216597
216435
  case "context":
216598
216436
  await contextCommand(args.slice(1));
216599
216437
  break;
216600
- case "session":
216601
- await sessionCommand(args.slice(1));
216438
+ case "sync":
216439
+ await syncCommand(args.slice(1));
216602
216440
  break;
216603
216441
  case "install-skill":
216604
216442
  await installSkillCommand();