@packmind/cli 0.16.1 → 0.17.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.
Files changed (2) hide show
  1. package/main.cjs +1808 -360
  2. package/package.json +2 -1
package/main.cjs CHANGED
@@ -234,9 +234,9 @@ var init_ansi_styles = __esm({
234
234
  });
235
235
 
236
236
  // node_modules/chalk/source/vendor/supports-color/index.js
237
- function hasFlag(flag4, argv = globalThis.Deno ? globalThis.Deno.args : import_node_process.default.argv) {
238
- const prefix = flag4.startsWith("-") ? "" : flag4.length === 1 ? "-" : "--";
239
- const position = argv.indexOf(prefix + flag4);
237
+ function hasFlag(flag5, argv = globalThis.Deno ? globalThis.Deno.args : import_node_process.default.argv) {
238
+ const prefix = flag5.startsWith("-") ? "" : flag5.length === 1 ? "-" : "--";
239
+ const position = argv.indexOf(prefix + flag5);
240
240
  const terminatorPosition = argv.indexOf("--");
241
241
  return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
242
242
  }
@@ -935,7 +935,7 @@ var require_flag = __commonJS({
935
935
  Object.defineProperty(exports2, "__esModule", { value: true });
936
936
  exports2.boolean = void 0;
937
937
  exports2.fullFlag = fullFlag;
938
- exports2.flag = flag4;
938
+ exports2.flag = flag5;
939
939
  var chalk_1 = __importDefault((init_source(), __toCommonJS(source_exports)));
940
940
  var Result = __importStar(require_Result());
941
941
  var findOption_1 = require_findOption();
@@ -1084,7 +1084,7 @@ var require_flag = __commonJS({
1084
1084
  }
1085
1085
  };
1086
1086
  }
1087
- function flag4(config) {
1087
+ function flag5(config) {
1088
1088
  return fullFlag({
1089
1089
  type: types_1.boolean,
1090
1090
  ...config
@@ -1698,12 +1698,12 @@ var require_command = __commonJS({
1698
1698
  return mod && mod.__esModule ? mod : { "default": mod };
1699
1699
  };
1700
1700
  Object.defineProperty(exports2, "__esModule", { value: true });
1701
- exports2.command = command20;
1701
+ exports2.command = command21;
1702
1702
  var chalk_1 = __importDefault((init_source(), __toCommonJS(source_exports)));
1703
1703
  var Result = __importStar(require_Result());
1704
1704
  var circuitbreaker_1 = require_circuitbreaker();
1705
1705
  var utils_1 = require_utils();
1706
- function command20(config) {
1706
+ function command21(config) {
1707
1707
  const argEntries = (0, utils_1.entries)(config.args);
1708
1708
  const circuitbreaker = (0, circuitbreaker_1.createCircuitBreaker)(!!config.version);
1709
1709
  return {
@@ -2574,9 +2574,9 @@ var require_browser = __commonJS({
2574
2574
  var require_has_flag = __commonJS({
2575
2575
  "node_modules/has-flag/index.js"(exports2, module2) {
2576
2576
  "use strict";
2577
- module2.exports = (flag4, argv = process.argv) => {
2578
- const prefix = flag4.startsWith("-") ? "" : flag4.length === 1 ? "-" : "--";
2579
- const position = argv.indexOf(prefix + flag4);
2577
+ module2.exports = (flag5, argv = process.argv) => {
2578
+ const prefix = flag5.startsWith("-") ? "" : flag5.length === 1 ? "-" : "--";
2579
+ const position = argv.indexOf(prefix + flag5);
2580
2580
  const terminatorPosition = argv.indexOf("--");
2581
2581
  return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
2582
2582
  };
@@ -3852,7 +3852,7 @@ var require_package = __commonJS({
3852
3852
  "apps/cli/package.json"(exports2, module2) {
3853
3853
  module2.exports = {
3854
3854
  name: "@packmind/cli",
3855
- version: "0.16.1",
3855
+ version: "0.17.0",
3856
3856
  description: "A command-line interface for Packmind linting and code quality checks",
3857
3857
  private: false,
3858
3858
  bin: {
@@ -3895,7 +3895,7 @@ var require_package = __commonJS({
3895
3895
  });
3896
3896
 
3897
3897
  // apps/cli/src/main.ts
3898
- var import_cmd_ts26 = __toESM(require_cjs());
3898
+ var import_cmd_ts27 = __toESM(require_cjs());
3899
3899
 
3900
3900
  // apps/cli/src/infra/commands/LinterCommand.ts
3901
3901
  var import_cmd_ts = __toESM(require_cjs());
@@ -4059,6 +4059,13 @@ var OrganizationCreatedEvent = class extends UserEvent {
4059
4059
  }
4060
4060
  };
4061
4061
 
4062
+ // packages/types/src/accounts/events/UserSignedInEvent.ts
4063
+ var UserSignedInEvent = class extends UserEvent {
4064
+ static {
4065
+ this.eventName = "accounts.user.signed-in";
4066
+ }
4067
+ };
4068
+
4062
4069
  // packages/types/src/accounts/TrialActivationToken.ts
4063
4070
  var createTrialActivationTokenId = brandedIdFactory();
4064
4071
  var createTrialActivationToken = brandedIdFactory();
@@ -4969,6 +4976,29 @@ var createAIProviderId = brandedIdFactory();
4969
4976
  // packages/types/src/playbookChangeManagement/ChangeProposalId.ts
4970
4977
  var createChangeProposalId = brandedIdFactory();
4971
4978
 
4979
+ // packages/types/src/playbookChangeManagement/ChangeProposalTypeLabels.ts
4980
+ var CHANGE_PROPOSAL_TYPE_LABELS = {
4981
+ ["updateCommandName" /* updateCommandName */]: "Name",
4982
+ ["updateCommandDescription" /* updateCommandDescription */]: "Instructions updated",
4983
+ ["updateStandardName" /* updateStandardName */]: "Name",
4984
+ ["updateStandardDescription" /* updateStandardDescription */]: "Description",
4985
+ ["updateStandardScope" /* updateStandardScope */]: "Scope",
4986
+ ["addRule" /* addRule */]: "Rule (add)",
4987
+ ["updateRule" /* updateRule */]: "Rule (update)",
4988
+ ["deleteRule" /* deleteRule */]: "Rule (delete)",
4989
+ ["updateSkillName" /* updateSkillName */]: "Name",
4990
+ ["updateSkillDescription" /* updateSkillDescription */]: "Description",
4991
+ ["updateSkillPrompt" /* updateSkillPrompt */]: "Prompt",
4992
+ ["updateSkillMetadata" /* updateSkillMetadata */]: "Metadata",
4993
+ ["updateSkillLicense" /* updateSkillLicense */]: "License",
4994
+ ["updateSkillCompatibility" /* updateSkillCompatibility */]: "Compatibility",
4995
+ ["updateSkillAllowedTools" /* updateSkillAllowedTools */]: "Allowed Tools",
4996
+ ["addSkillFile" /* addSkillFile */]: "File (add)",
4997
+ ["updateSkillFileContent" /* updateSkillFileContent */]: "File content",
4998
+ ["updateSkillFilePermissions" /* updateSkillFilePermissions */]: "File permissions",
4999
+ ["deleteSkillFile" /* deleteSkillFile */]: "File (delete)"
5000
+ };
5001
+
4972
5002
  // apps/cli/src/application/useCases/ExecuteSingleFileAstUseCase.ts
4973
5003
  var ExecuteSingleFileAstUseCase = class _ExecuteSingleFileAstUseCase {
4974
5004
  constructor(linterExecutionUseCase) {
@@ -4980,8 +5010,8 @@ var ExecuteSingleFileAstUseCase = class _ExecuteSingleFileAstUseCase {
4980
5010
  static {
4981
5011
  this.fallbackRuleContent = "adhoc-rule";
4982
5012
  }
4983
- async execute(command20) {
4984
- const { program, fileContent, language } = command20;
5013
+ async execute(command21) {
5014
+ const { program, fileContent, language } = command21;
4985
5015
  const result = await this.linterExecutionUseCase.execute({
4986
5016
  filePath: "cli-single-file",
4987
5017
  fileContent,
@@ -4992,7 +5022,8 @@ var ExecuteSingleFileAstUseCase = class _ExecuteSingleFileAstUseCase {
4992
5022
  ruleContent: _ExecuteSingleFileAstUseCase.fallbackRuleContent,
4993
5023
  standardSlug: _ExecuteSingleFileAstUseCase.fallbackStandardSlug,
4994
5024
  sourceCodeState: "AST",
4995
- language
5025
+ language,
5026
+ severity: "error" /* ERROR */
4996
5027
  }
4997
5028
  ]
4998
5029
  });
@@ -5031,30 +5062,30 @@ var GitService = class {
5031
5062
  this.gitRunner = gitRunner;
5032
5063
  this.logger = logger2;
5033
5064
  }
5034
- getGitRepositoryRoot(path14) {
5065
+ getGitRepositoryRoot(path18) {
5035
5066
  try {
5036
5067
  const { stdout } = this.gitRunner("rev-parse --show-toplevel", {
5037
- cwd: path14
5068
+ cwd: path18
5038
5069
  });
5039
5070
  const gitRoot = stdout.trim();
5040
5071
  this.logger.debug("Resolved git repository root", {
5041
- inputPath: path14,
5072
+ inputPath: path18,
5042
5073
  gitRoot
5043
5074
  });
5044
5075
  return gitRoot;
5045
5076
  } catch (error) {
5046
5077
  if (error instanceof Error) {
5047
5078
  throw new Error(
5048
- `Failed to get Git repository root. The path '${path14}' does not appear to be inside a Git repository.
5079
+ `Failed to get Git repository root. The path '${path18}' does not appear to be inside a Git repository.
5049
5080
  ${error.message}`
5050
5081
  );
5051
5082
  }
5052
5083
  throw new Error("Failed to get Git repository root: Unknown error");
5053
5084
  }
5054
5085
  }
5055
- tryGetGitRepositoryRoot(path14) {
5086
+ tryGetGitRepositoryRoot(path18) {
5056
5087
  try {
5057
- return this.getGitRepositoryRoot(path14);
5088
+ return this.getGitRepositoryRoot(path18);
5058
5089
  } catch {
5059
5090
  return null;
5060
5091
  }
@@ -5361,8 +5392,8 @@ var GetGitRemoteUrlUseCase = class {
5361
5392
  constructor(gitRemoteUrlService = new GitService()) {
5362
5393
  this.gitRemoteUrlService = gitRemoteUrlService;
5363
5394
  }
5364
- async execute(command20) {
5365
- const { path: repoPath, origin: origin9 } = command20;
5395
+ async execute(command21) {
5396
+ const { path: repoPath, origin: origin9 } = command21;
5366
5397
  return this.gitRemoteUrlService.getGitRemoteUrl(repoPath, origin9);
5367
5398
  }
5368
5399
  };
@@ -5398,6 +5429,9 @@ function formatLabel(text) {
5398
5429
  function formatError(text) {
5399
5430
  return source_default.red(text);
5400
5431
  }
5432
+ function formatWarning(text) {
5433
+ return source_default.yellow(text);
5434
+ }
5401
5435
  function formatBold(text) {
5402
5436
  return source_default.bold(text);
5403
5437
  }
@@ -5504,8 +5538,8 @@ var ListFilesInDirectoryUseCase = class {
5504
5538
  constructor(listFiles = new ListFiles()) {
5505
5539
  this.listFiles = listFiles;
5506
5540
  }
5507
- async execute(command20) {
5508
- const { path: directoryPath, extensions, excludes = [] } = command20;
5541
+ async execute(command21) {
5542
+ const { path: directoryPath, extensions, excludes = [] } = command21;
5509
5543
  const files = await this.listFiles.listFilesInDirectory(
5510
5544
  directoryPath,
5511
5545
  extensions,
@@ -5552,6 +5586,17 @@ var LintFilesAgainstRuleUseCase = class {
5552
5586
  this.services = services;
5553
5587
  this.repositories = repositories;
5554
5588
  this.logger = logger2;
5589
+ this.mapToActiveDetectionProgram = (item, fallbackLanguage) => {
5590
+ return {
5591
+ language: item.language ?? fallbackLanguage,
5592
+ severity: item.severity,
5593
+ detectionProgram: {
5594
+ mode: item.mode,
5595
+ code: item.code,
5596
+ sourceCodeState: item.sourceCodeState
5597
+ }
5598
+ };
5599
+ };
5555
5600
  }
5556
5601
  fileMatchesTargetAndScope(filePath, targetPath, scopePatterns) {
5557
5602
  if (!scopePatterns || scopePatterns.length === 0) {
@@ -5599,7 +5644,7 @@ var LintFilesAgainstRuleUseCase = class {
5599
5644
  }
5600
5645
  return pattern;
5601
5646
  }
5602
- async execute(command20) {
5647
+ async execute(command21) {
5603
5648
  const {
5604
5649
  path: userPath,
5605
5650
  draftMode,
@@ -5607,7 +5652,7 @@ var LintFilesAgainstRuleUseCase = class {
5607
5652
  ruleId,
5608
5653
  language,
5609
5654
  diffMode
5610
- } = command20;
5655
+ } = command21;
5611
5656
  this.logger.debug(
5612
5657
  `Starting linting: path="${userPath}", draftMode=${!!draftMode}, standardSlug="${standardSlug || "N/A"}", ruleId="${ruleId || "N/A"}", language="${language || "N/A"}", diffMode="${diffMode ?? "none"}"`
5613
5658
  );
@@ -5715,14 +5760,7 @@ var LintFilesAgainstRuleUseCase = class {
5715
5760
  {
5716
5761
  content: draftProgramsResult.ruleContent || "Draft Rule",
5717
5762
  activeDetectionPrograms: draftProgramsResult.programs.map(
5718
- (program) => ({
5719
- language: program.language,
5720
- detectionProgram: {
5721
- mode: program.mode,
5722
- code: program.code,
5723
- sourceCodeState: program.sourceCodeState
5724
- }
5725
- })
5763
+ (item) => this.mapToActiveDetectionProgram(item, language)
5726
5764
  )
5727
5765
  }
5728
5766
  ]
@@ -5759,14 +5797,7 @@ var LintFilesAgainstRuleUseCase = class {
5759
5797
  {
5760
5798
  content: activeProgramsResult.ruleContent || "Active Rule",
5761
5799
  activeDetectionPrograms: activeProgramsResult.programs.map(
5762
- (program) => ({
5763
- language: program.language,
5764
- detectionProgram: {
5765
- mode: program.mode,
5766
- code: program.code,
5767
- sourceCodeState: program.sourceCodeState
5768
- }
5769
- })
5800
+ (item) => this.mapToActiveDetectionProgram(item, language)
5770
5801
  )
5771
5802
  }
5772
5803
  ]
@@ -5842,7 +5873,8 @@ var LintFilesAgainstRuleUseCase = class {
5842
5873
  ruleContent: rule.content,
5843
5874
  standardSlug: standard.slug,
5844
5875
  sourceCodeState: activeProgram.detectionProgram.sourceCodeState,
5845
- language: fileLanguage
5876
+ language: fileLanguage,
5877
+ severity: activeProgram.severity ?? "error" /* ERROR */
5846
5878
  });
5847
5879
  programsByLanguage.set(programLanguage, programsForLanguage);
5848
5880
  } catch (error) {
@@ -5925,8 +5957,8 @@ var LintFilesAgainstRuleUseCase = class {
5925
5957
  return null;
5926
5958
  }
5927
5959
  }
5928
- async executeProgramsForFile(command20) {
5929
- const result = await this.services.linterExecutionUseCase.execute(command20);
5960
+ async executeProgramsForFile(command21) {
5961
+ const result = await this.services.linterExecutionUseCase.execute(command21);
5930
5962
  return result.violations;
5931
5963
  }
5932
5964
  extractExtensionFromFile(filePath) {
@@ -5983,8 +6015,8 @@ var LintFilesFromConfigUseCase = class {
5983
6015
  }
5984
6016
  return pattern;
5985
6017
  }
5986
- async execute(command20) {
5987
- const { path: userPath, diffMode } = command20;
6018
+ async execute(command21) {
6019
+ const { path: userPath, diffMode } = command21;
5988
6020
  this.logger.debug(
5989
6021
  `Starting local linting: path="${userPath}", diffMode="${diffMode ?? "none"}"`
5990
6022
  );
@@ -6088,6 +6120,7 @@ var LintFilesFromConfigUseCase = class {
6088
6120
  allConfigs.configs
6089
6121
  );
6090
6122
  const programsByLanguage = /* @__PURE__ */ new Map();
6123
+ const seenPrograms = /* @__PURE__ */ new Set();
6091
6124
  for (const targetConfig of matchingTargets) {
6092
6125
  const detectionPrograms = await this.getDetectionProgramsForTarget(targetConfig);
6093
6126
  for (const target of detectionPrograms.targets) {
@@ -6109,13 +6142,19 @@ var LintFilesFromConfigUseCase = class {
6109
6142
  if (!programLanguage || programLanguage !== fileLanguage) {
6110
6143
  continue;
6111
6144
  }
6145
+ const programKey = `${standard.slug}:${rule.content}:${activeProgram.language}`;
6146
+ if (seenPrograms.has(programKey)) {
6147
+ continue;
6148
+ }
6149
+ seenPrograms.add(programKey);
6112
6150
  const programsForLanguage = programsByLanguage.get(programLanguage) ?? [];
6113
6151
  programsForLanguage.push({
6114
6152
  code: activeProgram.detectionProgram.code,
6115
6153
  ruleContent: rule.content,
6116
6154
  standardSlug: standard.slug,
6117
6155
  sourceCodeState: activeProgram.detectionProgram.sourceCodeState,
6118
- language: fileLanguage
6156
+ language: fileLanguage,
6157
+ severity: activeProgram.severity ?? "error" /* ERROR */
6119
6158
  });
6120
6159
  programsByLanguage.set(programLanguage, programsForLanguage);
6121
6160
  } catch (error) {
@@ -6233,8 +6272,8 @@ var LintFilesFromConfigUseCase = class {
6233
6272
  return null;
6234
6273
  }
6235
6274
  }
6236
- async executeProgramsForFile(command20) {
6237
- const result = await this.services.linterExecutionUseCase.execute(command20);
6275
+ async executeProgramsForFile(command21) {
6276
+ const result = await this.services.linterExecutionUseCase.execute(command21);
6238
6277
  return result.violations;
6239
6278
  }
6240
6279
  extractExtensionFromFile(filePath) {
@@ -6300,10 +6339,10 @@ var PackmindHttpClient = class {
6300
6339
  return null;
6301
6340
  }
6302
6341
  }
6303
- async request(path14, options = {}) {
6342
+ async request(path18, options = {}) {
6304
6343
  const { host } = this.getAuthContext();
6305
6344
  const { method = "GET", body } = options;
6306
- const url = `${host}${path14}`;
6345
+ const url = `${host}${path18}`;
6307
6346
  try {
6308
6347
  const response = await fetch(url, {
6309
6348
  method,
@@ -6346,6 +6385,23 @@ var PackmindHttpClient = class {
6346
6385
  }
6347
6386
  };
6348
6387
 
6388
+ // apps/cli/src/infra/repositories/ChangeProposalGateway.ts
6389
+ var ChangeProposalGateway = class {
6390
+ constructor(httpClient) {
6391
+ this.httpClient = httpClient;
6392
+ this.batchCreate = async (command21) => {
6393
+ const { organizationId } = this.httpClient.getAuthContext();
6394
+ return this.httpClient.request(
6395
+ `/api/v0/organizations/${organizationId}/spaces/${command21.spaceId}/change-proposals/batch`,
6396
+ {
6397
+ method: "POST",
6398
+ body: { proposals: command21.proposals }
6399
+ }
6400
+ );
6401
+ };
6402
+ }
6403
+ };
6404
+
6349
6405
  // apps/cli/src/domain/errors/CommunityEditionError.ts
6350
6406
  var CommunityEditionError = class extends Error {
6351
6407
  constructor(feature) {
@@ -6360,13 +6416,13 @@ var CommunityEditionError = class extends Error {
6360
6416
  var LinterGateway = class {
6361
6417
  constructor(httpClient) {
6362
6418
  this.httpClient = httpClient;
6363
- this.getDraftDetectionProgramsForRule = async (command20) => {
6419
+ this.getDraftDetectionProgramsForRule = async (command21) => {
6364
6420
  const payload = {
6365
- standardSlug: command20.standardSlug,
6366
- ruleId: command20.ruleId
6421
+ standardSlug: command21.standardSlug,
6422
+ ruleId: command21.ruleId
6367
6423
  };
6368
- if (command20.language) {
6369
- payload.language = command20.language;
6424
+ if (command21.language) {
6425
+ payload.language = command21.language;
6370
6426
  }
6371
6427
  return this.httpClient.request("/api/v0/list-draft-detection-program", {
6372
6428
  method: "POST",
@@ -6378,13 +6434,13 @@ var LinterGateway = class {
6378
6434
  }
6379
6435
  });
6380
6436
  };
6381
- this.getActiveDetectionProgramsForRule = async (command20) => {
6437
+ this.getActiveDetectionProgramsForRule = async (command21) => {
6382
6438
  const payload = {
6383
- standardSlug: command20.standardSlug,
6384
- ruleId: command20.ruleId
6439
+ standardSlug: command21.standardSlug,
6440
+ ruleId: command21.ruleId
6385
6441
  };
6386
- if (command20.language) {
6387
- payload.language = command20.language;
6442
+ if (command21.language) {
6443
+ payload.language = command21.language;
6388
6444
  }
6389
6445
  return this.httpClient.request("/api/v0/list-active-detection-program", {
6390
6446
  method: "POST",
@@ -6396,13 +6452,13 @@ var LinterGateway = class {
6396
6452
  }
6397
6453
  });
6398
6454
  };
6399
- this.getDetectionProgramsForPackages = async (command20) => {
6455
+ this.getDetectionProgramsForPackages = async (command21) => {
6400
6456
  const response = await this.httpClient.request(
6401
6457
  "/api/v0/detection-programs-for-packages",
6402
6458
  {
6403
6459
  method: "POST",
6404
6460
  body: {
6405
- packagesSlugs: command20.packagesSlugs
6461
+ packagesSlugs: command21.packagesSlugs
6406
6462
  },
6407
6463
  onError: (response2) => {
6408
6464
  if (response2.status === 404) {
@@ -6413,10 +6469,10 @@ var LinterGateway = class {
6413
6469
  );
6414
6470
  return handleScopeInTargetsResponse(response);
6415
6471
  };
6416
- this.trackLinterExecution = async (command20) => {
6472
+ this.trackLinterExecution = async (command21) => {
6417
6473
  return this.httpClient.request(`/api/v0/track-execution`, {
6418
6474
  method: "POST",
6419
- body: command20
6475
+ body: command21
6420
6476
  });
6421
6477
  };
6422
6478
  }
@@ -6474,27 +6530,27 @@ var SpacesGateway = class {
6474
6530
  var SkillsGateway = class {
6475
6531
  constructor(httpClient) {
6476
6532
  this.httpClient = httpClient;
6477
- this.upload = async (command20) => {
6533
+ this.upload = async (command21) => {
6478
6534
  const { organizationId } = this.httpClient.getAuthContext();
6479
6535
  return this.httpClient.request(
6480
- `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/skills/upload`,
6536
+ `/api/v0/organizations/${organizationId}/spaces/${command21.spaceId}/skills/upload`,
6481
6537
  {
6482
6538
  method: "POST",
6483
- body: command20
6539
+ body: command21
6484
6540
  }
6485
6541
  );
6486
6542
  };
6487
- this.getDefaults = async (command20) => {
6543
+ this.getDefaults = async (command21) => {
6488
6544
  const { organizationId } = this.httpClient.getAuthContext();
6489
6545
  const queryParams = new URLSearchParams();
6490
- if (command20.includeBeta) {
6546
+ if (command21.includeBeta) {
6491
6547
  queryParams.set("includeBeta", "true");
6492
- } else if (command20.cliVersion) {
6493
- queryParams.set("cliVersion", command20.cliVersion);
6548
+ } else if (command21.cliVersion) {
6549
+ queryParams.set("cliVersion", command21.cliVersion);
6494
6550
  }
6495
- if (command20.agents !== void 0) {
6551
+ if (command21.agents !== void 0) {
6496
6552
  queryParams.append("agentsConfigOverride", "true");
6497
- command20.agents.forEach((agent) => {
6553
+ command21.agents.forEach((agent) => {
6498
6554
  queryParams.append("agent", agent);
6499
6555
  });
6500
6556
  }
@@ -6503,10 +6559,10 @@ var SkillsGateway = class {
6503
6559
  `/api/v0/organizations/${organizationId}/skills/default${queryString ? `?${queryString}` : ""}`
6504
6560
  );
6505
6561
  };
6506
- this.list = async (command20) => {
6562
+ this.list = async (command21) => {
6507
6563
  const { organizationId } = this.httpClient.getAuthContext();
6508
6564
  return this.httpClient.request(
6509
- `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/skills`
6565
+ `/api/v0/organizations/${organizationId}/spaces/${command21.spaceId}/skills`
6510
6566
  );
6511
6567
  };
6512
6568
  }
@@ -6516,17 +6572,17 @@ var SkillsGateway = class {
6516
6572
  var CommandsGateway = class {
6517
6573
  constructor(httpClient) {
6518
6574
  this.httpClient = httpClient;
6519
- this.create = async (command20) => {
6575
+ this.create = async (command21) => {
6520
6576
  const { organizationId } = this.httpClient.getAuthContext();
6521
6577
  return this.httpClient.request(
6522
- `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/recipes`,
6523
- { method: "POST", body: command20 }
6578
+ `/api/v0/organizations/${organizationId}/spaces/${command21.spaceId}/recipes`,
6579
+ { method: "POST", body: command21 }
6524
6580
  );
6525
6581
  };
6526
- this.list = async (command20) => {
6582
+ this.list = async (command21) => {
6527
6583
  const { organizationId } = this.httpClient.getAuthContext();
6528
6584
  const listRecipesResponse = await this.httpClient.request(
6529
- `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/recipes`
6585
+ `/api/v0/organizations/${organizationId}/spaces/${command21.spaceId}/recipes`
6530
6586
  );
6531
6587
  if (listRecipesResponse instanceof Array) {
6532
6588
  return { recipes: listRecipesResponse };
@@ -6568,10 +6624,10 @@ var StandardsGateway = class {
6568
6624
  }
6569
6625
  );
6570
6626
  };
6571
- this.list = async (command20) => {
6627
+ this.list = async (command21) => {
6572
6628
  const { organizationId } = this.httpClient.getAuthContext();
6573
6629
  return this.httpClient.request(
6574
- `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/standards`
6630
+ `/api/v0/organizations/${organizationId}/spaces/${command21.spaceId}/standards`
6575
6631
  );
6576
6632
  };
6577
6633
  }
@@ -6594,24 +6650,24 @@ var PackagesGateway = class {
6594
6650
  `/api/v0/organizations/${organizationId}/packages/${encodeURIComponent(slug)}`
6595
6651
  );
6596
6652
  };
6597
- this.create = async (command20) => {
6653
+ this.create = async (command21) => {
6598
6654
  const { organizationId } = this.httpClient.getAuthContext();
6599
6655
  return this.httpClient.request(
6600
- `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/packages`,
6656
+ `/api/v0/organizations/${organizationId}/spaces/${command21.spaceId}/packages`,
6601
6657
  {
6602
6658
  method: "POST",
6603
- body: command20
6659
+ body: command21
6604
6660
  }
6605
6661
  );
6606
6662
  };
6607
- this.addArtefacts = async (command20) => {
6663
+ this.addArtefacts = async (command21) => {
6608
6664
  const { organizationId } = this.httpClient.getAuthContext();
6609
- const { packageId, spaceId } = command20;
6665
+ const { packageId, spaceId } = command21;
6610
6666
  return this.httpClient.request(
6611
6667
  `/api/v0/organizations/${organizationId}/spaces/${spaceId}/packages/${packageId}/add-artifacts`,
6612
6668
  {
6613
6669
  method: "POST",
6614
- body: command20
6670
+ body: command21
6615
6671
  }
6616
6672
  );
6617
6673
  };
@@ -6622,31 +6678,31 @@ var PackagesGateway = class {
6622
6678
  var DeploymentGateway = class {
6623
6679
  constructor(httpClient) {
6624
6680
  this.httpClient = httpClient;
6625
- this.pull = async (command20) => {
6681
+ this.pull = async (command21) => {
6626
6682
  const { organizationId } = this.httpClient.getAuthContext();
6627
6683
  const queryParams = new URLSearchParams();
6628
- if (command20.packagesSlugs && command20.packagesSlugs.length > 0) {
6629
- command20.packagesSlugs.forEach((slug) => {
6684
+ if (command21.packagesSlugs && command21.packagesSlugs.length > 0) {
6685
+ command21.packagesSlugs.forEach((slug) => {
6630
6686
  queryParams.append("packageSlug", slug);
6631
6687
  });
6632
6688
  }
6633
- if (command20.previousPackagesSlugs && command20.previousPackagesSlugs.length > 0) {
6634
- command20.previousPackagesSlugs.forEach((slug) => {
6689
+ if (command21.previousPackagesSlugs && command21.previousPackagesSlugs.length > 0) {
6690
+ command21.previousPackagesSlugs.forEach((slug) => {
6635
6691
  queryParams.append("previousPackageSlug", slug);
6636
6692
  });
6637
6693
  }
6638
- if (command20.gitRemoteUrl) {
6639
- queryParams.append("gitRemoteUrl", command20.gitRemoteUrl);
6694
+ if (command21.gitRemoteUrl) {
6695
+ queryParams.append("gitRemoteUrl", command21.gitRemoteUrl);
6640
6696
  }
6641
- if (command20.gitBranch) {
6642
- queryParams.append("gitBranch", command20.gitBranch);
6697
+ if (command21.gitBranch) {
6698
+ queryParams.append("gitBranch", command21.gitBranch);
6643
6699
  }
6644
- if (command20.relativePath) {
6645
- queryParams.append("relativePath", command20.relativePath);
6700
+ if (command21.relativePath) {
6701
+ queryParams.append("relativePath", command21.relativePath);
6646
6702
  }
6647
- if (command20.agents !== void 0) {
6703
+ if (command21.agents !== void 0) {
6648
6704
  queryParams.append("agentsConfigOverride", "true");
6649
- command20.agents.forEach((agent) => {
6705
+ command21.agents.forEach((agent) => {
6650
6706
  queryParams.append("agent", agent);
6651
6707
  });
6652
6708
  }
@@ -6654,13 +6710,29 @@ var DeploymentGateway = class {
6654
6710
  `/api/v0/organizations/${organizationId}/pull?${queryParams.toString()}`
6655
6711
  );
6656
6712
  };
6657
- this.notifyDistribution = async (command20) => {
6713
+ this.getDeployed = async (command21) => {
6714
+ const { organizationId } = this.httpClient.getAuthContext();
6715
+ return this.httpClient.request(
6716
+ `/api/v0/organizations/${organizationId}/deployed-content`,
6717
+ {
6718
+ method: "POST",
6719
+ body: {
6720
+ packagesSlugs: command21.packagesSlugs,
6721
+ gitRemoteUrl: command21.gitRemoteUrl,
6722
+ gitBranch: command21.gitBranch,
6723
+ relativePath: command21.relativePath,
6724
+ ...command21.agents !== void 0 && { agents: command21.agents }
6725
+ }
6726
+ }
6727
+ );
6728
+ };
6729
+ this.notifyDistribution = async (command21) => {
6658
6730
  const { organizationId } = this.httpClient.getAuthContext();
6659
6731
  return this.httpClient.request(
6660
6732
  `/api/v0/organizations/${organizationId}/deployments`,
6661
6733
  {
6662
6734
  method: "POST",
6663
- body: command20
6735
+ body: command21
6664
6736
  }
6665
6737
  );
6666
6738
  };
@@ -6678,6 +6750,7 @@ var PackmindGateway = class {
6678
6750
  constructor(apiKey) {
6679
6751
  this.apiKey = apiKey;
6680
6752
  this.httpClient = new PackmindHttpClient(apiKey);
6753
+ this.changeProposals = new ChangeProposalGateway(this.httpClient);
6681
6754
  this.linter = new LinterGateway(this.httpClient);
6682
6755
  this.mcp = new McpGateway(this.httpClient);
6683
6756
  this.spaces = new SpacesGateway(this.httpClient);
@@ -8429,8 +8502,8 @@ var ExecuteLinterProgramsUseCase = class {
8429
8502
  this.linterAstAdapter = linterAstAdapter;
8430
8503
  this.logger = logger2;
8431
8504
  }
8432
- async execute(command20) {
8433
- const { filePath, fileContent, language, programs } = command20;
8505
+ async execute(command21) {
8506
+ const { filePath, fileContent, language, programs } = command21;
8434
8507
  if (programs.length === 0) {
8435
8508
  return {
8436
8509
  file: filePath,
@@ -8573,7 +8646,8 @@ var ExecuteLinterProgramsUseCase = class {
8573
8646
  line,
8574
8647
  character,
8575
8648
  rule: ruleName,
8576
- standard: program.standardSlug
8649
+ standard: program.standardSlug,
8650
+ severity: program.severity
8577
8651
  };
8578
8652
  }
8579
8653
  isViolationLike(value) {
@@ -9100,15 +9174,114 @@ function removeTrailingSlash(url) {
9100
9174
  return url.endsWith("/") ? url.slice(0, -1) : url;
9101
9175
  }
9102
9176
 
9177
+ // packages/node-utils/src/skillMd/parseSkillMdContent.ts
9178
+ var import_yaml = require("yaml");
9179
+ var FRONTMATTER_DELIMITER = "---";
9180
+ function serializeSkillMetadata(fields) {
9181
+ const sorted = Object.keys(fields).sort((a, b) => a.localeCompare(b)).reduce(
9182
+ (acc, key) => {
9183
+ acc[key] = fields[key];
9184
+ return acc;
9185
+ },
9186
+ {}
9187
+ );
9188
+ return JSON.stringify(sorted);
9189
+ }
9190
+ function parseSkillMdContent(content) {
9191
+ try {
9192
+ const trimmed = content.trim();
9193
+ if (!trimmed.startsWith(FRONTMATTER_DELIMITER)) {
9194
+ return null;
9195
+ }
9196
+ const afterOpening = trimmed.slice(FRONTMATTER_DELIMITER.length);
9197
+ const closingIndex = afterOpening.indexOf(`
9198
+ ${FRONTMATTER_DELIMITER}`);
9199
+ if (closingIndex === -1) {
9200
+ return null;
9201
+ }
9202
+ const frontmatter = afterOpening.slice(0, closingIndex).trim();
9203
+ const body = afterOpening.slice(closingIndex + FRONTMATTER_DELIMITER.length + 1).trim();
9204
+ const parsed = (0, import_yaml.parse)(frontmatter);
9205
+ if (parsed === null || typeof parsed !== "object") {
9206
+ return null;
9207
+ }
9208
+ const { "allowed-tools": allowedTools, ...rest } = parsed;
9209
+ const properties = {
9210
+ ...rest,
9211
+ ...allowedTools !== void 0 && { allowedTools }
9212
+ };
9213
+ return { properties, body };
9214
+ } catch {
9215
+ return null;
9216
+ }
9217
+ }
9218
+
9219
+ // packages/node-utils/src/skillMd/parseSkillMd.ts
9220
+ function parseSkillMd(content) {
9221
+ const parsed = parseSkillMdContent(content);
9222
+ if (!parsed) {
9223
+ return null;
9224
+ }
9225
+ const { properties, body } = parsed;
9226
+ const name = String(properties["name"] ?? "");
9227
+ const description = String(properties["description"] ?? "");
9228
+ const license = String(properties["license"] ?? "");
9229
+ const compatibility = String(properties["compatibility"] ?? "");
9230
+ const allowedTools = String(properties["allowedTools"] ?? "");
9231
+ const metadata = properties["metadata"];
9232
+ const metadataJson = metadata != null && typeof metadata === "object" ? serializeSkillMetadata(metadata) : "{}";
9233
+ return {
9234
+ name,
9235
+ description,
9236
+ body,
9237
+ license,
9238
+ compatibility,
9239
+ allowedTools,
9240
+ metadataJson
9241
+ };
9242
+ }
9243
+
9103
9244
  // apps/cli/src/application/useCases/InstallPackagesUseCase.ts
9104
9245
  var fs4 = __toESM(require("fs/promises"));
9105
9246
  var path5 = __toESM(require("path"));
9247
+
9248
+ // apps/cli/src/infra/utils/permissions.ts
9249
+ var DEFAULT_PERMISSIONS = "rw-r--r--";
9250
+ function supportsUnixPermissions() {
9251
+ return process.platform !== "win32";
9252
+ }
9253
+ function modeToPermissionString(mode) {
9254
+ const perms = mode & 511;
9255
+ const chars = "rwx";
9256
+ let result = "";
9257
+ for (let i = 8; i >= 0; i--) {
9258
+ result += perms & 1 << i ? chars[(8 - i) % 3] : "-";
9259
+ }
9260
+ return result;
9261
+ }
9262
+ function modeToPermissionStringOrDefault(mode) {
9263
+ if (!supportsUnixPermissions()) {
9264
+ return DEFAULT_PERMISSIONS;
9265
+ }
9266
+ return modeToPermissionString(mode);
9267
+ }
9268
+ function parsePermissionString(permString) {
9269
+ let mode = 0;
9270
+ for (let i = 0; i < 9; i++) {
9271
+ if (permString[i] !== "-") {
9272
+ mode |= 1 << 8 - i;
9273
+ }
9274
+ }
9275
+ return mode;
9276
+ }
9277
+
9278
+ // apps/cli/src/application/useCases/InstallPackagesUseCase.ts
9106
9279
  var InstallPackagesUseCase = class {
9107
9280
  constructor(packmindGateway) {
9108
9281
  this.packmindGateway = packmindGateway;
9109
9282
  }
9110
- async execute(command20) {
9111
- const baseDirectory = command20.baseDirectory || process.cwd();
9283
+ async execute(command21) {
9284
+ const baseDirectory = command21.baseDirectory || process.cwd();
9112
9285
  const result = {
9113
9286
  filesCreated: 0,
9114
9287
  filesUpdated: 0,
@@ -9120,12 +9293,12 @@ var InstallPackagesUseCase = class {
9120
9293
  skillDirectoriesDeleted: 0
9121
9294
  };
9122
9295
  const response = await this.packmindGateway.deployment.pull({
9123
- packagesSlugs: command20.packagesSlugs,
9124
- previousPackagesSlugs: command20.previousPackagesSlugs,
9125
- gitRemoteUrl: command20.gitRemoteUrl,
9126
- gitBranch: command20.gitBranch,
9127
- relativePath: command20.relativePath,
9128
- agents: command20.agents
9296
+ packagesSlugs: command21.packagesSlugs,
9297
+ previousPackagesSlugs: command21.previousPackagesSlugs,
9298
+ gitRemoteUrl: command21.gitRemoteUrl,
9299
+ gitBranch: command21.gitBranch,
9300
+ relativePath: command21.relativePath,
9301
+ agents: command21.agents
9129
9302
  });
9130
9303
  const filteredCreateOrUpdate = response.fileUpdates.createOrUpdate.filter(
9131
9304
  (file) => file.path !== "packmind.json"
@@ -9151,7 +9324,12 @@ var InstallPackagesUseCase = class {
9151
9324
  );
9152
9325
  for (const file of uniqueFiles) {
9153
9326
  try {
9154
- await this.createOrUpdateFile(baseDirectory, file, result);
9327
+ await this.createOrUpdateFile(
9328
+ baseDirectory,
9329
+ file,
9330
+ result,
9331
+ file.skillFilePermissions
9332
+ );
9155
9333
  } catch (error) {
9156
9334
  const errorMsg = error instanceof Error ? error.message : String(error);
9157
9335
  result.errors.push(
@@ -9173,7 +9351,7 @@ var InstallPackagesUseCase = class {
9173
9351
  }
9174
9352
  return result;
9175
9353
  }
9176
- async createOrUpdateFile(baseDirectory, file, result) {
9354
+ async createOrUpdateFile(baseDirectory, file, result, skillFilePermissions) {
9177
9355
  const fullPath = path5.join(baseDirectory, file.path);
9178
9356
  const directory = path5.dirname(fullPath);
9179
9357
  await fs4.mkdir(directory, { recursive: true });
@@ -9195,6 +9373,9 @@ var InstallPackagesUseCase = class {
9195
9373
  baseDirectory
9196
9374
  );
9197
9375
  }
9376
+ if (skillFilePermissions && supportsUnixPermissions()) {
9377
+ await fs4.chmod(fullPath, parsePermissionString(skillFilePermissions));
9378
+ }
9198
9379
  }
9199
9380
  async handleFullContentUpdate(fullPath, content, fileExists, result, isBase64) {
9200
9381
  if (isBase64) {
@@ -9255,12 +9436,12 @@ var InstallPackagesUseCase = class {
9255
9436
  }
9256
9437
  async deleteFile(baseDirectory, filePath, result) {
9257
9438
  const fullPath = path5.join(baseDirectory, filePath);
9258
- const stat4 = await fs4.stat(fullPath).catch(() => null);
9259
- if (stat4?.isDirectory()) {
9439
+ const stat5 = await fs4.stat(fullPath).catch(() => null);
9440
+ if (stat5?.isDirectory()) {
9260
9441
  await fs4.rm(fullPath, { recursive: true, force: true });
9261
9442
  result.filesDeleted++;
9262
9443
  await this.removeEmptyParentDirectories(fullPath, baseDirectory);
9263
- } else if (stat4?.isFile()) {
9444
+ } else if (stat5?.isFile()) {
9264
9445
  await fs4.unlink(fullPath);
9265
9446
  result.filesDeleted++;
9266
9447
  await this.removeEmptyParentDirectories(fullPath, baseDirectory);
@@ -9403,8 +9584,8 @@ var InstallDefaultSkillsUseCase = class {
9403
9584
  constructor(repositories) {
9404
9585
  this.repositories = repositories;
9405
9586
  }
9406
- async execute(command20) {
9407
- const baseDirectory = command20.baseDirectory || process.cwd();
9587
+ async execute(command21) {
9588
+ const baseDirectory = command21.baseDirectory || process.cwd();
9408
9589
  const result = {
9409
9590
  filesCreated: 0,
9410
9591
  filesUpdated: 0,
@@ -9414,8 +9595,8 @@ var InstallDefaultSkillsUseCase = class {
9414
9595
  const agents = config?.agents;
9415
9596
  const response = await this.repositories.packmindGateway.skills.getDefaults(
9416
9597
  {
9417
- cliVersion: command20.cliVersion,
9418
- includeBeta: command20.includeBeta,
9598
+ cliVersion: command21.cliVersion,
9599
+ includeBeta: command21.includeBeta,
9419
9600
  agents
9420
9601
  }
9421
9602
  );
@@ -9480,8 +9661,8 @@ var GetPackageSummaryUseCase = class {
9480
9661
  constructor(gateway) {
9481
9662
  this.gateway = gateway;
9482
9663
  }
9483
- async execute(command20) {
9484
- return this.gateway.packages.getSummary(command20);
9664
+ async execute(command21) {
9665
+ return this.gateway.packages.getSummary(command21);
9485
9666
  }
9486
9667
  };
9487
9668
 
@@ -9760,8 +9941,8 @@ var LoginUseCase = class {
9760
9941
  startCallbackServer: deps?.startCallbackServer ?? defaultStartCallbackServer
9761
9942
  };
9762
9943
  }
9763
- async execute(command20) {
9764
- const { host, code: providedCode } = command20;
9944
+ async execute(command21) {
9945
+ const { host, code: providedCode } = command21;
9765
9946
  let code;
9766
9947
  if (providedCode) {
9767
9948
  code = providedCode;
@@ -9799,8 +9980,8 @@ var LogoutUseCase = class {
9799
9980
  constructor(deps) {
9800
9981
  this.deps = {
9801
9982
  getCredentialsPath: deps?.getCredentialsPath ?? getCredentialsPath,
9802
- fileExists: deps?.fileExists ?? ((path14) => fs7.existsSync(path14)),
9803
- deleteFile: deps?.deleteFile ?? ((path14) => fs7.unlinkSync(path14)),
9983
+ fileExists: deps?.fileExists ?? ((path18) => fs7.existsSync(path18)),
9984
+ deleteFile: deps?.deleteFile ?? ((path18) => fs7.unlinkSync(path18)),
9804
9985
  hasEnvVar: deps?.hasEnvVar ?? (() => !!process.env[ENV_VAR_NAME2])
9805
9986
  };
9806
9987
  }
@@ -9860,8 +10041,8 @@ var SetupMcpUseCase = class {
9860
10041
  constructor(deps) {
9861
10042
  this.deps = deps;
9862
10043
  }
9863
- async execute(command20) {
9864
- const { agentTypes } = command20;
10044
+ async execute(command21) {
10045
+ const { agentTypes } = command21;
9865
10046
  const [tokenResult, urlResult] = await Promise.all([
9866
10047
  this.deps.gateway.mcp.getToken({}),
9867
10048
  this.deps.gateway.mcp.getUrl({})
@@ -9932,9 +10113,9 @@ var McpConfigService = class {
9932
10113
  return JSON.stringify(mcpConfig, null, 2);
9933
10114
  }
9934
10115
  installClaudeMcp(config) {
9935
- const command20 = `claude mcp add --transport http packmind ${config.url} --header "Authorization: Bearer ${config.accessToken}"`;
10116
+ const command21 = `claude mcp add --transport http packmind ${config.url} --header "Authorization: Bearer ${config.accessToken}"`;
9936
10117
  try {
9937
- (0, import_child_process2.execSync)(command20, { stdio: "pipe" });
10118
+ (0, import_child_process2.execSync)(command21, { stdio: "pipe" });
9938
10119
  return { success: true };
9939
10120
  } catch (error) {
9940
10121
  const execError = error;
@@ -10430,16 +10611,9 @@ var ListSkillsUseCase = class {
10430
10611
  var import_promises = __toESM(require("fs/promises"));
10431
10612
  var import_path2 = __toESM(require("path"));
10432
10613
  var import_minimatch3 = require("minimatch");
10433
- function normalizePath2(filePath) {
10434
- let normalized = filePath.replace(/\\/g, "/");
10435
- if (normalized.startsWith("/") || normalized.startsWith("\\")) {
10436
- normalized = normalized.substring(1);
10437
- }
10438
- return normalized;
10439
- }
10440
- function normalizeLineEndings(content) {
10441
- return content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
10442
- }
10614
+
10615
+ // apps/cli/src/infra/utils/binaryDetection.ts
10616
+ var path10 = __toESM(require("path"));
10443
10617
  var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
10444
10618
  // Images
10445
10619
  ".png",
@@ -10497,7 +10671,7 @@ var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
10497
10671
  ".sqlite3"
10498
10672
  ]);
10499
10673
  function isBinaryExtension(filePath) {
10500
- const ext = import_path2.default.extname(filePath).toLowerCase();
10674
+ const ext = path10.extname(filePath).toLowerCase();
10501
10675
  return BINARY_EXTENSIONS.has(ext);
10502
10676
  }
10503
10677
  function isBinaryBuffer(buffer) {
@@ -10506,6 +10680,18 @@ function isBinaryBuffer(buffer) {
10506
10680
  function isBinaryFile(filePath, buffer) {
10507
10681
  return isBinaryExtension(filePath) || isBinaryBuffer(buffer);
10508
10682
  }
10683
+
10684
+ // apps/cli/src/infra/utils/readSkillDirectory.ts
10685
+ function normalizePath2(filePath) {
10686
+ let normalized = filePath.replace(/\\/g, "/");
10687
+ if (normalized.startsWith("/") || normalized.startsWith("\\")) {
10688
+ normalized = normalized.substring(1);
10689
+ }
10690
+ return normalized;
10691
+ }
10692
+ function normalizeLineEndings(content) {
10693
+ return content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
10694
+ }
10509
10695
  var MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
10510
10696
  var MAX_FILE_SIZE_MB = 10;
10511
10697
  var BLACKLIST_PATTERNS = ["**/.DS_Store"];
@@ -10528,9 +10714,9 @@ async function readSkillDirectory(dirPath) {
10528
10714
  if (entry.isDirectory()) {
10529
10715
  await readDir(fullPath, basePath);
10530
10716
  } else if (entry.isFile()) {
10531
- const stat4 = await import_promises.default.stat(fullPath);
10532
- if (stat4.size > MAX_FILE_SIZE_BYTES) {
10533
- const fileSizeMB = (stat4.size / (1024 * 1024)).toFixed(2);
10717
+ const stat5 = await import_promises.default.stat(fullPath);
10718
+ if (stat5.size > MAX_FILE_SIZE_BYTES) {
10719
+ const fileSizeMB = (stat5.size / (1024 * 1024)).toFixed(2);
10534
10720
  throw new Error(
10535
10721
  `File "${relativePath}" is ${fileSizeMB} MB which exceeds the maximum allowed size of ${MAX_FILE_SIZE_MB} MB per file.`
10536
10722
  );
@@ -10549,8 +10735,7 @@ async function readSkillDirectory(dirPath) {
10549
10735
  relativePath: normalizedPath,
10550
10736
  content,
10551
10737
  size: Buffer.byteLength(content, isBinary ? "base64" : "utf-8"),
10552
- permissions: "rw-r--r--",
10553
- // Simple default
10738
+ permissions: modeToPermissionStringOrDefault(stat5.mode),
10554
10739
  isBase64: isBinary
10555
10740
  });
10556
10741
  }
@@ -10565,8 +10750,8 @@ var UploadSkillUseCase = class {
10565
10750
  constructor(deps) {
10566
10751
  this.deps = deps;
10567
10752
  }
10568
- async execute(command20) {
10569
- const files = await readSkillDirectory(command20.skillPath);
10753
+ async execute(command21) {
10754
+ const files = await readSkillDirectory(command21.skillPath);
10570
10755
  if (!files.find((f) => f.relativePath === "SKILL.md")) {
10571
10756
  throw new Error("SKILL.md not found in skill directory");
10572
10757
  }
@@ -10592,7 +10777,7 @@ var UploadSkillUseCase = class {
10592
10777
  const uploadSkillResponse = await this.deps.gateway.skills.upload({
10593
10778
  spaceId: createSpaceId(space.id),
10594
10779
  files: payload.files,
10595
- originSkill: command20.originSkill
10780
+ originSkill: command21.originSkill
10596
10781
  });
10597
10782
  return {
10598
10783
  skillId: uploadSkillResponse.skill.id,
@@ -10606,123 +10791,1007 @@ var UploadSkillUseCase = class {
10606
10791
  }
10607
10792
  };
10608
10793
 
10609
- // apps/cli/src/PackmindCliHexaFactory.ts
10610
- var PackmindCliHexaFactory = class {
10611
- constructor() {
10612
- this.repositories = {
10613
- packmindGateway: new PackmindGateway(loadApiKey()),
10614
- configFileRepository: new ConfigFileRepository()
10615
- };
10616
- this.services = {
10617
- listFiles: new ListFiles(),
10618
- gitRemoteUrlService: new GitService(),
10619
- linterExecutionUseCase: new ExecuteLinterProgramsUseCase(),
10620
- diffViolationFilterService: new DiffViolationFilterService()
10621
- };
10622
- this.useCases = {
10623
- executeSingleFileAst: new ExecuteSingleFileAstUseCase(
10624
- this.services.linterExecutionUseCase
10625
- ),
10626
- getGitRemoteUrl: new GetGitRemoteUrlUseCase(),
10627
- listFilesInDirectoryUseCase: new ListFilesInDirectoryUseCase(),
10628
- lintFilesAgainstRule: new LintFilesAgainstRuleUseCase(
10629
- this.services,
10630
- this.repositories
10631
- ),
10632
- lintFilesFromConfig: new LintFilesFromConfigUseCase(
10633
- this.services,
10634
- this.repositories
10635
- ),
10636
- installPackages: new InstallPackagesUseCase(
10637
- this.repositories.packmindGateway
10638
- ),
10639
- installDefaultSkills: new InstallDefaultSkillsUseCase(this.repositories),
10640
- listPackages: new ListPackagesUseCase(this.repositories.packmindGateway),
10641
- getPackageBySlug: new GetPackageSummaryUseCase(
10642
- this.repositories.packmindGateway
10643
- ),
10644
- login: new LoginUseCase(),
10645
- logout: new LogoutUseCase(),
10646
- whoami: new WhoamiUseCase(),
10647
- setupMcp: new SetupMcpUseCase({
10648
- gateway: this.repositories.packmindGateway,
10649
- mcpConfigService: new McpConfigService()
10650
- }),
10651
- listStandards: new ListStandardsUseCase(
10652
- this.repositories.packmindGateway
10653
- ),
10654
- listCommands: new ListCommandsUseCase(this.repositories.packmindGateway),
10655
- listSkills: new ListSkillsUseCase(this.repositories.packmindGateway),
10656
- uploadSkill: new UploadSkillUseCase({
10657
- gateway: this.repositories.packmindGateway
10658
- })
10659
- };
10794
+ // apps/cli/src/application/useCases/diffStrategies/CommandDiffStrategy.ts
10795
+ var import_diff = require("diff");
10796
+ var fs11 = __toESM(require("fs/promises"));
10797
+ var path12 = __toESM(require("path"));
10798
+
10799
+ // apps/cli/src/application/utils/stripFrontmatter.ts
10800
+ var FRONTMATTER_DELIMITER2 = "---";
10801
+ function stripFrontmatter(content) {
10802
+ if (!content.startsWith(`${FRONTMATTER_DELIMITER2}
10803
+ `)) {
10804
+ return content;
10805
+ }
10806
+ const contentAfterOpening = content.slice(FRONTMATTER_DELIMITER2.length + 1);
10807
+ const closingIndex = contentAfterOpening.indexOf(
10808
+ `
10809
+ ${FRONTMATTER_DELIMITER2}`
10810
+ );
10811
+ if (closingIndex === -1) {
10812
+ return content;
10660
10813
  }
10661
- };
10814
+ return contentAfterOpening.slice(closingIndex + FRONTMATTER_DELIMITER2.length + 1).trimStart();
10815
+ }
10662
10816
 
10663
- // apps/cli/src/PackmindCliHexa.ts
10664
- var origin8 = "PackmindCliHexa";
10665
- var PackmindCliHexa = class {
10666
- constructor(logger2 = new PackmindLogger(origin8)) {
10667
- this.notifyDistribution = async (command20) => {
10668
- return this.hexa.repositories.packmindGateway.deployment.notifyDistribution(
10669
- command20
10670
- );
10671
- };
10672
- this.logger = logger2;
10817
+ // apps/cli/src/application/useCases/diffStrategies/CommandDiffStrategy.ts
10818
+ var CommandDiffStrategy = class {
10819
+ supports(file) {
10820
+ return file.artifactType === "command";
10821
+ }
10822
+ async diff(file, baseDirectory) {
10823
+ const fullPath = path12.join(baseDirectory, file.path);
10824
+ let localContent;
10673
10825
  try {
10674
- this.hexa = new PackmindCliHexaFactory();
10675
- } catch (error) {
10676
- this.logger.error("Failed to initialize PackmindCliHexa", {
10677
- error: error instanceof Error ? error.message : String(error)
10678
- });
10679
- throw error;
10826
+ localContent = await fs11.readFile(fullPath, "utf-8");
10827
+ } catch {
10828
+ return [];
10680
10829
  }
10830
+ const serverBody = stripFrontmatter(file.content);
10831
+ const localBody = stripFrontmatter(localContent);
10832
+ const changes = (0, import_diff.diffLines)(serverBody, localBody);
10833
+ const hasDifferences = changes.some(
10834
+ (change) => change.added || change.removed
10835
+ );
10836
+ if (!hasDifferences) {
10837
+ return [];
10838
+ }
10839
+ return [
10840
+ {
10841
+ filePath: file.path,
10842
+ type: "updateCommandDescription" /* updateCommandDescription */,
10843
+ payload: {
10844
+ oldValue: serverBody,
10845
+ newValue: localBody
10846
+ },
10847
+ artifactName: file.artifactName,
10848
+ artifactType: file.artifactType,
10849
+ artifactId: file.artifactId,
10850
+ spaceId: file.spaceId
10851
+ }
10852
+ ];
10681
10853
  }
10682
- /**
10683
- * Destroys the DeploymentsHexa and cleans up resources
10684
- */
10685
- destroy() {
10686
- this.logger.info("Destroying PackmindCliHexa");
10687
- this.logger.info("PackmindCliHexa destroyed");
10688
- }
10689
- async getGitRemoteUrl(command20) {
10690
- return this.hexa.useCases.getGitRemoteUrl.execute(command20);
10854
+ };
10855
+
10856
+ // apps/cli/src/application/useCases/diffStrategies/SkillDiffStrategy.ts
10857
+ var import_diff2 = require("diff");
10858
+ var fs12 = __toESM(require("fs/promises"));
10859
+ var path13 = __toESM(require("path"));
10860
+ var SkillDiffStrategy = class {
10861
+ supports(file) {
10862
+ return file.artifactType === "skill";
10691
10863
  }
10692
- async executeSingleFileAst(command20) {
10693
- return this.hexa.useCases.executeSingleFileAst.execute(command20);
10864
+ async diff(file, baseDirectory, context) {
10865
+ if (file.path.endsWith("/SKILL.md")) {
10866
+ return this.diffSkillMd(file, baseDirectory);
10867
+ }
10868
+ return this.diffSkillFile(file, baseDirectory, context?.skillFolders ?? []);
10694
10869
  }
10695
- async listFilesInDirectory(command20) {
10696
- return this.hexa.useCases.listFilesInDirectoryUseCase.execute(command20);
10870
+ async diffNewFiles(skillFolders, serverFiles, baseDirectory) {
10871
+ const diffs = [];
10872
+ for (const folder of skillFolders) {
10873
+ const folderPath = path13.join(baseDirectory, folder);
10874
+ const localFiles = await this.listFilesRecursively(folderPath);
10875
+ const serverPathsInFolder = new Set(
10876
+ serverFiles.filter((f) => f.path.startsWith(folder + "/")).map((f) => f.path)
10877
+ );
10878
+ const skillMdFile = serverFiles.find(
10879
+ (f) => f.path === `${folder}/SKILL.md` && f.artifactType === "skill"
10880
+ );
10881
+ if (!skillMdFile) {
10882
+ continue;
10883
+ }
10884
+ for (const relativePath of localFiles) {
10885
+ if (relativePath === "SKILL.md") {
10886
+ continue;
10887
+ }
10888
+ const filePath = `${folder}/${relativePath}`;
10889
+ if (serverPathsInFolder.has(filePath)) {
10890
+ continue;
10891
+ }
10892
+ const fullPath = path13.join(baseDirectory, filePath);
10893
+ const localRead = await this.tryReadFileBinaryAware(fullPath);
10894
+ if (localRead === null) {
10895
+ continue;
10896
+ }
10897
+ const permissions = await this.tryGetPermissions(fullPath) ?? "rw-r--r--";
10898
+ diffs.push({
10899
+ filePath,
10900
+ type: "addSkillFile" /* addSkillFile */,
10901
+ payload: {
10902
+ item: {
10903
+ path: relativePath,
10904
+ content: localRead.content,
10905
+ permissions,
10906
+ isBase64: localRead.isBase64
10907
+ }
10908
+ },
10909
+ artifactName: skillMdFile.artifactName,
10910
+ artifactType: "skill",
10911
+ artifactId: skillMdFile.artifactId,
10912
+ spaceId: skillMdFile.spaceId
10913
+ });
10914
+ }
10915
+ }
10916
+ return diffs;
10697
10917
  }
10698
- async lintFilesAgainstRule(command20) {
10699
- return this.hexa.useCases.lintFilesAgainstRule.execute(command20);
10918
+ async diffSkillMd(file, baseDirectory) {
10919
+ const fullPath = path13.join(baseDirectory, file.path);
10920
+ const localContent = await this.tryReadFile(fullPath);
10921
+ if (localContent === null) {
10922
+ return [];
10923
+ }
10924
+ const serverParsed = parseSkillMd(file.content);
10925
+ const localParsed = parseSkillMd(localContent);
10926
+ if (!serverParsed || !localParsed) {
10927
+ const serverBody = stripFrontmatter(file.content);
10928
+ const localBody = stripFrontmatter(localContent);
10929
+ const changes = (0, import_diff2.diffLines)(serverBody, localBody);
10930
+ const hasDifferences = changes.some(
10931
+ (change) => change.added || change.removed
10932
+ );
10933
+ if (!hasDifferences) {
10934
+ return [];
10935
+ }
10936
+ return [
10937
+ {
10938
+ filePath: file.path,
10939
+ type: "updateSkillPrompt" /* updateSkillPrompt */,
10940
+ payload: { oldValue: serverBody, newValue: localBody },
10941
+ artifactName: file.artifactName,
10942
+ artifactType: file.artifactType,
10943
+ artifactId: file.artifactId,
10944
+ spaceId: file.spaceId
10945
+ }
10946
+ ];
10947
+ }
10948
+ const baseDiff = {
10949
+ filePath: file.path,
10950
+ artifactName: file.artifactName,
10951
+ artifactType: file.artifactType,
10952
+ artifactId: file.artifactId,
10953
+ spaceId: file.spaceId
10954
+ };
10955
+ const checks = [
10956
+ this.checkUpdateSkillName(serverParsed, localParsed, baseDiff),
10957
+ this.checkUpdateSkillDescription(serverParsed, localParsed, baseDiff),
10958
+ this.checkUpdateSkillPrompt(serverParsed, localParsed, baseDiff),
10959
+ this.checkUpdateSkillMetadata(serverParsed, localParsed, baseDiff),
10960
+ this.checkUpdateSkillLicense(serverParsed, localParsed, baseDiff),
10961
+ this.checkUpdateSkillCompatibility(serverParsed, localParsed, baseDiff),
10962
+ this.checkUpdateSkillAllowedTools(serverParsed, localParsed, baseDiff)
10963
+ ];
10964
+ return checks.filter((d) => d !== null);
10700
10965
  }
10701
- async lintFilesFromConfig(command20) {
10702
- return this.hexa.useCases.lintFilesFromConfig.execute(command20);
10966
+ async diffSkillFile(file, baseDirectory, skillFolders) {
10967
+ if (!file.skillFileId) {
10968
+ return [];
10969
+ }
10970
+ const skillFileId = createSkillFileId(file.skillFileId);
10971
+ const fullPath = path13.join(baseDirectory, file.path);
10972
+ const localRead = await this.tryReadFileBinaryAware(fullPath);
10973
+ const fileRelativePath = this.computeRelativePath(file.path, skillFolders);
10974
+ if (localRead === null) {
10975
+ return [
10976
+ {
10977
+ filePath: file.path,
10978
+ type: "deleteSkillFile" /* deleteSkillFile */,
10979
+ payload: {
10980
+ targetId: skillFileId,
10981
+ item: {
10982
+ id: skillFileId,
10983
+ path: fileRelativePath,
10984
+ content: file.content,
10985
+ permissions: file.skillFilePermissions ?? "read",
10986
+ isBase64: file.isBase64 ?? false
10987
+ }
10988
+ },
10989
+ artifactName: file.artifactName,
10990
+ artifactType: file.artifactType,
10991
+ artifactId: file.artifactId,
10992
+ spaceId: file.spaceId
10993
+ }
10994
+ ];
10995
+ }
10996
+ const baseDiff = {
10997
+ filePath: file.path,
10998
+ artifactName: file.artifactName,
10999
+ artifactType: file.artifactType,
11000
+ artifactId: file.artifactId,
11001
+ spaceId: file.spaceId
11002
+ };
11003
+ const checks = await Promise.all([
11004
+ this.checkUpdateSkillFileContent(
11005
+ file,
11006
+ localRead.content,
11007
+ localRead.isBase64,
11008
+ skillFileId,
11009
+ baseDiff
11010
+ ),
11011
+ this.checkUpdateSkillFilePermissions(
11012
+ file,
11013
+ fullPath,
11014
+ skillFileId,
11015
+ baseDiff
11016
+ )
11017
+ ]);
11018
+ return checks.filter((d) => d !== null);
10703
11019
  }
10704
- async installPackages(command20) {
10705
- return this.hexa.useCases.installPackages.execute(command20);
11020
+ checkUpdateSkillName(serverParsed, localParsed, baseDiff) {
11021
+ if (serverParsed.name === localParsed.name) {
11022
+ return null;
11023
+ }
11024
+ return {
11025
+ ...baseDiff,
11026
+ type: "updateSkillName" /* updateSkillName */,
11027
+ payload: { oldValue: serverParsed.name, newValue: localParsed.name }
11028
+ };
10706
11029
  }
10707
- async listPackages(command20) {
10708
- return this.hexa.useCases.listPackages.execute(command20);
11030
+ checkUpdateSkillDescription(serverParsed, localParsed, baseDiff) {
11031
+ if (serverParsed.description === localParsed.description) {
11032
+ return null;
11033
+ }
11034
+ return {
11035
+ ...baseDiff,
11036
+ type: "updateSkillDescription" /* updateSkillDescription */,
11037
+ payload: {
11038
+ oldValue: serverParsed.description,
11039
+ newValue: localParsed.description
11040
+ }
11041
+ };
10709
11042
  }
10710
- async getPackageBySlug(command20) {
10711
- return this.hexa.useCases.getPackageBySlug.execute(command20);
11043
+ checkUpdateSkillPrompt(serverParsed, localParsed, baseDiff) {
11044
+ if (serverParsed.body === localParsed.body) {
11045
+ return null;
11046
+ }
11047
+ return {
11048
+ ...baseDiff,
11049
+ type: "updateSkillPrompt" /* updateSkillPrompt */,
11050
+ payload: { oldValue: serverParsed.body, newValue: localParsed.body }
11051
+ };
10712
11052
  }
10713
- async listStandards(command20) {
10714
- return this.hexa.useCases.listStandards.execute(command20);
11053
+ checkUpdateSkillMetadata(serverParsed, localParsed, baseDiff) {
11054
+ if (serverParsed.metadataJson === localParsed.metadataJson) {
11055
+ return null;
11056
+ }
11057
+ return {
11058
+ ...baseDiff,
11059
+ type: "updateSkillMetadata" /* updateSkillMetadata */,
11060
+ payload: {
11061
+ oldValue: serverParsed.metadataJson,
11062
+ newValue: localParsed.metadataJson
11063
+ }
11064
+ };
10715
11065
  }
10716
- async listCommands(command20) {
10717
- return this.hexa.useCases.listCommands.execute(command20);
11066
+ checkUpdateSkillLicense(serverParsed, localParsed, baseDiff) {
11067
+ if (serverParsed.license === localParsed.license) {
11068
+ return null;
11069
+ }
11070
+ return {
11071
+ ...baseDiff,
11072
+ type: "updateSkillLicense" /* updateSkillLicense */,
11073
+ payload: {
11074
+ oldValue: serverParsed.license,
11075
+ newValue: localParsed.license
11076
+ }
11077
+ };
10718
11078
  }
10719
- async listSkills(command20) {
10720
- return this.hexa.useCases.listSkills.execute(command20);
11079
+ checkUpdateSkillCompatibility(serverParsed, localParsed, baseDiff) {
11080
+ if (serverParsed.compatibility === localParsed.compatibility) {
11081
+ return null;
11082
+ }
11083
+ return {
11084
+ ...baseDiff,
11085
+ type: "updateSkillCompatibility" /* updateSkillCompatibility */,
11086
+ payload: {
11087
+ oldValue: serverParsed.compatibility,
11088
+ newValue: localParsed.compatibility
11089
+ }
11090
+ };
10721
11091
  }
10722
- async configExists(baseDirectory) {
10723
- return await this.hexa.repositories.configFileRepository.configExists(
10724
- baseDirectory
10725
- );
11092
+ checkUpdateSkillAllowedTools(serverParsed, localParsed, baseDiff) {
11093
+ if (serverParsed.allowedTools === localParsed.allowedTools) {
11094
+ return null;
11095
+ }
11096
+ return {
11097
+ ...baseDiff,
11098
+ type: "updateSkillAllowedTools" /* updateSkillAllowedTools */,
11099
+ payload: {
11100
+ oldValue: serverParsed.allowedTools,
11101
+ newValue: localParsed.allowedTools
11102
+ }
11103
+ };
11104
+ }
11105
+ checkUpdateSkillFileContent(file, localContent, localIsBase64, skillFileId, baseDiff) {
11106
+ const isBinary = localIsBase64 || (file.isBase64 ?? false);
11107
+ if (isBinary) {
11108
+ if (localContent === file.content) {
11109
+ return null;
11110
+ }
11111
+ return {
11112
+ ...baseDiff,
11113
+ type: "updateSkillFileContent" /* updateSkillFileContent */,
11114
+ payload: {
11115
+ targetId: skillFileId,
11116
+ oldValue: file.content,
11117
+ newValue: localContent,
11118
+ isBase64: true
11119
+ }
11120
+ };
11121
+ }
11122
+ if (localContent === file.content) {
11123
+ return null;
11124
+ }
11125
+ return {
11126
+ ...baseDiff,
11127
+ type: "updateSkillFileContent" /* updateSkillFileContent */,
11128
+ payload: {
11129
+ targetId: skillFileId,
11130
+ oldValue: file.content,
11131
+ newValue: localContent,
11132
+ isBase64: false
11133
+ }
11134
+ };
11135
+ }
11136
+ async checkUpdateSkillFilePermissions(file, fullPath, skillFileId, baseDiff) {
11137
+ if (!file.skillFilePermissions) {
11138
+ return null;
11139
+ }
11140
+ const localPermissions = await this.tryGetPermissions(fullPath);
11141
+ if (!localPermissions || localPermissions === file.skillFilePermissions) {
11142
+ return null;
11143
+ }
11144
+ return {
11145
+ ...baseDiff,
11146
+ type: "updateSkillFilePermissions" /* updateSkillFilePermissions */,
11147
+ payload: {
11148
+ targetId: skillFileId,
11149
+ oldValue: file.skillFilePermissions,
11150
+ newValue: localPermissions
11151
+ }
11152
+ };
11153
+ }
11154
+ async tryReadFile(filePath) {
11155
+ try {
11156
+ return await fs12.readFile(filePath, "utf-8");
11157
+ } catch {
11158
+ return null;
11159
+ }
11160
+ }
11161
+ async tryReadFileBinaryAware(filePath) {
11162
+ try {
11163
+ const buffer = await fs12.readFile(filePath);
11164
+ if (isBinaryFile(filePath, buffer)) {
11165
+ return { content: buffer.toString("base64"), isBase64: true };
11166
+ }
11167
+ return { content: buffer.toString("utf-8"), isBase64: false };
11168
+ } catch {
11169
+ return null;
11170
+ }
11171
+ }
11172
+ async listFilesRecursively(dirPath, prefix = "") {
11173
+ let entries;
11174
+ try {
11175
+ entries = await fs12.readdir(dirPath);
11176
+ } catch {
11177
+ return [];
11178
+ }
11179
+ const files = [];
11180
+ for (const entry of entries) {
11181
+ const fullPath = path13.join(dirPath, entry);
11182
+ const stat5 = await this.tryStatFile(fullPath);
11183
+ if (!stat5) {
11184
+ continue;
11185
+ }
11186
+ const relativePath = prefix ? `${prefix}/${entry}` : entry;
11187
+ if (stat5.isDirectory) {
11188
+ const subFiles = await this.listFilesRecursively(
11189
+ fullPath,
11190
+ relativePath
11191
+ );
11192
+ files.push(...subFiles);
11193
+ } else {
11194
+ files.push(relativePath);
11195
+ }
11196
+ }
11197
+ return files;
11198
+ }
11199
+ async tryStatFile(filePath) {
11200
+ try {
11201
+ const stat5 = await fs12.stat(filePath);
11202
+ return { isDirectory: stat5.isDirectory() };
11203
+ } catch {
11204
+ return null;
11205
+ }
11206
+ }
11207
+ async tryGetPermissions(filePath) {
11208
+ try {
11209
+ const stat5 = await fs12.stat(filePath);
11210
+ return modeToPermissionStringOrDefault(stat5.mode);
11211
+ } catch {
11212
+ return null;
11213
+ }
11214
+ }
11215
+ computeRelativePath(filePath, skillFolders) {
11216
+ const skillFolder = skillFolders.find((f) => filePath.startsWith(f + "/"));
11217
+ if (skillFolder) {
11218
+ return filePath.slice(skillFolder.length + 1);
11219
+ }
11220
+ return filePath.split("/").slice(3).join("/");
11221
+ }
11222
+ };
11223
+
11224
+ // apps/cli/src/application/useCases/diffStrategies/StandardDiffStrategy.ts
11225
+ var fs13 = __toESM(require("fs/promises"));
11226
+ var path14 = __toESM(require("path"));
11227
+
11228
+ // apps/cli/src/application/utils/parseStandardMd.ts
11229
+ var DEPLOYER_PARSERS = [
11230
+ { pattern: ".packmind/standards/", parse: parsePackmindStandard },
11231
+ { pattern: ".claude/rules/packmind/standard-", parse: parseClaudeStandard },
11232
+ { pattern: ".cursor/rules/packmind/standard-", parse: parseCursorStandard },
11233
+ {
11234
+ pattern: ".continue/rules/packmind/standard-",
11235
+ parse: parseContinueStandard
11236
+ },
11237
+ { pattern: ".github/instructions/packmind-", parse: parseCopilotStandard }
11238
+ ];
11239
+ function parseStandardMd(content, filePath) {
11240
+ const deployer = DEPLOYER_PARSERS.find((d) => filePath.includes(d.pattern));
11241
+ if (!deployer) {
11242
+ return null;
11243
+ }
11244
+ return deployer.parse(content);
11245
+ }
11246
+ function parsePackmindStandard(content) {
11247
+ const lines = content.split("\n");
11248
+ let name = null;
11249
+ let nameLineIndex = -1;
11250
+ for (let i = 0; i < lines.length; i++) {
11251
+ if (lines[i].startsWith("# ") && !lines[i].startsWith("## ")) {
11252
+ const extracted = lines[i].slice(2).trim();
11253
+ if (extracted) {
11254
+ name = extracted;
11255
+ nameLineIndex = i;
11256
+ break;
11257
+ }
11258
+ }
11259
+ }
11260
+ if (!name) {
11261
+ return null;
11262
+ }
11263
+ let rulesLineIndex = -1;
11264
+ for (let i = nameLineIndex + 1; i < lines.length; i++) {
11265
+ if (lines[i].trim() === "## Rules") {
11266
+ rulesLineIndex = i;
11267
+ break;
11268
+ }
11269
+ }
11270
+ const descriptionLines = [];
11271
+ let rulesStartIndex = -1;
11272
+ if (rulesLineIndex >= 0) {
11273
+ for (let i = nameLineIndex + 1; i < rulesLineIndex; i++) {
11274
+ descriptionLines.push(lines[i]);
11275
+ }
11276
+ rulesStartIndex = rulesLineIndex + 1;
11277
+ } else {
11278
+ for (let i = nameLineIndex + 1; i < lines.length; i++) {
11279
+ if (lines[i].startsWith("* ") || lines[i].startsWith("- ")) {
11280
+ rulesStartIndex = i;
11281
+ break;
11282
+ }
11283
+ descriptionLines.push(lines[i]);
11284
+ }
11285
+ }
11286
+ const rules = extractRulesList(lines, rulesStartIndex);
11287
+ return {
11288
+ name,
11289
+ description: descriptionLines.join("\n").trim(),
11290
+ scope: "",
11291
+ rules
11292
+ };
11293
+ }
11294
+ function parseClaudeStandard(content) {
11295
+ const { frontmatter, body } = extractFrontmatter(content);
11296
+ const scope = extractScopeFromKey(frontmatter, "paths");
11297
+ const parsed = parseIdeStandardBody(body, scope);
11298
+ if (!parsed) return null;
11299
+ return addFrontmatterFields(parsed, frontmatter);
11300
+ }
11301
+ function parseCursorStandard(content) {
11302
+ const { frontmatter, body } = extractFrontmatter(content);
11303
+ const scope = extractScopeFromKey(frontmatter, "globs");
11304
+ return parseIdeStandardBody(body, scope);
11305
+ }
11306
+ function parseContinueStandard(content) {
11307
+ const { frontmatter, body } = extractFrontmatter(content);
11308
+ const scope = extractScopeFromKey(frontmatter, "globs");
11309
+ const parsed = parseIdeStandardBody(body, scope);
11310
+ if (!parsed) return null;
11311
+ return addFrontmatterFields(parsed, frontmatter);
11312
+ }
11313
+ function parseCopilotStandard(content) {
11314
+ const { frontmatter, body } = extractFrontmatter(content);
11315
+ const rawScope = extractFrontmatterValue(frontmatter, "applyTo");
11316
+ let scope = "";
11317
+ if (rawScope) {
11318
+ const stripped = rawScope.replace(/(?:^['"])|(?:['"]$)/g, "");
11319
+ scope = stripped === "**" ? "" : stripped;
11320
+ }
11321
+ return parseIdeStandardBody(body, scope);
11322
+ }
11323
+ var RULES_FALLBACK = "No rules defined yet.";
11324
+ function extractRulesList(lines, startIndex) {
11325
+ if (startIndex < 0) return [];
11326
+ const rules = [];
11327
+ for (let i = startIndex; i < lines.length; i++) {
11328
+ const line = lines[i];
11329
+ if (line.startsWith("* ") || line.startsWith("- ")) {
11330
+ const content = line.slice(2).trim();
11331
+ if (content && content !== RULES_FALLBACK) {
11332
+ rules.push(content);
11333
+ }
11334
+ } else if (line.startsWith("Full standard is available")) {
11335
+ break;
11336
+ } else if (line.startsWith("## ")) {
11337
+ break;
11338
+ }
11339
+ }
11340
+ return rules;
11341
+ }
11342
+ function extractFrontmatter(content) {
11343
+ const match = content.match(/^---\n([\s\S]*?)\n---\n?/);
11344
+ if (!match) {
11345
+ return { frontmatter: "", body: content };
11346
+ }
11347
+ return {
11348
+ frontmatter: match[1],
11349
+ body: content.slice(match[0].length)
11350
+ };
11351
+ }
11352
+ function parseIdeStandardBody(body, scope) {
11353
+ const lines = body.split("\n");
11354
+ let name = null;
11355
+ let nameLineIndex = -1;
11356
+ for (let i = 0; i < lines.length; i++) {
11357
+ if (lines[i].startsWith("## Standard: ")) {
11358
+ const extracted = lines[i].slice("## Standard: ".length).trim();
11359
+ if (extracted) {
11360
+ name = extracted;
11361
+ nameLineIndex = i;
11362
+ break;
11363
+ }
11364
+ }
11365
+ }
11366
+ if (!name) {
11367
+ return null;
11368
+ }
11369
+ const descriptionLines = [];
11370
+ let rulesStartIndex = -1;
11371
+ for (let i = nameLineIndex + 1; i < lines.length; i++) {
11372
+ if (lines[i].startsWith("* ") || lines[i].startsWith("- ")) {
11373
+ rulesStartIndex = i;
11374
+ break;
11375
+ }
11376
+ if (lines[i].startsWith("Full standard is available")) break;
11377
+ descriptionLines.push(lines[i]);
11378
+ }
11379
+ let description = descriptionLines.join("\n").trim();
11380
+ if (description.endsWith(" :")) {
11381
+ description = description.slice(0, -2).trim();
11382
+ }
11383
+ const rules = extractRulesList(lines, rulesStartIndex);
11384
+ return { name, description, scope, rules };
11385
+ }
11386
+ function addFrontmatterFields(parsed, frontmatter) {
11387
+ const fmName = extractFrontmatterValue(frontmatter, "name");
11388
+ const fmDescription = extractFrontmatterValue(frontmatter, "description");
11389
+ return {
11390
+ ...parsed,
11391
+ ...fmName ? { frontmatterName: fmName } : {},
11392
+ ...fmDescription ? { frontmatterDescription: fmDescription } : {}
11393
+ };
11394
+ }
11395
+ function extractFrontmatterValue(frontmatter, key) {
11396
+ if (!frontmatter) return "";
11397
+ for (const line of frontmatter.split("\n")) {
11398
+ const trimmed = line.trim();
11399
+ if (trimmed.startsWith(`${key}:`)) {
11400
+ const raw = trimmed.slice(key.length + 1).trim();
11401
+ return stripYamlQuotes(raw);
11402
+ }
11403
+ }
11404
+ return "";
11405
+ }
11406
+ function stripYamlQuotes(value) {
11407
+ if (value.startsWith("'") && value.endsWith("'") && value.length >= 2) {
11408
+ return value.slice(1, -1).replace(/''/g, "'");
11409
+ }
11410
+ if (value.startsWith('"') && value.endsWith('"') && value.length >= 2) {
11411
+ return value.slice(1, -1);
11412
+ }
11413
+ return value;
11414
+ }
11415
+ function extractScopeFromKey(frontmatter, key) {
11416
+ const rawValue = extractFrontmatterValue(frontmatter, key);
11417
+ if (!rawValue) return "";
11418
+ return normalizeScopeValue(rawValue);
11419
+ }
11420
+ function normalizeScopeValue(rawValue) {
11421
+ if (!rawValue) return "";
11422
+ if (rawValue.startsWith("[")) {
11423
+ const inner = rawValue.slice(1, -1);
11424
+ const items = inner.split(",").map((item) => item.trim().replace(/(?:^["'])|(?:["']$)/g, ""));
11425
+ return items.join(", ");
11426
+ }
11427
+ return rawValue.replace(/(?:^["'])|(?:["']$)/g, "");
11428
+ }
11429
+
11430
+ // apps/cli/src/application/useCases/diffStrategies/StandardDiffStrategy.ts
11431
+ var StandardDiffStrategy = class {
11432
+ supports(file) {
11433
+ return file.artifactType === "standard";
11434
+ }
11435
+ async diff(file, baseDirectory) {
11436
+ const fullPath = path14.join(baseDirectory, file.path);
11437
+ let localContent;
11438
+ try {
11439
+ localContent = await fs13.readFile(fullPath, "utf-8");
11440
+ } catch {
11441
+ return [];
11442
+ }
11443
+ const serverParsed = parseStandardMd(file.content, file.path);
11444
+ const localParsed = parseStandardMd(localContent, file.path);
11445
+ if (!serverParsed || !localParsed) {
11446
+ return [];
11447
+ }
11448
+ const diffs = [];
11449
+ const diffBase = {
11450
+ filePath: file.path,
11451
+ artifactName: file.artifactName,
11452
+ artifactType: file.artifactType,
11453
+ artifactId: file.artifactId,
11454
+ spaceId: file.spaceId
11455
+ };
11456
+ if (serverParsed.frontmatterName && localParsed.frontmatterName && serverParsed.frontmatterName !== localParsed.frontmatterName) {
11457
+ diffs.push({
11458
+ ...diffBase,
11459
+ type: "updateStandardName" /* updateStandardName */,
11460
+ payload: {
11461
+ oldValue: serverParsed.frontmatterName,
11462
+ newValue: localParsed.frontmatterName
11463
+ }
11464
+ });
11465
+ }
11466
+ if (serverParsed.name !== localParsed.name) {
11467
+ diffs.push({
11468
+ ...diffBase,
11469
+ type: "updateStandardName" /* updateStandardName */,
11470
+ payload: {
11471
+ oldValue: serverParsed.name,
11472
+ newValue: localParsed.name
11473
+ }
11474
+ });
11475
+ }
11476
+ if (serverParsed.frontmatterDescription && localParsed.frontmatterDescription && serverParsed.frontmatterDescription !== localParsed.frontmatterDescription) {
11477
+ diffs.push({
11478
+ ...diffBase,
11479
+ type: "updateStandardDescription" /* updateStandardDescription */,
11480
+ payload: {
11481
+ oldValue: serverParsed.frontmatterDescription,
11482
+ newValue: localParsed.frontmatterDescription
11483
+ }
11484
+ });
11485
+ }
11486
+ if (serverParsed.description !== localParsed.description) {
11487
+ diffs.push({
11488
+ ...diffBase,
11489
+ type: "updateStandardDescription" /* updateStandardDescription */,
11490
+ payload: {
11491
+ oldValue: serverParsed.description,
11492
+ newValue: localParsed.description
11493
+ }
11494
+ });
11495
+ }
11496
+ if (serverParsed.scope !== localParsed.scope) {
11497
+ diffs.push({
11498
+ ...diffBase,
11499
+ type: "updateStandardScope" /* updateStandardScope */,
11500
+ payload: {
11501
+ oldValue: serverParsed.scope,
11502
+ newValue: localParsed.scope
11503
+ }
11504
+ });
11505
+ }
11506
+ const serverRules = new Set(serverParsed.rules);
11507
+ const localRules = new Set(localParsed.rules);
11508
+ for (const rule of serverRules) {
11509
+ if (!localRules.has(rule)) {
11510
+ const ruleId = createRuleId("unresolved");
11511
+ diffs.push({
11512
+ ...diffBase,
11513
+ type: "deleteRule" /* deleteRule */,
11514
+ payload: {
11515
+ targetId: ruleId,
11516
+ item: { id: ruleId, content: rule }
11517
+ }
11518
+ });
11519
+ }
11520
+ }
11521
+ for (const rule of localRules) {
11522
+ if (!serverRules.has(rule)) {
11523
+ diffs.push({
11524
+ ...diffBase,
11525
+ type: "addRule" /* addRule */,
11526
+ payload: {
11527
+ item: { content: rule }
11528
+ }
11529
+ });
11530
+ }
11531
+ }
11532
+ return diffs;
11533
+ }
11534
+ };
11535
+
11536
+ // apps/cli/src/application/useCases/DiffArtefactsUseCase.ts
11537
+ var DiffArtefactsUseCase = class {
11538
+ constructor(packmindGateway) {
11539
+ this.packmindGateway = packmindGateway;
11540
+ this.strategies = [
11541
+ new CommandDiffStrategy(),
11542
+ new SkillDiffStrategy(),
11543
+ new StandardDiffStrategy()
11544
+ ];
11545
+ }
11546
+ async execute(command21) {
11547
+ const baseDirectory = command21.baseDirectory || process.cwd();
11548
+ const response = await this.packmindGateway.deployment.getDeployed({
11549
+ packagesSlugs: command21.packagesSlugs,
11550
+ gitRemoteUrl: command21.gitRemoteUrl,
11551
+ gitBranch: command21.gitBranch,
11552
+ relativePath: command21.relativePath,
11553
+ agents: command21.agents
11554
+ });
11555
+ const filteredFiles = response.fileUpdates.createOrUpdate.filter(
11556
+ (file) => file.path !== "packmind.json"
11557
+ );
11558
+ const uniqueFilesMap = /* @__PURE__ */ new Map();
11559
+ for (const file of filteredFiles) {
11560
+ uniqueFilesMap.set(file.path, file);
11561
+ }
11562
+ const diffableFiles = Array.from(uniqueFilesMap.values()).filter(
11563
+ (file) => !!file.artifactType && !!file.artifactName && file.content !== void 0
11564
+ );
11565
+ const prefixedSkillFolders = this.prefixSkillFolders(
11566
+ response.skillFolders,
11567
+ command21.relativePath
11568
+ );
11569
+ const diffs = [];
11570
+ for (const file of diffableFiles) {
11571
+ const strategy = this.strategies.find((s) => s.supports(file));
11572
+ if (strategy) {
11573
+ const fileDiffs = await strategy.diff(file, baseDirectory, {
11574
+ skillFolders: prefixedSkillFolders
11575
+ });
11576
+ diffs.push(...fileDiffs);
11577
+ }
11578
+ }
11579
+ for (const strategy of this.strategies) {
11580
+ if (strategy.diffNewFiles) {
11581
+ const newFileDiffs = await strategy.diffNewFiles(
11582
+ prefixedSkillFolders,
11583
+ diffableFiles,
11584
+ baseDirectory
11585
+ );
11586
+ diffs.push(...newFileDiffs);
11587
+ }
11588
+ }
11589
+ return diffs;
11590
+ }
11591
+ prefixSkillFolders(skillFolders, relativePath) {
11592
+ if (!relativePath) return skillFolders;
11593
+ let normalized = relativePath;
11594
+ while (normalized.startsWith("/")) normalized = normalized.slice(1);
11595
+ while (normalized.endsWith("/")) normalized = normalized.slice(0, -1);
11596
+ if (!normalized) return skillFolders;
11597
+ return skillFolders.map((folder) => `${normalized}/${folder}`);
11598
+ }
11599
+ };
11600
+
11601
+ // apps/cli/src/application/useCases/SubmitDiffsUseCase.ts
11602
+ var SUPPORTED_ARTIFACT_TYPES = /* @__PURE__ */ new Set(["command", "skill", "standard"]);
11603
+ var SubmitDiffsUseCase = class {
11604
+ constructor(packmindGateway) {
11605
+ this.packmindGateway = packmindGateway;
11606
+ }
11607
+ async execute(command21) {
11608
+ const { groupedDiffs } = command21;
11609
+ const skipped = [];
11610
+ const validDiffs = [];
11611
+ for (const group of groupedDiffs) {
11612
+ const firstDiff = group[0];
11613
+ if (!firstDiff) {
11614
+ continue;
11615
+ }
11616
+ if (!SUPPORTED_ARTIFACT_TYPES.has(firstDiff.artifactType)) {
11617
+ skipped.push({
11618
+ name: firstDiff.artifactName,
11619
+ reason: "Only commands, skills, and standards are supported"
11620
+ });
11621
+ continue;
11622
+ }
11623
+ for (const diff of group) {
11624
+ if (!diff.artifactId || !diff.spaceId) {
11625
+ skipped.push({
11626
+ name: diff.artifactName,
11627
+ reason: "Missing artifact metadata"
11628
+ });
11629
+ continue;
11630
+ }
11631
+ validDiffs.push(diff);
11632
+ }
11633
+ }
11634
+ const diffsBySpaceId = /* @__PURE__ */ new Map();
11635
+ for (const diff of validDiffs) {
11636
+ const existing = diffsBySpaceId.get(diff.spaceId) ?? [];
11637
+ existing.push(diff);
11638
+ diffsBySpaceId.set(diff.spaceId, existing);
11639
+ }
11640
+ let submitted = 0;
11641
+ let alreadySubmitted = 0;
11642
+ const errors = [];
11643
+ for (const [spaceId, diffs] of diffsBySpaceId) {
11644
+ const response = await this.packmindGateway.changeProposals.batchCreate({
11645
+ spaceId,
11646
+ proposals: diffs.map((diff) => ({
11647
+ type: diff.type,
11648
+ artefactId: diff.artifactId,
11649
+ payload: diff.payload,
11650
+ captureMode: "commit" /* commit */
11651
+ }))
11652
+ });
11653
+ submitted += response.created;
11654
+ alreadySubmitted += response.skipped;
11655
+ for (const error of response.errors) {
11656
+ errors.push({
11657
+ name: diffs[error.index].artifactName,
11658
+ message: error.message,
11659
+ code: error.code,
11660
+ artifactType: diffs[error.index].artifactType
11661
+ });
11662
+ }
11663
+ }
11664
+ return { submitted, alreadySubmitted, skipped, errors };
11665
+ }
11666
+ };
11667
+
11668
+ // apps/cli/src/PackmindCliHexaFactory.ts
11669
+ var PackmindCliHexaFactory = class {
11670
+ constructor() {
11671
+ this.repositories = {
11672
+ packmindGateway: new PackmindGateway(loadApiKey()),
11673
+ configFileRepository: new ConfigFileRepository()
11674
+ };
11675
+ this.services = {
11676
+ listFiles: new ListFiles(),
11677
+ gitRemoteUrlService: new GitService(),
11678
+ linterExecutionUseCase: new ExecuteLinterProgramsUseCase(),
11679
+ diffViolationFilterService: new DiffViolationFilterService()
11680
+ };
11681
+ this.useCases = {
11682
+ executeSingleFileAst: new ExecuteSingleFileAstUseCase(
11683
+ this.services.linterExecutionUseCase
11684
+ ),
11685
+ getGitRemoteUrl: new GetGitRemoteUrlUseCase(),
11686
+ listFilesInDirectoryUseCase: new ListFilesInDirectoryUseCase(),
11687
+ lintFilesAgainstRule: new LintFilesAgainstRuleUseCase(
11688
+ this.services,
11689
+ this.repositories
11690
+ ),
11691
+ lintFilesFromConfig: new LintFilesFromConfigUseCase(
11692
+ this.services,
11693
+ this.repositories
11694
+ ),
11695
+ installPackages: new InstallPackagesUseCase(
11696
+ this.repositories.packmindGateway
11697
+ ),
11698
+ installDefaultSkills: new InstallDefaultSkillsUseCase(this.repositories),
11699
+ listPackages: new ListPackagesUseCase(this.repositories.packmindGateway),
11700
+ getPackageBySlug: new GetPackageSummaryUseCase(
11701
+ this.repositories.packmindGateway
11702
+ ),
11703
+ login: new LoginUseCase(),
11704
+ logout: new LogoutUseCase(),
11705
+ whoami: new WhoamiUseCase(),
11706
+ setupMcp: new SetupMcpUseCase({
11707
+ gateway: this.repositories.packmindGateway,
11708
+ mcpConfigService: new McpConfigService()
11709
+ }),
11710
+ listStandards: new ListStandardsUseCase(
11711
+ this.repositories.packmindGateway
11712
+ ),
11713
+ listCommands: new ListCommandsUseCase(this.repositories.packmindGateway),
11714
+ listSkills: new ListSkillsUseCase(this.repositories.packmindGateway),
11715
+ uploadSkill: new UploadSkillUseCase({
11716
+ gateway: this.repositories.packmindGateway
11717
+ }),
11718
+ diffArtefacts: new DiffArtefactsUseCase(
11719
+ this.repositories.packmindGateway
11720
+ ),
11721
+ submitDiffs: new SubmitDiffsUseCase(this.repositories.packmindGateway)
11722
+ };
11723
+ }
11724
+ };
11725
+
11726
+ // apps/cli/src/PackmindCliHexa.ts
11727
+ var origin8 = "PackmindCliHexa";
11728
+ var PackmindCliHexa = class {
11729
+ constructor(logger2 = new PackmindLogger(origin8)) {
11730
+ this.notifyDistribution = async (command21) => {
11731
+ return this.hexa.repositories.packmindGateway.deployment.notifyDistribution(
11732
+ command21
11733
+ );
11734
+ };
11735
+ this.logger = logger2;
11736
+ try {
11737
+ this.hexa = new PackmindCliHexaFactory();
11738
+ } catch (error) {
11739
+ this.logger.error("Failed to initialize PackmindCliHexa", {
11740
+ error: error instanceof Error ? error.message : String(error)
11741
+ });
11742
+ throw error;
11743
+ }
11744
+ }
11745
+ /**
11746
+ * Destroys the DeploymentsHexa and cleans up resources
11747
+ */
11748
+ destroy() {
11749
+ this.logger.info("Destroying PackmindCliHexa");
11750
+ this.logger.info("PackmindCliHexa destroyed");
11751
+ }
11752
+ async getGitRemoteUrl(command21) {
11753
+ return this.hexa.useCases.getGitRemoteUrl.execute(command21);
11754
+ }
11755
+ async executeSingleFileAst(command21) {
11756
+ return this.hexa.useCases.executeSingleFileAst.execute(command21);
11757
+ }
11758
+ async listFilesInDirectory(command21) {
11759
+ return this.hexa.useCases.listFilesInDirectoryUseCase.execute(command21);
11760
+ }
11761
+ async lintFilesAgainstRule(command21) {
11762
+ return this.hexa.useCases.lintFilesAgainstRule.execute(command21);
11763
+ }
11764
+ async lintFilesFromConfig(command21) {
11765
+ return this.hexa.useCases.lintFilesFromConfig.execute(command21);
11766
+ }
11767
+ async installPackages(command21) {
11768
+ return this.hexa.useCases.installPackages.execute(command21);
11769
+ }
11770
+ async diffArtefacts(command21) {
11771
+ return this.hexa.useCases.diffArtefacts.execute(command21);
11772
+ }
11773
+ async submitDiffs(groupedDiffs) {
11774
+ return this.hexa.useCases.submitDiffs.execute({ groupedDiffs });
11775
+ }
11776
+ async listPackages(command21) {
11777
+ return this.hexa.useCases.listPackages.execute(command21);
11778
+ }
11779
+ async getPackageBySlug(command21) {
11780
+ return this.hexa.useCases.getPackageBySlug.execute(command21);
11781
+ }
11782
+ async listStandards(command21) {
11783
+ return this.hexa.useCases.listStandards.execute(command21);
11784
+ }
11785
+ async listCommands(command21) {
11786
+ return this.hexa.useCases.listCommands.execute(command21);
11787
+ }
11788
+ async listSkills(command21) {
11789
+ return this.hexa.useCases.listSkills.execute(command21);
11790
+ }
11791
+ async configExists(baseDirectory) {
11792
+ return await this.hexa.repositories.configFileRepository.configExists(
11793
+ baseDirectory
11794
+ );
10726
11795
  }
10727
11796
  async readConfig(baseDirectory) {
10728
11797
  const config = await this.hexa.repositories.configFileRepository.readConfig(
@@ -10804,17 +11873,17 @@ var PackmindCliHexa = class {
10804
11873
  directory
10805
11874
  );
10806
11875
  }
10807
- async login(command20) {
10808
- return this.hexa.useCases.login.execute(command20);
11876
+ async login(command21) {
11877
+ return this.hexa.useCases.login.execute(command21);
10809
11878
  }
10810
- async logout(command20) {
10811
- return this.hexa.useCases.logout.execute(command20);
11879
+ async logout(command21) {
11880
+ return this.hexa.useCases.logout.execute(command21);
10812
11881
  }
10813
- async whoami(command20) {
10814
- return this.hexa.useCases.whoami.execute(command20);
11882
+ async whoami(command21) {
11883
+ return this.hexa.useCases.whoami.execute(command21);
10815
11884
  }
10816
- async setupMcp(command20) {
10817
- return this.hexa.useCases.setupMcp.execute(command20);
11885
+ async setupMcp(command21) {
11886
+ return this.hexa.useCases.setupMcp.execute(command21);
10818
11887
  }
10819
11888
  getCurrentBranch(repoPath) {
10820
11889
  return this.hexa.services.gitRemoteUrlService.getCurrentBranch(repoPath).branch;
@@ -10822,11 +11891,11 @@ var PackmindCliHexa = class {
10822
11891
  getGitRemoteUrlFromPath(repoPath) {
10823
11892
  return this.hexa.services.gitRemoteUrlService.getGitRemoteUrl(repoPath).gitRemoteUrl;
10824
11893
  }
10825
- async uploadSkill(command20) {
10826
- return this.hexa.useCases.uploadSkill.execute(command20);
11894
+ async uploadSkill(command21) {
11895
+ return this.hexa.useCases.uploadSkill.execute(command21);
10827
11896
  }
10828
- async installDefaultSkills(command20) {
10829
- return this.hexa.useCases.installDefaultSkills.execute(command20);
11897
+ async installDefaultSkills(command21) {
11898
+ return this.hexa.useCases.installDefaultSkills.execute(command21);
10830
11899
  }
10831
11900
  getPackmindGateway() {
10832
11901
  return this.hexa.repositories.packmindGateway;
@@ -10858,39 +11927,70 @@ var IDELintLogger = class {
10858
11927
  });
10859
11928
  }
10860
11929
  logViolation(violation) {
10861
- violation.violations.forEach(({ line, character, standard, rule }) => {
10862
- logConsole(
10863
- `${violation.file}:${line}:${character}:error:@${standard}/${rule}`
10864
- );
10865
- });
11930
+ violation.violations.forEach(
11931
+ ({ line, character, standard, rule, severity }) => {
11932
+ const label = (severity ?? "error" /* ERROR */) === "warning" /* WARNING */ ? "warning" : "error";
11933
+ logConsole(
11934
+ `${violation.file}:${line}:${character}:${label}:@${standard}/${rule}`
11935
+ );
11936
+ }
11937
+ );
10866
11938
  }
10867
11939
  };
10868
11940
 
10869
11941
  // apps/cli/src/infra/repositories/HumanReadableLogger.ts
10870
11942
  var HumanReadableLogger = class {
11943
+ effectiveSeverity(s) {
11944
+ return s ?? "error" /* ERROR */;
11945
+ }
10871
11946
  logViolations(violations) {
10872
11947
  violations.forEach((violation) => {
10873
11948
  this.logViolation(violation);
10874
11949
  });
10875
- if (violations.length > 0) {
10876
- const totalViolationCount = violations.reduce(
10877
- (acc, violation) => acc + violation.violations.length,
10878
- 0
10879
- );
11950
+ if (violations.length === 0) {
11951
+ logSuccessConsole(`\u2705 No violations found`);
11952
+ return;
11953
+ }
11954
+ const allDetails = violations.flatMap((v) => v.violations);
11955
+ const errorCount = allDetails.filter(
11956
+ (d) => this.effectiveSeverity(d.severity) === "error" /* ERROR */
11957
+ ).length;
11958
+ const warningCount = allDetails.filter(
11959
+ (d) => this.effectiveSeverity(d.severity) === "warning" /* WARNING */
11960
+ ).length;
11961
+ const errorFileCount = violations.filter(
11962
+ (v) => v.violations.some(
11963
+ (d) => this.effectiveSeverity(d.severity) === "error" /* ERROR */
11964
+ )
11965
+ ).length;
11966
+ const warningFileCount = violations.filter(
11967
+ (v) => v.violations.some(
11968
+ (d) => this.effectiveSeverity(d.severity) === "warning" /* WARNING */
11969
+ )
11970
+ ).length;
11971
+ if (errorCount > 0) {
10880
11972
  logErrorConsole(
10881
- `\u274C Found ${formatBold(String(totalViolationCount))} violation(s) in ${formatBold(String(violations.length))} file(s)`
11973
+ `\u274C Found ${formatBold(String(errorCount))} error(s) in ${formatBold(String(errorFileCount))} file(s)`
11974
+ );
11975
+ }
11976
+ if (warningCount > 0) {
11977
+ logWarningConsole(
11978
+ `\u26A0\uFE0F Found ${formatBold(String(warningCount))} warning(s) in ${formatBold(String(warningFileCount))} file(s)`
10882
11979
  );
10883
- } else {
10884
- logSuccessConsole(`\u2705 No violations found`);
10885
11980
  }
10886
11981
  }
10887
11982
  logViolation(violation) {
10888
11983
  logConsole(formatFilePath(violation.file));
10889
- violation.violations.forEach(({ line, character, standard, rule }) => {
10890
- logConsole(
10891
- formatError(` ${line}:${character} error @${standard}/${rule}`)
10892
- );
10893
- });
11984
+ violation.violations.forEach(
11985
+ ({ line, character, standard, rule, severity }) => {
11986
+ const effective = this.effectiveSeverity(severity);
11987
+ const label = effective === "warning" /* WARNING */ ? "warning" : "error";
11988
+ const format = effective === "warning" /* WARNING */ ? formatWarning : formatError;
11989
+ logConsole(
11990
+ format(` ${line}:${character} ${label} @${standard}/${rule}`)
11991
+ );
11992
+ }
11993
+ );
10894
11994
  }
10895
11995
  };
10896
11996
 
@@ -10898,19 +11998,24 @@ var HumanReadableLogger = class {
10898
11998
  var pathModule = __toESM(require("path"));
10899
11999
 
10900
12000
  // apps/cli/src/infra/commands/lintHandler.ts
12001
+ var SEVERITY_LEVELS = {
12002
+ ["warning" /* WARNING */]: 0,
12003
+ ["error" /* ERROR */]: 1
12004
+ };
10901
12005
  function isNotLoggedInError(error) {
10902
12006
  return error instanceof NotLoggedInError;
10903
12007
  }
10904
12008
  async function lintHandler(args2, deps) {
10905
12009
  const {
10906
- path: path14,
12010
+ path: path18,
10907
12011
  draft,
10908
12012
  rule,
10909
12013
  language,
10910
12014
  logger: logger2,
10911
12015
  continueOnError,
10912
12016
  continueOnMissingKey,
10913
- diff
12017
+ diff,
12018
+ level
10914
12019
  } = args2;
10915
12020
  const {
10916
12021
  packmindCliHexa,
@@ -10923,7 +12028,7 @@ async function lintHandler(args2, deps) {
10923
12028
  throw new Error("option --rule is required to use --draft mode");
10924
12029
  }
10925
12030
  const startedAt = Date.now();
10926
- const targetPath = path14 ?? ".";
12031
+ const targetPath = path18 ?? ".";
10927
12032
  const absolutePath = resolvePath(targetPath);
10928
12033
  if (diff) {
10929
12034
  const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(absolutePath);
@@ -10978,14 +12083,27 @@ async function lintHandler(args2, deps) {
10978
12083
  }
10979
12084
  throw error;
10980
12085
  }
12086
+ const effectiveSeverity = (s) => s ?? "error" /* ERROR */;
12087
+ const filteredViolations = level ? violations.map((v) => ({
12088
+ ...v,
12089
+ violations: v.violations.filter(
12090
+ (d) => SEVERITY_LEVELS[effectiveSeverity(d.severity)] >= SEVERITY_LEVELS[level]
12091
+ )
12092
+ })).filter((v) => v.violations.length > 0) : violations;
10981
12093
  (logger2 === "ide" /* ide */ ? ideLintLogger : humanReadableLogger).logViolations(
10982
- violations
12094
+ filteredViolations
12095
+ );
12096
+ const hasErrors = filteredViolations.some(
12097
+ (v) => v.violations.some(
12098
+ (d) => effectiveSeverity(d.severity) === "error" /* ERROR */
12099
+ )
10983
12100
  );
10984
12101
  const durationSeconds = (Date.now() - startedAt) / 1e3;
10985
- logInfoConsole(`Lint completed in ${durationSeconds.toFixed(2)}s`);
10986
- if (violations.length > 0 && !continueOnError) {
12102
+ if (hasErrors && !continueOnError) {
12103
+ logErrorConsole(`Lint failed in ${durationSeconds.toFixed(2)}s`);
10987
12104
  exit(1);
10988
12105
  } else {
12106
+ logInfoConsole(`Lint completed in ${durationSeconds.toFixed(2)}s`);
10989
12107
  exit(0);
10990
12108
  }
10991
12109
  }
@@ -11031,6 +12149,19 @@ var DiffModeType = {
11031
12149
  );
11032
12150
  }
11033
12151
  };
12152
+ var LevelType = {
12153
+ from: async (input) => {
12154
+ switch (input) {
12155
+ case "error":
12156
+ return "error" /* ERROR */;
12157
+ case "warning":
12158
+ return "warning" /* WARNING */;
12159
+ }
12160
+ throw new Error(
12161
+ `${input} is not a valid value for the --level option. Expected values are: error, warning`
12162
+ );
12163
+ }
12164
+ };
11034
12165
  var lintCommand = (0, import_cmd_ts.command)({
11035
12166
  name: "lint",
11036
12167
  description: "Lint code at the specified path",
@@ -11085,6 +12216,11 @@ var lintCommand = (0, import_cmd_ts.command)({
11085
12216
  changedLines: (0, import_cmd_ts.flag)({
11086
12217
  long: "changed-lines",
11087
12218
  description: "Only lint lines that have changed"
12219
+ }),
12220
+ level: (0, import_cmd_ts.option)({
12221
+ long: "level",
12222
+ description: "Minimum severity level to display (error | warning)",
12223
+ type: (0, import_cmd_ts.optional)(LevelType)
11088
12224
  })
11089
12225
  },
11090
12226
  handler: async (args2) => {
@@ -11174,8 +12310,8 @@ function extractWasmFiles() {
11174
12310
 
11175
12311
  // apps/cli/src/main.ts
11176
12312
  var import_dotenv = require("dotenv");
11177
- var fs16 = __toESM(require("fs"));
11178
- var path13 = __toESM(require("path"));
12313
+ var fs19 = __toESM(require("fs"));
12314
+ var path17 = __toESM(require("path"));
11179
12315
 
11180
12316
  // apps/cli/src/infra/commands/InstallCommand.ts
11181
12317
  var import_cmd_ts2 = __toESM(require_cjs());
@@ -12250,13 +13386,13 @@ Credentials are loaded from (in order of priority):`);
12250
13386
 
12251
13387
  // apps/cli/src/infra/commands/SetupMcpCommand.ts
12252
13388
  var import_cmd_ts7 = __toESM(require_cjs());
12253
- var fs12 = __toESM(require("fs"));
13389
+ var fs15 = __toESM(require("fs"));
12254
13390
  var readline2 = __toESM(require("readline"));
12255
13391
  var inquirer = __toESM(require("inquirer"));
12256
13392
 
12257
13393
  // apps/cli/src/application/services/AgentDetectionService.ts
12258
- var fs11 = __toESM(require("fs"));
12259
- var path11 = __toESM(require("path"));
13394
+ var fs14 = __toESM(require("fs"));
13395
+ var path15 = __toESM(require("path"));
12260
13396
  var os4 = __toESM(require("os"));
12261
13397
  var import_child_process3 = require("child_process");
12262
13398
  var AgentDetectionService = class {
@@ -12283,21 +13419,21 @@ var AgentDetectionService = class {
12283
13419
  return this.isCommandAvailable("claude");
12284
13420
  }
12285
13421
  isCursorAvailable() {
12286
- const cursorConfigDir = path11.join(os4.homedir(), ".cursor");
12287
- return fs11.existsSync(cursorConfigDir);
13422
+ const cursorConfigDir = path15.join(os4.homedir(), ".cursor");
13423
+ return fs14.existsSync(cursorConfigDir);
12288
13424
  }
12289
13425
  isVSCodeAvailable() {
12290
- const vscodeDir = path11.join(this.projectDir, ".vscode");
12291
- return fs11.existsSync(vscodeDir);
13426
+ const vscodeDir = path15.join(this.projectDir, ".vscode");
13427
+ return fs14.existsSync(vscodeDir);
12292
13428
  }
12293
13429
  isContinueAvailable() {
12294
- const continueDir = path11.join(this.projectDir, ".continue");
12295
- return fs11.existsSync(continueDir);
13430
+ const continueDir = path15.join(this.projectDir, ".continue");
13431
+ return fs14.existsSync(continueDir);
12296
13432
  }
12297
- isCommandAvailable(command20) {
13433
+ isCommandAvailable(command21) {
12298
13434
  try {
12299
13435
  const whichCommand = process.platform === "win32" ? "where" : "which";
12300
- (0, import_child_process3.execSync)(`${whichCommand} ${command20}`, { stdio: "pipe" });
13436
+ (0, import_child_process3.execSync)(`${whichCommand} ${command21}`, { stdio: "pipe" });
12301
13437
  return true;
12302
13438
  } catch {
12303
13439
  return false;
@@ -12331,8 +13467,8 @@ var ALL_AGENTS2 = [
12331
13467
  { type: "continue", name: "Continue.dev" }
12332
13468
  ];
12333
13469
  async function promptAgentsWithReadline(choices) {
12334
- const input = fs12.createReadStream("/dev/tty");
12335
- const output = fs12.createWriteStream("/dev/tty");
13470
+ const input = fs15.createReadStream("/dev/tty");
13471
+ const output = fs15.createWriteStream("/dev/tty");
12336
13472
  const rl = readline2.createInterface({
12337
13473
  input,
12338
13474
  output
@@ -12700,7 +13836,7 @@ var import_cmd_ts15 = __toESM(require_cjs());
12700
13836
  var import_cmd_ts13 = __toESM(require_cjs());
12701
13837
 
12702
13838
  // apps/cli/src/infra/utils/readPlaybookFile.ts
12703
- var fs13 = __toESM(require("fs/promises"));
13839
+ var fs16 = __toESM(require("fs/promises"));
12704
13840
 
12705
13841
  // apps/cli/src/domain/entities/PlaybookDTO.ts
12706
13842
  var import_zod = require("zod");
@@ -12739,7 +13875,7 @@ function validatePlaybook(data) {
12739
13875
  // apps/cli/src/infra/utils/readPlaybookFile.ts
12740
13876
  async function readPlaybookFile(filePath) {
12741
13877
  try {
12742
- const content = await fs13.readFile(filePath, "utf-8");
13878
+ const content = await fs16.readFile(filePath, "utf-8");
12743
13879
  let parsed;
12744
13880
  try {
12745
13881
  parsed = JSON.parse(content);
@@ -12955,7 +14091,7 @@ var import_cmd_ts18 = __toESM(require_cjs());
12955
14091
  var import_cmd_ts16 = __toESM(require_cjs());
12956
14092
 
12957
14093
  // apps/cli/src/infra/utils/readCommandPlaybookFile.ts
12958
- var fs14 = __toESM(require("fs/promises"));
14094
+ var fs17 = __toESM(require("fs/promises"));
12959
14095
 
12960
14096
  // apps/cli/src/domain/entities/CommandPlaybookDTO.ts
12961
14097
  var import_zod2 = require("zod");
@@ -12993,7 +14129,7 @@ function validateCommandPlaybook(data) {
12993
14129
  // apps/cli/src/infra/utils/readCommandPlaybookFile.ts
12994
14130
  async function readCommandPlaybookFile(filePath) {
12995
14131
  try {
12996
- const content = await fs14.readFile(filePath, "utf-8");
14132
+ const content = await fs17.readFile(filePath, "utf-8");
12997
14133
  let parsed;
12998
14134
  try {
12999
14135
  parsed = JSON.parse(content);
@@ -13072,7 +14208,7 @@ var CreateCommandFromPlaybookUseCase = class {
13072
14208
  }
13073
14209
  async execute(playbook) {
13074
14210
  const space = await this.gateway.spaces.getGlobal();
13075
- const command20 = await this.gateway.commands.create({
14211
+ const command21 = await this.gateway.commands.create({
13076
14212
  spaceId: space.id,
13077
14213
  name: playbook.name,
13078
14214
  summary: playbook.summary,
@@ -13086,9 +14222,9 @@ var CreateCommandFromPlaybookUseCase = class {
13086
14222
  originSkill: playbook.originSkill
13087
14223
  });
13088
14224
  return {
13089
- commandId: command20.id,
13090
- name: command20.name,
13091
- slug: command20.slug
14225
+ commandId: command21.id,
14226
+ name: command21.name,
14227
+ slug: command21.slug
13092
14228
  };
13093
14229
  }
13094
14230
  };
@@ -13215,11 +14351,322 @@ var commandsCommand = (0, import_cmd_ts18.subcommands)({
13215
14351
  }
13216
14352
  });
13217
14353
 
14354
+ // apps/cli/src/infra/commands/DiffCommand.ts
14355
+ var import_cmd_ts19 = __toESM(require_cjs());
14356
+
14357
+ // apps/cli/src/infra/utils/diffFormatter.ts
14358
+ var import_diff3 = require("diff");
14359
+ init_source();
14360
+ function formatContentDiff(oldContent, newContent) {
14361
+ const changes = (0, import_diff3.diffLines)(oldContent, newContent);
14362
+ const lines = [];
14363
+ for (const change of changes) {
14364
+ const trimmedValue = change.value.replace(/\n$/, "");
14365
+ const changeLines = trimmedValue.split("\n");
14366
+ if (change.added) {
14367
+ for (const line of changeLines) {
14368
+ lines.push(source_default.green(` + ${line}`));
14369
+ }
14370
+ } else if (change.removed) {
14371
+ for (const line of changeLines) {
14372
+ lines.push(source_default.red(` - ${line}`));
14373
+ }
14374
+ }
14375
+ }
14376
+ return {
14377
+ lines,
14378
+ hasChanges: lines.length > 0
14379
+ };
14380
+ }
14381
+
14382
+ // apps/cli/src/infra/commands/diffArtefactsHandler.ts
14383
+ init_source();
14384
+ var ARTIFACT_TYPE_LABELS = {
14385
+ command: "Command",
14386
+ standard: "Standard",
14387
+ skill: "Skill"
14388
+ };
14389
+ function subGroupByChangeContent(diffs) {
14390
+ const groups = /* @__PURE__ */ new Map();
14391
+ for (const diff of diffs) {
14392
+ const key = JSON.stringify({ type: diff.type, payload: diff.payload });
14393
+ const group = groups.get(key) ?? [];
14394
+ group.push(diff);
14395
+ groups.set(key, group);
14396
+ }
14397
+ return Array.from(groups.values());
14398
+ }
14399
+ function groupDiffsByArtefact(diffs) {
14400
+ const groups = /* @__PURE__ */ new Map();
14401
+ for (const diff of diffs) {
14402
+ const key = `${diff.artifactType}:${diff.artifactName}`;
14403
+ const group = groups.get(key) ?? [];
14404
+ group.push(diff);
14405
+ groups.set(key, group);
14406
+ }
14407
+ return groups;
14408
+ }
14409
+ function formatDiffPayload(diff, log) {
14410
+ const payload = diff.payload;
14411
+ if (diff.type === "addSkillFile" /* addSkillFile */) {
14412
+ const item = payload.item;
14413
+ if (item.isBase64) {
14414
+ log(source_default.green(" + [binary file]"));
14415
+ } else {
14416
+ for (const line of item.content.split("\n")) {
14417
+ log(source_default.green(` + ${line}`));
14418
+ }
14419
+ }
14420
+ return;
14421
+ }
14422
+ if (diff.type === "deleteSkillFile" /* deleteSkillFile */) {
14423
+ const item = payload.item;
14424
+ if (item.isBase64) {
14425
+ log(source_default.red(" - [binary file]"));
14426
+ } else {
14427
+ const lines2 = item.content.split("\n");
14428
+ const MAX_DELETED_LINES = 3;
14429
+ const preview = lines2.slice(0, MAX_DELETED_LINES);
14430
+ for (const line of preview) {
14431
+ log(source_default.red(` - ${line}`));
14432
+ }
14433
+ if (lines2.length > MAX_DELETED_LINES) {
14434
+ const remaining = lines2.length - MAX_DELETED_LINES;
14435
+ log(source_default.red(` ... and ${remaining} more lines deleted`));
14436
+ }
14437
+ }
14438
+ return;
14439
+ }
14440
+ if (diff.type === "updateSkillFileContent" /* updateSkillFileContent */) {
14441
+ const typedPayload = payload;
14442
+ if (typedPayload.isBase64) {
14443
+ log(source_default.green(" ~ [binary content changed]"));
14444
+ return;
14445
+ }
14446
+ }
14447
+ if (diff.type === "addRule" /* addRule */) {
14448
+ const item = payload.item;
14449
+ log(source_default.green(` + ${item.content}`));
14450
+ return;
14451
+ }
14452
+ if (diff.type === "deleteRule" /* deleteRule */) {
14453
+ const item = payload.item;
14454
+ log(source_default.red(` - ${item.content}`));
14455
+ return;
14456
+ }
14457
+ const oldValue = payload.oldValue;
14458
+ const newValue = payload.newValue;
14459
+ const { lines } = formatContentDiff(oldValue, newValue);
14460
+ for (const line of lines) {
14461
+ log(line);
14462
+ }
14463
+ }
14464
+ async function diffArtefactsHandler(deps) {
14465
+ const { packmindCliHexa, exit, getCwd, log, error, submit } = deps;
14466
+ const cwd = getCwd();
14467
+ let configPackages;
14468
+ let configAgents;
14469
+ try {
14470
+ const fullConfig = await packmindCliHexa.readFullConfig(cwd);
14471
+ if (fullConfig) {
14472
+ configPackages = Object.keys(fullConfig.packages);
14473
+ configAgents = fullConfig.agents;
14474
+ } else {
14475
+ configPackages = [];
14476
+ }
14477
+ } catch (err) {
14478
+ error("ERROR Failed to parse packmind.json");
14479
+ if (err instanceof Error) {
14480
+ error(`ERROR ${err.message}`);
14481
+ } else {
14482
+ error(`ERROR ${String(err)}`);
14483
+ }
14484
+ error("\n\u{1F4A1} Please fix the packmind.json file or delete it to continue.");
14485
+ exit(1);
14486
+ return { diffsFound: 0 };
14487
+ }
14488
+ if (configPackages.length === 0) {
14489
+ log("Usage: packmind-cli diff");
14490
+ log("");
14491
+ log("Compare local command files against the server.");
14492
+ log("Configure packages in packmind.json first.");
14493
+ exit(0);
14494
+ return { diffsFound: 0 };
14495
+ }
14496
+ try {
14497
+ let gitRemoteUrl;
14498
+ let gitBranch;
14499
+ let relativePath;
14500
+ const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
14501
+ if (gitRoot) {
14502
+ try {
14503
+ gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
14504
+ gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
14505
+ relativePath = cwd.startsWith(gitRoot) ? cwd.slice(gitRoot.length) : "/";
14506
+ if (!relativePath.startsWith("/")) {
14507
+ relativePath = "/" + relativePath;
14508
+ }
14509
+ if (!relativePath.endsWith("/")) {
14510
+ relativePath = relativePath + "/";
14511
+ }
14512
+ } catch (err) {
14513
+ logWarningConsole(
14514
+ `Failed to collect git info: ${err instanceof Error ? err.message : String(err)}`
14515
+ );
14516
+ }
14517
+ }
14518
+ if (!gitRemoteUrl || !gitBranch || !relativePath) {
14519
+ error(
14520
+ "\n\u274C Could not determine git repository info. The diff command requires a git repository with a remote configured."
14521
+ );
14522
+ exit(1);
14523
+ return { diffsFound: 0 };
14524
+ }
14525
+ const packageCount = configPackages.length;
14526
+ const packageWord = packageCount === 1 ? "package" : "packages";
14527
+ logInfoConsole(
14528
+ `Comparing ${packageCount} ${packageWord}: ${configPackages.join(", ")}...`
14529
+ );
14530
+ const diffs = await packmindCliHexa.diffArtefacts({
14531
+ baseDirectory: cwd,
14532
+ packagesSlugs: configPackages,
14533
+ gitRemoteUrl,
14534
+ gitBranch,
14535
+ relativePath,
14536
+ agents: configAgents
14537
+ });
14538
+ if (diffs.length === 0) {
14539
+ log("No changes found.");
14540
+ if (submit) {
14541
+ logInfoConsole("No changes to submit.");
14542
+ }
14543
+ exit(0);
14544
+ return { diffsFound: 0 };
14545
+ }
14546
+ log(formatHeader(`
14547
+ Changes found:
14548
+ `));
14549
+ const groups = groupDiffsByArtefact(diffs);
14550
+ for (const [, groupDiffs] of groups) {
14551
+ const { artifactType, artifactName } = groupDiffs[0];
14552
+ const typeLabel = ARTIFACT_TYPE_LABELS[artifactType];
14553
+ log(formatBold(`${typeLabel} "${artifactName}"`));
14554
+ const subGroups = subGroupByChangeContent(groupDiffs);
14555
+ for (const subGroup of subGroups) {
14556
+ for (const diff of subGroup) {
14557
+ log(` ${formatFilePath(diff.filePath)}`);
14558
+ }
14559
+ const label = CHANGE_PROPOSAL_TYPE_LABELS[subGroup[0].type] ?? "content changed";
14560
+ log(` - ${label}`);
14561
+ formatDiffPayload(subGroup[0], log);
14562
+ }
14563
+ log("");
14564
+ }
14565
+ const changeCount = diffs.length;
14566
+ const changeWord = changeCount === 1 ? "change" : "changes";
14567
+ const typeSortOrder = {
14568
+ command: 0,
14569
+ skill: 1,
14570
+ standard: 2
14571
+ };
14572
+ const uniqueArtefacts = /* @__PURE__ */ new Map();
14573
+ for (const [key, groupDiffs] of groups) {
14574
+ if (!uniqueArtefacts.has(key)) {
14575
+ uniqueArtefacts.set(key, {
14576
+ type: groupDiffs[0].artifactType,
14577
+ name: groupDiffs[0].artifactName
14578
+ });
14579
+ }
14580
+ }
14581
+ const sortedArtefacts = Array.from(uniqueArtefacts.values()).sort(
14582
+ (a, b) => typeSortOrder[a.type] - typeSortOrder[b.type] || a.name.localeCompare(b.name, void 0, { sensitivity: "base" })
14583
+ );
14584
+ const artefactCount = sortedArtefacts.length;
14585
+ const artefactWord = artefactCount === 1 ? "artefact" : "artefacts";
14586
+ logWarningConsole(
14587
+ `Summary: ${changeCount} ${changeWord} found on ${artefactCount} ${artefactWord}:`
14588
+ );
14589
+ for (const artefact of sortedArtefacts) {
14590
+ const typeLabel = ARTIFACT_TYPE_LABELS[artefact.type];
14591
+ logWarningConsole(`* ${typeLabel} "${artefact.name}"`);
14592
+ }
14593
+ if (submit) {
14594
+ const groupedDiffs = Array.from(groupDiffsByArtefact(diffs).values());
14595
+ const result = await packmindCliHexa.submitDiffs(groupedDiffs);
14596
+ for (const err of result.errors) {
14597
+ if (err.code === "ChangeProposalPayloadMismatchError") {
14598
+ logErrorConsole(
14599
+ `Failed to submit "${err.name}": ${err.artifactType ?? "artifact"} is outdated, please run \`packmind-cli install\` to update it`
14600
+ );
14601
+ } else {
14602
+ logErrorConsole(`Failed to submit "${err.name}": ${err.message}`);
14603
+ }
14604
+ }
14605
+ const summaryParts = [];
14606
+ if (result.submitted > 0) {
14607
+ summaryParts.push(`${result.submitted} submitted`);
14608
+ }
14609
+ if (result.alreadySubmitted > 0) {
14610
+ summaryParts.push(`${result.alreadySubmitted} already submitted`);
14611
+ }
14612
+ if (result.errors.length > 0) {
14613
+ const errorWord = result.errors.length === 1 ? "error" : "errors";
14614
+ summaryParts.push(`${result.errors.length} ${errorWord}`);
14615
+ }
14616
+ if (summaryParts.length > 0) {
14617
+ const summaryMessage = `Summary: ${summaryParts.join(", ")}`;
14618
+ if (result.errors.length === 0 && result.alreadySubmitted === 0) {
14619
+ logSuccessConsole(summaryMessage);
14620
+ } else if (result.errors.length > 0 && result.submitted > 0 || result.alreadySubmitted > 0) {
14621
+ logWarningConsole(summaryMessage);
14622
+ } else {
14623
+ logErrorConsole(summaryMessage);
14624
+ }
14625
+ }
14626
+ }
14627
+ exit(0);
14628
+ return { diffsFound: changeCount };
14629
+ } catch (err) {
14630
+ error("\n\u274C Failed to diff:");
14631
+ if (err instanceof Error) {
14632
+ error(` ${err.message}`);
14633
+ } else {
14634
+ error(` ${String(err)}`);
14635
+ }
14636
+ exit(1);
14637
+ return { diffsFound: 0 };
14638
+ }
14639
+ }
14640
+
14641
+ // apps/cli/src/infra/commands/DiffCommand.ts
14642
+ var diffCommand = (0, import_cmd_ts19.command)({
14643
+ name: "diff",
14644
+ description: "Show differences between local command files and server content",
14645
+ args: {
14646
+ submit: (0, import_cmd_ts19.flag)({
14647
+ long: "submit",
14648
+ description: "Submit detected changes as change proposals"
14649
+ })
14650
+ },
14651
+ handler: async ({ submit }) => {
14652
+ const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
14653
+ const packmindCliHexa = new PackmindCliHexa(packmindLogger);
14654
+ await diffArtefactsHandler({
14655
+ packmindCliHexa,
14656
+ exit: process.exit,
14657
+ getCwd: () => process.cwd(),
14658
+ log: console.log,
14659
+ error: console.error,
14660
+ submit
14661
+ });
14662
+ }
14663
+ });
14664
+
13218
14665
  // apps/cli/src/infra/commands/PackagesCommand.ts
13219
- var import_cmd_ts22 = __toESM(require_cjs());
14666
+ var import_cmd_ts23 = __toESM(require_cjs());
13220
14667
 
13221
14668
  // apps/cli/src/infra/commands/CreatePackageCommand.ts
13222
- var import_cmd_ts19 = __toESM(require_cjs());
14669
+ var import_cmd_ts20 = __toESM(require_cjs());
13223
14670
 
13224
14671
  // apps/cli/src/infra/commands/createPackageHandler.ts
13225
14672
  function buildWebappUrl2(host, orgSlug, packageId) {
@@ -13268,15 +14715,15 @@ var CreatePackageUseCase = class {
13268
14715
  constructor(gateway) {
13269
14716
  this.gateway = gateway;
13270
14717
  }
13271
- async execute(command20) {
14718
+ async execute(command21) {
13272
14719
  const space = await this.gateway.spaces.getGlobal();
13273
14720
  const result = await this.gateway.packages.create({
13274
14721
  spaceId: space.id,
13275
- name: command20.name,
13276
- description: command20.description ?? "",
14722
+ name: command21.name,
14723
+ description: command21.description ?? "",
13277
14724
  recipeIds: [],
13278
14725
  standardIds: [],
13279
- originSkill: command20.originSkill
14726
+ originSkill: command21.originSkill
13280
14727
  });
13281
14728
  return {
13282
14729
  packageId: result.package.id,
@@ -13287,20 +14734,20 @@ var CreatePackageUseCase = class {
13287
14734
  };
13288
14735
 
13289
14736
  // apps/cli/src/infra/commands/CreatePackageCommand.ts
13290
- var createPackageCommand = (0, import_cmd_ts19.command)({
14737
+ var createPackageCommand = (0, import_cmd_ts20.command)({
13291
14738
  name: "create",
13292
14739
  description: "Create a new package",
13293
14740
  args: {
13294
- name: (0, import_cmd_ts19.positional)({
14741
+ name: (0, import_cmd_ts20.positional)({
13295
14742
  displayName: "name",
13296
14743
  description: "Name of the package to create",
13297
- type: import_cmd_ts19.string
14744
+ type: import_cmd_ts20.string
13298
14745
  }),
13299
- description: (0, import_cmd_ts19.option)({
14746
+ description: (0, import_cmd_ts20.option)({
13300
14747
  long: "description",
13301
14748
  short: "d",
13302
14749
  description: "Description of the package (optional)",
13303
- type: (0, import_cmd_ts19.optional)(import_cmd_ts19.string)
14750
+ type: (0, import_cmd_ts20.optional)(import_cmd_ts20.string)
13304
14751
  }),
13305
14752
  originSkill: originSkillOption
13306
14753
  },
@@ -13349,7 +14796,7 @@ var createPackageCommand = (0, import_cmd_ts19.command)({
13349
14796
  });
13350
14797
 
13351
14798
  // apps/cli/src/infra/commands/AddToPackageCommand.ts
13352
- var import_cmd_ts20 = __toESM(require_cjs());
14799
+ var import_cmd_ts21 = __toESM(require_cjs());
13353
14800
 
13354
14801
  // apps/cli/src/domain/errors/ItemNotFoundError.ts
13355
14802
  var ItemNotFoundError = class extends Error {
@@ -13366,8 +14813,8 @@ var AddToPackageUseCase = class {
13366
14813
  constructor(gateway) {
13367
14814
  this.gateway = gateway;
13368
14815
  }
13369
- async execute(command20) {
13370
- const { packageSlug, itemType, itemSlugs } = command20;
14816
+ async execute(command21) {
14817
+ const { packageSlug, itemType, itemSlugs } = command21;
13371
14818
  const space = await this.gateway.spaces.getGlobal();
13372
14819
  const packages = await this.gateway.packages.list({});
13373
14820
  const pkg = packages.packages.find((pkg2) => pkg2.slug === packageSlug);
@@ -13384,7 +14831,7 @@ var AddToPackageUseCase = class {
13384
14831
  standardIds: [],
13385
14832
  recipeIds: [],
13386
14833
  skillIds: [],
13387
- originSkill: command20.originSkill
14834
+ originSkill: command21.originSkill
13388
14835
  };
13389
14836
  if (itemType === "standard") {
13390
14837
  addCommand.standardIds = ids.map(createStandardId);
@@ -13429,7 +14876,7 @@ var AddToPackageUseCase = class {
13429
14876
  }
13430
14877
  async findCommandBySlug(slug, spaceId) {
13431
14878
  const commands = await this.gateway.commands.list({ spaceId });
13432
- return commands.recipes.find((command20) => command20.slug === slug) ?? null;
14879
+ return commands.recipes.find((command21) => command21.slug === slug) ?? null;
13433
14880
  }
13434
14881
  async findSkillBySlug(slug, spaceId) {
13435
14882
  const skills = await this.gateway.skills.list({ spaceId });
@@ -13485,29 +14932,29 @@ async function addToPackageHandler(packageSlug, itemType, itemSlugs, useCase, or
13485
14932
  }
13486
14933
 
13487
14934
  // apps/cli/src/infra/commands/AddToPackageCommand.ts
13488
- var addToPackageCommand = (0, import_cmd_ts20.command)({
14935
+ var addToPackageCommand = (0, import_cmd_ts21.command)({
13489
14936
  name: "add",
13490
14937
  description: "Add standards, commands, or skills to a package",
13491
14938
  args: {
13492
- to: (0, import_cmd_ts20.option)({
14939
+ to: (0, import_cmd_ts21.option)({
13493
14940
  long: "to",
13494
14941
  description: "Target package slug",
13495
- type: import_cmd_ts20.string
14942
+ type: import_cmd_ts21.string
13496
14943
  }),
13497
- standards: (0, import_cmd_ts20.multioption)({
14944
+ standards: (0, import_cmd_ts21.multioption)({
13498
14945
  long: "standard",
13499
14946
  description: "Standard slug(s) to add",
13500
- type: (0, import_cmd_ts20.array)(import_cmd_ts20.string)
14947
+ type: (0, import_cmd_ts21.array)(import_cmd_ts21.string)
13501
14948
  }),
13502
- commands: (0, import_cmd_ts20.multioption)({
14949
+ commands: (0, import_cmd_ts21.multioption)({
13503
14950
  long: "command",
13504
14951
  description: "Command slug(s) to add",
13505
- type: (0, import_cmd_ts20.array)(import_cmd_ts20.string)
14952
+ type: (0, import_cmd_ts21.array)(import_cmd_ts21.string)
13506
14953
  }),
13507
- skills: (0, import_cmd_ts20.multioption)({
14954
+ skills: (0, import_cmd_ts21.multioption)({
13508
14955
  long: "skill",
13509
14956
  description: "Skill slug(s) to add",
13510
- type: (0, import_cmd_ts20.array)(import_cmd_ts20.string)
14957
+ type: (0, import_cmd_ts21.array)(import_cmd_ts21.string)
13511
14958
  }),
13512
14959
  originSkill: originSkillOption
13513
14960
  },
@@ -13551,8 +14998,8 @@ var addToPackageCommand = (0, import_cmd_ts20.command)({
13551
14998
  });
13552
14999
 
13553
15000
  // apps/cli/src/infra/commands/listPackagesCommand.ts
13554
- var import_cmd_ts21 = __toESM(require_cjs());
13555
- var listPackagesCommand = (0, import_cmd_ts21.command)({
15001
+ var import_cmd_ts22 = __toESM(require_cjs());
15002
+ var listPackagesCommand = (0, import_cmd_ts22.command)({
13556
15003
  name: "list",
13557
15004
  description: "List available packages",
13558
15005
  args: {},
@@ -13571,7 +15018,7 @@ var listPackagesCommand = (0, import_cmd_ts21.command)({
13571
15018
  });
13572
15019
 
13573
15020
  // apps/cli/src/infra/commands/PackagesCommand.ts
13574
- var packagesCommand = (0, import_cmd_ts22.subcommands)({
15021
+ var packagesCommand = (0, import_cmd_ts23.subcommands)({
13575
15022
  name: "packages",
13576
15023
  description: "Manage packages",
13577
15024
  cmds: {
@@ -13582,14 +15029,14 @@ var packagesCommand = (0, import_cmd_ts22.subcommands)({
13582
15029
  });
13583
15030
 
13584
15031
  // apps/cli/src/infra/commands/config/ConfigCommand.ts
13585
- var import_cmd_ts24 = __toESM(require_cjs());
15032
+ var import_cmd_ts25 = __toESM(require_cjs());
13586
15033
 
13587
15034
  // apps/cli/src/infra/commands/config/ConfigAgentsCommand.ts
13588
- var import_cmd_ts23 = __toESM(require_cjs());
15035
+ var import_cmd_ts24 = __toESM(require_cjs());
13589
15036
 
13590
15037
  // apps/cli/src/application/services/AgentArtifactDetectionService.ts
13591
- var fs15 = __toESM(require("fs/promises"));
13592
- var path12 = __toESM(require("path"));
15038
+ var fs18 = __toESM(require("fs/promises"));
15039
+ var path16 = __toESM(require("path"));
13593
15040
  var AGENT_ARTIFACT_CHECKS = [
13594
15041
  { agent: "claude", paths: [".claude"] },
13595
15042
  { agent: "cursor", paths: [".cursor"] },
@@ -13607,7 +15054,7 @@ var AgentArtifactDetectionService = class {
13607
15054
  const detected = [];
13608
15055
  for (const check of AGENT_ARTIFACT_CHECKS) {
13609
15056
  for (const relativePath of check.paths) {
13610
- const fullPath = path12.join(baseDirectory, relativePath);
15057
+ const fullPath = path16.join(baseDirectory, relativePath);
13611
15058
  const exists = await this.pathExists(fullPath);
13612
15059
  if (exists) {
13613
15060
  detected.push({
@@ -13622,7 +15069,7 @@ var AgentArtifactDetectionService = class {
13622
15069
  }
13623
15070
  async pathExists(filePath) {
13624
15071
  try {
13625
- await fs15.access(filePath);
15072
+ await fs18.access(filePath);
13626
15073
  return true;
13627
15074
  } catch {
13628
15075
  return false;
@@ -13745,7 +15192,7 @@ async function getPreselectedAgents(deps) {
13745
15192
  }
13746
15193
 
13747
15194
  // apps/cli/src/infra/commands/config/ConfigAgentsCommand.ts
13748
- var configAgentsCommand = (0, import_cmd_ts23.command)({
15195
+ var configAgentsCommand = (0, import_cmd_ts24.command)({
13749
15196
  name: "agents",
13750
15197
  description: "Configure which coding agents to generate artifacts for",
13751
15198
  args: {},
@@ -13765,7 +15212,7 @@ var configAgentsCommand = (0, import_cmd_ts23.command)({
13765
15212
  });
13766
15213
 
13767
15214
  // apps/cli/src/infra/commands/config/ConfigCommand.ts
13768
- var configCommand = (0, import_cmd_ts24.subcommands)({
15215
+ var configCommand = (0, import_cmd_ts25.subcommands)({
13769
15216
  name: "config",
13770
15217
  description: "Manage Packmind configuration",
13771
15218
  cmds: {
@@ -13774,7 +15221,7 @@ var configCommand = (0, import_cmd_ts24.subcommands)({
13774
15221
  });
13775
15222
 
13776
15223
  // apps/cli/src/infra/commands/InitCommand.ts
13777
- var import_cmd_ts25 = __toESM(require_cjs());
15224
+ var import_cmd_ts26 = __toESM(require_cjs());
13778
15225
 
13779
15226
  // apps/cli/src/infra/commands/initHandler.ts
13780
15227
  async function initHandler(deps) {
@@ -13831,7 +15278,7 @@ async function initHandler(deps) {
13831
15278
 
13832
15279
  // apps/cli/src/infra/commands/InitCommand.ts
13833
15280
  var { version: CLI_VERSION3 } = require_package();
13834
- var initCommand = (0, import_cmd_ts25.command)({
15281
+ var initCommand = (0, import_cmd_ts26.command)({
13835
15282
  name: "init",
13836
15283
  description: "Initialize Packmind in the current project",
13837
15284
  args: {},
@@ -13864,20 +15311,20 @@ function findEnvFile() {
13864
15311
  const currentDir = process.cwd();
13865
15312
  const gitService = new GitService();
13866
15313
  const gitRoot = gitService.getGitRepositoryRootSync(currentDir);
13867
- const filesystemRoot = path13.parse(currentDir).root;
15314
+ const filesystemRoot = path17.parse(currentDir).root;
13868
15315
  const stopDir = gitRoot ?? filesystemRoot;
13869
15316
  let searchDir = currentDir;
13870
- let parentDir = path13.dirname(searchDir);
15317
+ let parentDir = path17.dirname(searchDir);
13871
15318
  while (searchDir !== parentDir) {
13872
- const envPath2 = path13.join(searchDir, ".env");
13873
- if (fs16.existsSync(envPath2)) {
15319
+ const envPath2 = path17.join(searchDir, ".env");
15320
+ if (fs19.existsSync(envPath2)) {
13874
15321
  return envPath2;
13875
15322
  }
13876
15323
  if (searchDir === stopDir) {
13877
15324
  return null;
13878
15325
  }
13879
15326
  searchDir = parentDir;
13880
- parentDir = path13.dirname(searchDir);
15327
+ parentDir = path17.dirname(searchDir);
13881
15328
  }
13882
15329
  return null;
13883
15330
  }
@@ -13897,12 +15344,13 @@ if (args.includes("--version") || args.includes("-v")) {
13897
15344
  logConsole(`packmind-cli version ${CLI_VERSION4}`);
13898
15345
  process.exit(0);
13899
15346
  }
13900
- var app = (0, import_cmd_ts26.subcommands)({
15347
+ var app = (0, import_cmd_ts27.subcommands)({
13901
15348
  name: "packmind-cli",
13902
15349
  description: "Packmind CLI tool",
13903
15350
  cmds: {
13904
15351
  commands: commandsCommand,
13905
15352
  config: configCommand,
15353
+ diff: diffCommand,
13906
15354
  init: initCommand,
13907
15355
  install: installCommand,
13908
15356
  lint: lintCommand,
@@ -13918,7 +15366,7 @@ var app = (0, import_cmd_ts26.subcommands)({
13918
15366
  whoami: whoamiCommand
13919
15367
  }
13920
15368
  });
13921
- (0, import_cmd_ts26.run)(app, args).catch((error) => {
15369
+ (0, import_cmd_ts27.run)(app, args).catch((error) => {
13922
15370
  logErrorConsole(error.message);
13923
15371
  process.exit(1);
13924
15372
  });