@lahat-group/cli 1.1.3 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7555,7 +7555,8 @@ var ShelfModuleSchema = BaseModuleSchema.extend({
7555
7555
  });
7556
7556
  var RailModuleSchema = BaseModuleSchema.extend({
7557
7557
  type: external_exports.literal("rail"),
7558
- railVariant: external_exports.enum(["tall", "short"]).optional()
7558
+ railVariant: external_exports.enum(["tall", "short"]).optional(),
7559
+ railKind: external_exports.enum(["standard", "pull-down"]).optional()
7559
7560
  });
7560
7561
  var DrawerInternalModuleSchema = BaseModuleSchema.extend({
7561
7562
  type: external_exports.literal("drawer-internal"),
@@ -9064,6 +9065,19 @@ function getColumnDoorCount(bodyWidthCm) {
9064
9065
 
9065
9066
  // ../../packages/shared/src/describe.ts
9066
9067
  init_esm_shims();
9068
+
9069
+ // ../../packages/shared/src/hangingRail.ts
9070
+ init_esm_shims();
9071
+ var FRONTAL_RAIL_MAX_BODY_DEPTH_CM = 55;
9072
+ function allowsPullDownRail(bodyDepthCm) {
9073
+ return bodyDepthCm > FRONTAL_RAIL_MAX_BODY_DEPTH_CM;
9074
+ }
9075
+ function resolveRailPieceKind(railKind, bodyDepthCm) {
9076
+ if (!allowsPullDownRail(bodyDepthCm)) return "frontal";
9077
+ return railKind === "pull-down" ? "pull-down" : "standard";
9078
+ }
9079
+
9080
+ // ../../packages/shared/src/describe.ts
9067
9081
  var POSITION_LABELS = {
9068
9082
  "left-corner": "Left corner",
9069
9083
  "right-corner": "Right corner",
@@ -9246,7 +9260,8 @@ function groupModulesEn(modules, columnDepthCm, hasDoors) {
9246
9260
  break;
9247
9261
  case "rail": {
9248
9262
  const variant = mod.railVariant ?? "tall";
9249
- rails.push(variant);
9263
+ const kind = resolveRailPieceKind(mod.railKind, columnDepthCm);
9264
+ rails.push(kind === "standard" ? variant : `${variant}, ${kind}`);
9250
9265
  break;
9251
9266
  }
9252
9267
  case "drawer-internal":
@@ -9276,6 +9291,7 @@ function groupModulesHe(modules, columnDepthCm, hasDoors) {
9276
9291
  const rails = [];
9277
9292
  const drawersByHeight = /* @__PURE__ */ new Map();
9278
9293
  const RAIL_VARIANT_HE = { tall: "\u05D2\u05D1\u05D5\u05D4", short: "\u05E0\u05DE\u05D5\u05DA" };
9294
+ const RAIL_KIND_HE = { "pull-down": "\u05E1\u05E8\u05D5\u05D5\u05D8\u05D5", frontal: "\u05DE\u05D5\u05D8 \u05EA\u05DC\u05D9\u05D9\u05D4 \u05E7\u05D3\u05DE\u05D9" };
9279
9295
  const derivedDepth = deriveDrawerDepthCm(columnDepthCm * 10, hasDoors);
9280
9296
  for (const mod of modules) {
9281
9297
  switch (mod.type) {
@@ -9284,7 +9300,9 @@ function groupModulesHe(modules, columnDepthCm, hasDoors) {
9284
9300
  break;
9285
9301
  case "rail": {
9286
9302
  const variant = mod.railVariant ?? "tall";
9287
- rails.push(RAIL_VARIANT_HE[variant] ?? variant);
9303
+ const variantHe = RAIL_VARIANT_HE[variant] ?? variant;
9304
+ const kindHe = RAIL_KIND_HE[resolveRailPieceKind(mod.railKind, columnDepthCm)];
9305
+ rails.push(kindHe ? `${variantHe}, ${kindHe}` : variantHe);
9288
9306
  break;
9289
9307
  }
9290
9308
  case "drawer-internal":
@@ -9406,6 +9424,28 @@ init_esm_shims();
9406
9424
  // ../../packages/shared/src/permissions.ts
9407
9425
  init_esm_shims();
9408
9426
 
9427
+ // ../../packages/shared/src/agentScopes.ts
9428
+ init_esm_shims();
9429
+ var AGENT_SCOPES = {
9430
+ "profile:read": { he: "\u05DC\u05E8\u05D0\u05D5\u05EA \u05D0\u05EA \u05D4\u05E9\u05DD \u05D5\u05D4\u05D0\u05D9\u05DE\u05D9\u05D9\u05DC \u05E9\u05DC\u05DA", en: "See your name and email" },
9431
+ "projects:read": { he: "\u05DC\u05E8\u05D0\u05D5\u05EA \u05D0\u05EA \u05D4\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8\u05D9\u05DD \u05E9\u05DC\u05DA", en: "See your projects" },
9432
+ "projects:write": { he: "\u05DC\u05D9\u05E6\u05D5\u05E8 \u05D5\u05DC\u05E2\u05E8\u05D5\u05DA \u05E4\u05E8\u05D5\u05D9\u05E7\u05D8\u05D9\u05DD", en: "Create and edit projects" },
9433
+ "customers:read": { he: "\u05DC\u05E8\u05D0\u05D5\u05EA \u05D0\u05EA \u05D4\u05DC\u05E7\u05D5\u05D7\u05D5\u05EA \u05E9\u05DC\u05DA", en: "See your customers" },
9434
+ "customers:write": { he: "\u05DC\u05D9\u05E6\u05D5\u05E8 \u05D5\u05DC\u05E2\u05E8\u05D5\u05DA \u05DC\u05E7\u05D5\u05D7\u05D5\u05EA", en: "Create and edit customers" },
9435
+ "designs:read": { he: "\u05DC\u05E8\u05D0\u05D5\u05EA \u05D0\u05EA \u05EA\u05DB\u05E0\u05D5\u05E0\u05D9 \u05D4\u05D0\u05E8\u05D5\u05E0\u05D5\u05EA \u05E9\u05DC\u05DA", en: "See your wardrobe designs" },
9436
+ "designs:write": { he: "\u05DC\u05D9\u05E6\u05D5\u05E8 \u05D5\u05DC\u05E2\u05E8\u05D5\u05DA \u05EA\u05DB\u05E0\u05D5\u05E0\u05D9 \u05D0\u05E8\u05D5\u05E0\u05D5\u05EA", en: "Create and edit wardrobe designs" },
9437
+ "price:read": { he: "\u05DC\u05EA\u05DE\u05D7\u05E8 \u05EA\u05E6\u05D5\u05E8\u05EA \u05D0\u05E8\u05D5\u05DF", en: "Price a configuration" },
9438
+ "chat:read": { he: "\u05DC\u05E7\u05E8\u05D5\u05D0 \u05D4\u05D5\u05D3\u05E2\u05D5\u05EA \u05D1\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8\u05D9\u05DD \u05E9\u05DC\u05DA", en: "Read project messages" },
9439
+ "chat:write": { he: "\u05DC\u05DB\u05EA\u05D5\u05D1 \u05D4\u05D5\u05D3\u05E2\u05D5\u05EA \u05D1\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8\u05D9\u05DD \u05E9\u05DC\u05DA", en: "Post project messages" },
9440
+ "files:write": { he: "\u05DC\u05D4\u05E2\u05DC\u05D5\u05EA \u05EA\u05DE\u05D5\u05E0\u05D5\u05EA \u05E9\u05DC \u05EA\u05DB\u05E0\u05D5\u05E0\u05D9\u05DD", en: "Upload design images" },
9441
+ "quotations:write": { he: "\u05DC\u05D4\u05E4\u05D9\u05E7 \u05D4\u05E6\u05E2\u05EA \u05DE\u05D7\u05D9\u05E8", en: "Generate a quotation PDF" },
9442
+ "orders:read": { he: "\u05DC\u05E8\u05D0\u05D5\u05EA \u05D0\u05EA \u05D4\u05D4\u05D6\u05DE\u05E0\u05D5\u05EA \u05E9\u05DC\u05DA", en: "See your orders" },
9443
+ "orders:write": { he: "\u05DC\u05D4\u05DB\u05D9\u05DF \u05D8\u05D9\u05D5\u05D8\u05EA \u05D4\u05D6\u05DE\u05E0\u05D4 \u05DC\u05D0\u05D9\u05E9\u05D5\u05E8\u05DA", en: "Draft an order for you to confirm" },
9444
+ "orders:commit": { he: "\u05DC\u05D0\u05E9\u05E8 \u05D4\u05D6\u05DE\u05E0\u05D4 \u05D1\u05E9\u05DE\u05DA", en: "Confirm an order on your behalf" },
9445
+ "invitations:write": { he: "\u05DC\u05D4\u05D6\u05DE\u05D9\u05DF \u05D0\u05E0\u05E9\u05D9\u05DD \u05DC\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8\u05D9\u05DD \u05E9\u05DC\u05DA", en: "Invite people to your projects" }
9446
+ };
9447
+ var ALL_AGENT_SCOPES = Object.keys(AGENT_SCOPES);
9448
+
9409
9449
  // ../../packages/shared/src/legal.ts
9410
9450
  init_esm_shims();
9411
9451
 
@@ -9804,13 +9844,19 @@ var POOL_SIZE_MULTIPLIER = 128;
9804
9844
  var pool;
9805
9845
  var poolOffset;
9806
9846
  function fillPool(bytes) {
9807
- if (!pool || pool.length < bytes) {
9808
- pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
9809
- crypto.getRandomValues(pool);
9810
- poolOffset = 0;
9811
- } else if (poolOffset + bytes > pool.length) {
9812
- crypto.getRandomValues(pool);
9813
- poolOffset = 0;
9847
+ if (bytes < 0) throw new RangeError("Wrong ID size");
9848
+ try {
9849
+ if (!pool || pool.length < bytes) {
9850
+ pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
9851
+ crypto.getRandomValues(pool);
9852
+ poolOffset = 0;
9853
+ } else if (poolOffset + bytes > pool.length) {
9854
+ crypto.getRandomValues(pool);
9855
+ poolOffset = 0;
9856
+ }
9857
+ } catch (e) {
9858
+ pool = void 0;
9859
+ throw e;
9814
9860
  }
9815
9861
  poolOffset += bytes;
9816
9862
  }
@@ -10484,6 +10530,7 @@ function placementsToModules(placements, H) {
10484
10530
  type: "rail",
10485
10531
  height: 0,
10486
10532
  railVariant: p.railVariant ?? "tall",
10533
+ railKind: p.railKind ?? "standard",
10487
10534
  spacingAbove,
10488
10535
  spacingBelow
10489
10536
  });
@@ -10582,7 +10629,7 @@ function generateCustomLayout(options, H) {
10582
10629
  const clearance = railType === "tall" ? RAIL_CLEARANCE_TALL_CM : RAIL_CLEARANCE_SHORT_CM;
10583
10630
  const n1 = options.railUpperShelfCount ?? 0;
10584
10631
  const railY = options.railAtCeiling ? H - RAIL_CLEARANCE_ABOVE_MIN_CM : grid[Math.max(0, grid.length - 1 - n1)] - RAIL_CLEARANCE_ABOVE_MIN_CM;
10585
- placements.push({ type: "rail", y: railY, height: 0, railVariant: railType });
10632
+ placements.push({ type: "rail", y: railY, height: 0, railVariant: railType, railKind: options.railKind });
10586
10633
  hangingZones.push({ top: railY, bottom: railY - clearance });
10587
10634
  if (options.hasSecondRail && options.secondRailType) {
10588
10635
  const secondClearance = options.secondRailType === "tall" ? RAIL_CLEARANCE_TALL_CM : RAIL_CLEARANCE_SHORT_CM;
@@ -10593,7 +10640,7 @@ function generateCustomLayout(options, H) {
10593
10640
  if (anchorIdx2 >= 0) {
10594
10641
  const secondRailY = grid[anchorIdx2] - RAIL_CLEARANCE_ABOVE_MIN_CM;
10595
10642
  if (secondRailY > 0) {
10596
- placements.push({ type: "rail", y: secondRailY, height: 0, railVariant: options.secondRailType });
10643
+ placements.push({ type: "rail", y: secondRailY, height: 0, railVariant: options.secondRailType, railKind: options.secondRailKind });
10597
10644
  hangingZones.push({ top: secondRailY, bottom: secondRailY - secondClearance });
10598
10645
  }
10599
10646
  }
@@ -11866,7 +11913,7 @@ async function formatCliError(err, json) {
11866
11913
 
11867
11914
  // src/version.ts
11868
11915
  init_esm_shims();
11869
- var CLI_VERSION = "1.1.3";
11916
+ var CLI_VERSION = "1.1.5";
11870
11917
 
11871
11918
  // src/index.ts
11872
11919
  program.name("wardrobe").description("Wardrobe configurator CLI").version(CLI_VERSION);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lahat-group/cli",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "CLI + Claude Skill to build, validate, price, and save wardrobe designs.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
package/skill/SKILL.md CHANGED
@@ -63,15 +63,21 @@ Prefer generating the skeleton with `wardrobe init` rather than hand-writing it
63
63
  `init` fills materials, `ruleVersion`, and a valid column layout for you. Column
64
64
  `id`s are `nanoid()` and are not stable across rebuilds.
65
65
 
66
- ## Guardrails — orders require a human
66
+ ## Guardrails — committing to an order requires a human
67
67
 
68
- - **The CLI cannot place orders.** Ordering is intentionally not an agent verb: the
69
- agent key carries only `designs:read`, `designs:write`, `price:read` — **no order or
70
- admin scope**. Don't attempt to order, or to run admin/catalog operations.
68
+ - **The CLI cannot place orders.** The `wardrobe-cli` client is registered with
69
+ `profile:read`, `projects:read`, `designs:read`, `designs:write`, `price:read` —
70
+ **no order or admin scope** — so every order route answers `403 insufficient_scope`.
71
+ Don't attempt to order, or to run admin/catalog operations.
71
72
  - To turn a saved design into an order, direct the **human** to the web app: they
72
73
  open the project, review the design, and complete the **verify-details** flow —
73
74
  which computes the final price, freezes the PDF, and advances the order. Only a
74
75
  human does this. Your job ends at `apply` (a saved design) plus a clear summary.
76
+ - This is now a **scope** boundary rather than a property of the API surface: other
77
+ registered clients may hold `orders:write` and *draft* an order (status `created` —
78
+ no frozen PDF, no confirmation email). But `orders:commit`, which gates
79
+ `verify-details`, is held by no client at all, so the commitment step stays human
80
+ for every agent. See `docs/bot-api.md`.
75
81
 
76
82
  ## Error handling
77
83