@warmhub/cli 0.88.0 → 0.89.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 (3) hide show
  1. package/README.md +4 -0
  2. package/dist/wh.js +834 -477
  3. package/package.json +1 -1
package/dist/wh.js CHANGED
@@ -19389,6 +19389,19 @@ var ALL_BUILTIN_SHAPE_DEFS = {
19389
19389
  ...BUILTIN_VIEW_SHAPE_DEFS,
19390
19390
  ...BUILTIN_LICENSE_SHAPE_DEFS
19391
19391
  };
19392
+ // ../../packages/rules/src/client-flags.ts
19393
+ var CLIENT_FLAGS_HEADER = "X-WarmHub-Client-Flags";
19394
+ var CLIENT_FLAG_COMPATIBILITY_OVERRIDE = "compatibility-override";
19395
+ var KNOWN_CLIENT_FLAGS = new Set([
19396
+ CLIENT_FLAG_COMPATIBILITY_OVERRIDE
19397
+ ]);
19398
+ var CLIENT_FLAG_TOKEN_RE = /^[a-z0-9-]+$/;
19399
+ function isValidClientFlagToken(token) {
19400
+ return CLIENT_FLAG_TOKEN_RE.test(token);
19401
+ }
19402
+ function serializeClientFlags(flags) {
19403
+ return [...new Set(flags)].sort().join(",");
19404
+ }
19392
19405
  // ../../packages/rules/src/client-header.ts
19393
19406
  var CLIENT_HEADER = "X-WarmHub-Client";
19394
19407
  var WARMHUB_SDK_CLIENT_NAME = "@warmhub/sdk-ts";
@@ -19930,16 +19943,21 @@ function validateComponentManifestCliContract(manifest) {
19930
19943
  }
19931
19944
  return findings;
19932
19945
  }
19946
+ // ../../packages/rules/src/component-manifest-validate-types.ts
19947
+ function failureIfAny(errors, warnings) {
19948
+ const [first, ...rest] = errors;
19949
+ if (first === undefined)
19950
+ return;
19951
+ return { valid: false, errors: [first, ...rest], warnings };
19952
+ }
19953
+
19933
19954
  // ../../packages/rules/src/component-version.ts
19934
19955
  var SEMVER_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
19935
- function isValidSemver(version) {
19936
- return SEMVER_RE.test(version);
19956
+ function parseSemver(version) {
19957
+ return SEMVER_RE.test(version) ? version : null;
19937
19958
  }
19938
- function parse(version) {
19959
+ function decompose(version) {
19939
19960
  const match = SEMVER_RE.exec(version);
19940
- if (!match) {
19941
- throw new Error(`Invalid semver: ${JSON.stringify(version)}`);
19942
- }
19943
19961
  return {
19944
19962
  major: Number(match[1]),
19945
19963
  minor: Number(match[2]),
@@ -19959,6 +19977,8 @@ function comparePrerelease(a, b) {
19959
19977
  for (let i = 0;i < len; i++) {
19960
19978
  const ai = a[i];
19961
19979
  const bi = b[i];
19980
+ if (ai === undefined || bi === undefined)
19981
+ break;
19962
19982
  if (ai === bi)
19963
19983
  continue;
19964
19984
  const aNum = NUMERIC_RE.test(ai);
@@ -19977,8 +19997,8 @@ function comparePrerelease(a, b) {
19977
19997
  return a.length < b.length ? -1 : 1;
19978
19998
  }
19979
19999
  function compareSemver(a, b) {
19980
- const pa = parse(a);
19981
- const pb = parse(b);
20000
+ const pa = decompose(a);
20001
+ const pb = decompose(b);
19982
20002
  if (pa.major !== pb.major)
19983
20003
  return pa.major < pb.major ? -1 : 1;
19984
20004
  if (pa.minor !== pb.minor)
@@ -19989,8 +20009,8 @@ function compareSemver(a, b) {
19989
20009
  }
19990
20010
 
19991
20011
  // ../../packages/rules/src/component-manifest-validate-json.ts
19992
- function fail(errors, warnings = []) {
19993
- return { valid: false, errors, warnings };
20012
+ function failWith(message) {
20013
+ return { valid: false, errors: [message], warnings: [] };
19994
20014
  }
19995
20015
  function isObject2(v) {
19996
20016
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -20020,7 +20040,7 @@ function optionalStringArray(obj, field, path, errors) {
20020
20040
  }
20021
20041
  function validateComponentJson(data) {
20022
20042
  if (!isObject2(data)) {
20023
- return fail(["component.json must be a JSON object"]);
20043
+ return failWith("component.json must be a JSON object");
20024
20044
  }
20025
20045
  const errors = [];
20026
20046
  requireString(data, "id", "component", errors);
@@ -20029,11 +20049,8 @@ function validateComponentJson(data) {
20029
20049
  optionalString(data, "description", "component", errors);
20030
20050
  optionalString(data, "author", "component", errors);
20031
20051
  optionalStringArray(data, "tags", "component", errors);
20032
- if (errors.length > 0)
20033
- return fail(errors);
20034
- return {
20052
+ return failureIfAny(errors, []) ?? {
20035
20053
  valid: true,
20036
- errors: [],
20037
20054
  warnings: [],
20038
20055
  value: data
20039
20056
  };
@@ -20067,7 +20084,7 @@ function validateManifestComponent(data, errors) {
20067
20084
  requireString(data, "name", "manifest.component", errors);
20068
20085
  requireString(data, "version", "manifest.component", errors);
20069
20086
  if (typeof data.version === "string" && data.version.length > 0) {
20070
- if (!isValidSemver(data.version)) {
20087
+ if (parseSemver(data.version) === null) {
20071
20088
  errors.push(`manifest.component.version "${data.version}" is not valid semver (e.g. 1.2.3, 1.2.3-rc.1)`);
20072
20089
  }
20073
20090
  }
@@ -20260,7 +20277,7 @@ function validateTeardown(teardown, path, errors) {
20260
20277
  }
20261
20278
  function validateManifestJson(data) {
20262
20279
  if (!isObject2(data)) {
20263
- return fail(["manifest.json must be a JSON object"]);
20280
+ return failWith("manifest.json must be a JSON object");
20264
20281
  }
20265
20282
  const errors = [];
20266
20283
  const warnings = [];
@@ -20313,11 +20330,8 @@ function validateManifestJson(data) {
20313
20330
  if (data.cli !== undefined) {
20314
20331
  errors.push(...validateComponentManifestCliShape(data.cli).map((finding) => finding.message));
20315
20332
  }
20316
- if (errors.length > 0)
20317
- return { valid: false, errors, warnings };
20318
- return {
20333
+ return failureIfAny(errors, warnings) ?? {
20319
20334
  valid: true,
20320
- errors: [],
20321
20335
  warnings,
20322
20336
  value: data
20323
20337
  };
@@ -20538,17 +20552,27 @@ function joinFieldIdentityPath(...segments) {
20538
20552
  function joinFieldPathWithEscaper(escapeSegment, segments) {
20539
20553
  return segments.map((segment) => typeof segment === "number" ? `[${segment}]` : escapeSegment(segment)).join(".").replace(/\.\[/g, "[");
20540
20554
  }
20541
- // ../../packages/rules/src/tokens.ts
20542
- var COMMIT_TOKEN_SYNTAX_REMOVED_MESSAGE = "$N/#N commit-token syntax is no longer supported. Use explicit names and explicit wrefs. For assertions about newly created things, create the thing with a deterministic name and set about to that wref in the same commit.";
20543
- var ANY_TOKEN_RE = /[$#]\d+/;
20544
- function hasAnyTokens(s) {
20545
- return ANY_TOKEN_RE.test(s);
20555
+ // ../../packages/rules/src/org-qualified-ref.ts
20556
+ function splitOrgQualified(ref) {
20557
+ const parts = ref.split("/");
20558
+ if (parts.length !== 2)
20559
+ return null;
20560
+ const [first, second] = parts;
20561
+ if (!first || !second)
20562
+ return null;
20563
+ return [first, second];
20564
+ }
20565
+ function parseRepoSlug(ref) {
20566
+ const parts = splitOrgQualified(ref);
20567
+ return parts === null ? null : { org: parts[0], repo: parts[1] };
20568
+ }
20569
+ function parseComponentRef(ref) {
20570
+ const parts = splitOrgQualified(ref);
20571
+ return parts === null ? null : { org: parts[0], name: parts[1] };
20546
20572
  }
20547
-
20548
20573
  // ../../packages/rules/src/preflight-commit.ts
20549
20574
  function preflightCommitDiagnostics(operations, options) {
20550
20575
  const errors = [];
20551
- rejectCommitTokenSyntax(operations, errors, options);
20552
20576
  illegalOpSequences(operations, errors, options?.checkAddAdd ?? true, options);
20553
20577
  return errors;
20554
20578
  }
@@ -20558,33 +20582,6 @@ function sourceOperationIndex(filteredIndex, options) {
20558
20582
  function getOpName(op) {
20559
20583
  return op.name;
20560
20584
  }
20561
- function tokenStringFields(op) {
20562
- const fields = [getOpName(op), op.newName];
20563
- if (typeof op.about === "string") {
20564
- fields.push(op.about);
20565
- }
20566
- if (op.members) {
20567
- fields.push(...op.members);
20568
- }
20569
- return fields;
20570
- }
20571
- function rejectCommitTokenSyntax(operations, errors, options) {
20572
- for (let i = 0;i < operations.length; i++) {
20573
- const op = operations[i];
20574
- if (!op)
20575
- continue;
20576
- for (const field of tokenStringFields(op)) {
20577
- if (field && hasAnyTokens(field)) {
20578
- errors.push({
20579
- code: "COMMIT_TOKEN_SYNTAX_REMOVED",
20580
- operationIndex: sourceOperationIndex(i, options),
20581
- message: COMMIT_TOKEN_SYNTAX_REMOVED_MESSAGE
20582
- });
20583
- break;
20584
- }
20585
- }
20586
- }
20587
- }
20588
20585
  function illegalOpSequences(operations, errors, checkAddAdd, options) {
20589
20586
  const opHistory = new Map;
20590
20587
  for (let i = 0;i < operations.length; i++) {
@@ -20594,8 +20591,6 @@ function illegalOpSequences(operations, errors, checkAddAdd, options) {
20594
20591
  const name = getOpName(op);
20595
20592
  if (!name)
20596
20593
  continue;
20597
- if (hasAnyTokens(name))
20598
- continue;
20599
20594
  const kind = inferOperationKind({ ...op, name });
20600
20595
  const qualName = kind === "shape" ? `shape:${name}` : `thing:${name}`;
20601
20596
  const history = opHistory.get(qualName) ?? [];
@@ -20638,6 +20633,12 @@ var canonicalCollectionTypes = ["arc", "bond", "set", "list"];
20638
20633
  var collectionOps = ["add", "revise"];
20639
20634
  var COLLECTION_CREATE_REQUIRES_NAME_MESSAGE = "Collection create requires a name. Collections are ordinary named things (ADR 0004).";
20640
20635
  var COLLECTION_ABOUT_REMOVED_MESSAGE = 'about accepts a wref. Create the collection as its own named operation, then point the assertion at it. Prefer deterministic relationship names, for example: [{"operation":"add","kind":"collection","type":"arc","name":"a-to-b","members":["A","B"]},{"operation":"add","kind":"assertion","about":"Arc/a-to-b","name":"Assertion/example","data":{}}]. For CLI usage, use wh commit submit --file with the two operations.';
20636
+ function parseCollectionType(value) {
20637
+ return collectionTypes.find((candidate) => candidate === value) ?? null;
20638
+ }
20639
+ function parseCollectionOp(value) {
20640
+ return collectionOps.find((candidate) => candidate === value) ?? null;
20641
+ }
20641
20642
  function preflightOpDiagnostics(op, operationIndex) {
20642
20643
  const errors = [];
20643
20644
  errors.push(...builtinShapeGuard(op, operationIndex));
@@ -20770,7 +20771,7 @@ function validateCollectionOps(op, operationIndex) {
20770
20771
  const errors = [];
20771
20772
  if (op.kind !== "collection")
20772
20773
  return errors;
20773
- if (!collectionOps.includes(op.operation)) {
20774
+ if (parseCollectionOp(op.operation) === null) {
20774
20775
  return errors;
20775
20776
  }
20776
20777
  if (op.operation === "add" && !op.name) {
@@ -20780,7 +20781,8 @@ function validateCollectionOps(op, operationIndex) {
20780
20781
  message: COLLECTION_CREATE_REQUIRES_NAME_MESSAGE
20781
20782
  });
20782
20783
  }
20783
- if (!op.type || !collectionTypes.includes(op.type)) {
20784
+ const collectionType = parseCollectionType(op.type);
20785
+ if (collectionType === null) {
20784
20786
  errors.push({
20785
20787
  code: "VALIDATION_ERROR",
20786
20788
  operationIndex,
@@ -20804,8 +20806,8 @@ function validateCollectionOps(op, operationIndex) {
20804
20806
  }
20805
20807
  }
20806
20808
  }
20807
- if (op.type && op.members) {
20808
- const arityError = collectionArityError(op.type, op.members);
20809
+ if (collectionType !== null && op.members) {
20810
+ const arityError = collectionArityError(collectionType, op.members);
20809
20811
  if (arityError) {
20810
20812
  errors.push({
20811
20813
  code: "VALIDATION_ERROR",
@@ -20827,6 +20829,10 @@ function collectionArityError(tag, members) {
20827
20829
  case "set":
20828
20830
  case "list":
20829
20831
  return members.length < 1 ? `${tag === "set" ? "Set" : "List"} requires at least 1 member, got 0` : null;
20832
+ default: {
20833
+ const unhandled = tag;
20834
+ return unhandled;
20835
+ }
20830
20836
  }
20831
20837
  }
20832
20838
  // ../../packages/rules/src/preflight.ts
@@ -20896,7 +20902,7 @@ __export(exports_external, {
20896
20902
  pipe: () => pipe,
20897
20903
  partialRecord: () => partialRecord,
20898
20904
  parseAsync: () => parseAsync2,
20899
- parse: () => parse4,
20905
+ parse: () => parse3,
20900
20906
  overwrite: () => _overwrite,
20901
20907
  optional: () => optional,
20902
20908
  object: () => object,
@@ -21098,7 +21104,7 @@ __export(exports_core2, {
21098
21104
  process: () => process2,
21099
21105
  prettifyError: () => prettifyError,
21100
21106
  parseAsync: () => parseAsync,
21101
- parse: () => parse2,
21107
+ parse: () => parse,
21102
21108
  meta: () => meta,
21103
21109
  locales: () => exports_locales,
21104
21110
  isValidJWT: () => isValidJWT,
@@ -22282,7 +22288,7 @@ var _parse = (_Err) => (schema, value, _ctx, _params) => {
22282
22288
  }
22283
22289
  return result.value;
22284
22290
  };
22285
- var parse2 = /* @__PURE__ */ _parse($ZodRealError);
22291
+ var parse = /* @__PURE__ */ _parse($ZodRealError);
22286
22292
  var _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
22287
22293
  const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
22288
22294
  let result = schema._zod.run({ value, issues: [] }, ctx);
@@ -25069,10 +25075,10 @@ var $ZodFunction = /* @__PURE__ */ $constructor("$ZodFunction", (inst, def) => {
25069
25075
  throw new Error("implement() must be called with a function");
25070
25076
  }
25071
25077
  return function(...args) {
25072
- const parsedArgs = inst._def.input ? parse2(inst._def.input, args) : args;
25078
+ const parsedArgs = inst._def.input ? parse(inst._def.input, args) : args;
25073
25079
  const result = Reflect.apply(func, this, parsedArgs);
25074
25080
  if (inst._def.output) {
25075
- return parse2(inst._def.output, result);
25081
+ return parse(inst._def.output, result);
25076
25082
  }
25077
25083
  return result;
25078
25084
  };
@@ -33294,7 +33300,7 @@ var ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer2, {
33294
33300
  });
33295
33301
 
33296
33302
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/parse.js
33297
- var parse4 = /* @__PURE__ */ _parse(ZodRealError);
33303
+ var parse3 = /* @__PURE__ */ _parse(ZodRealError);
33298
33304
  var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
33299
33305
  var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
33300
33306
  var safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
@@ -33357,7 +33363,7 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
33357
33363
  inst.def = def;
33358
33364
  inst.type = def.type;
33359
33365
  Object.defineProperty(inst, "_def", { value: def });
33360
- inst.parse = (data, params) => parse4(inst, data, params, { callee: inst.parse });
33366
+ inst.parse = (data, params) => parse3(inst, data, params, { callee: inst.parse });
33361
33367
  inst.safeParse = (data, params) => safeParse2(inst, data, params);
33362
33368
  inst.parseAsync = async (data, params) => parseAsync2(inst, data, params, { callee: inst.parseAsync });
33363
33369
  inst.safeParseAsync = async (data, params) => safeParseAsync2(inst, data, params);
@@ -35417,16 +35423,8 @@ var BASE_PRIMITIVE_TYPES = [
35417
35423
  ];
35418
35424
  var BASE_PRIMITIVE_TYPE_SET = new Set(BASE_PRIMITIVE_TYPES);
35419
35425
  var VALID_PRIMITIVE_TYPES = new Set([
35420
- "number",
35421
- "string",
35422
- "boolean",
35423
- "wref",
35424
- "array",
35425
- "number?",
35426
- "string?",
35427
- "boolean?",
35428
- "wref?",
35429
- "array?"
35426
+ ...BASE_PRIMITIVE_TYPES,
35427
+ ...BASE_PRIMITIVE_TYPES.map((type) => `${type}?`)
35430
35428
  ]);
35431
35429
  function isPlainObject2(value) {
35432
35430
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -42601,6 +42599,54 @@ var SYSTEM_INFRA_SHAPE_NAMES = new Set(SYSTEM_COMPONENTS.filter((entry) => entry
42601
42599
  function findSystemComponent(componentId) {
42602
42600
  return SYSTEM_COMPONENTS.find((entry) => entry.componentId === componentId);
42603
42601
  }
42602
+ // ../../packages/sdk-ts/src/grant-client.ts
42603
+ function createGrantClient(getTrpc, mapError) {
42604
+ return {
42605
+ create: async (orgName, repoName, input) => {
42606
+ try {
42607
+ return await getTrpc().grant.create.mutate({
42608
+ orgName,
42609
+ repoName,
42610
+ ...input
42611
+ });
42612
+ } catch (error51) {
42613
+ throw mapError(error51);
42614
+ }
42615
+ },
42616
+ get: async (orgName, repoName, grantId) => {
42617
+ try {
42618
+ return await getTrpc().grant.get.query({ orgName, repoName, grantId });
42619
+ } catch (error51) {
42620
+ throw mapError(error51);
42621
+ }
42622
+ },
42623
+ list: async (orgName, repoName, opts) => {
42624
+ try {
42625
+ return await getTrpc().grant.list.query({
42626
+ orgName,
42627
+ repoName,
42628
+ limit: opts?.limit,
42629
+ cursor: opts?.cursor
42630
+ });
42631
+ } catch (error51) {
42632
+ throw mapError(error51);
42633
+ }
42634
+ },
42635
+ revoke: async (orgName, repoName, grantId, opts) => {
42636
+ try {
42637
+ return await getTrpc().grant.revoke.mutate({
42638
+ orgName,
42639
+ repoName,
42640
+ grantId,
42641
+ reason: opts?.reason
42642
+ });
42643
+ } catch (error51) {
42644
+ throw mapError(error51);
42645
+ }
42646
+ }
42647
+ };
42648
+ }
42649
+
42604
42650
  // ../../packages/sdk-ts/src/repository-checkpoint-client.ts
42605
42651
  function normalizeRepositoryCheckpointStatus(status) {
42606
42652
  return {
@@ -43379,7 +43425,7 @@ function completedOperationsFrom(result) {
43379
43425
  // ../../packages/sdk-ts/package.json
43380
43426
  var package_default = {
43381
43427
  name: "@warmhub/sdk-ts",
43382
- version: "0.86.0",
43428
+ version: "0.87.0",
43383
43429
  private: false,
43384
43430
  type: "module",
43385
43431
  description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -43514,21 +43560,23 @@ function clientCompatibilityFailure(capabilities, identity2) {
43514
43560
  hint: "Upgrade the WarmHub backend before retrying this write."
43515
43561
  };
43516
43562
  }
43517
- const minimum = capabilities.minSupportedClients[identity2.name];
43518
- if (typeof minimum !== "string" || !isValidSemver(minimum)) {
43563
+ const advertised = capabilities.minSupportedClients[identity2.name];
43564
+ const minimum = typeof advertised === "string" ? parseSemver(advertised) : null;
43565
+ if (!minimum) {
43519
43566
  return {
43520
43567
  message: `The backend does not advertise a valid compatibility floor for ${identity2.name}.`,
43521
43568
  hint: "Upgrade the WarmHub backend or register this first-party client family before writing."
43522
43569
  };
43523
43570
  }
43524
43571
  if (!sdkVersionIsDevelopment(identity2.version)) {
43525
- if (!isValidSemver(identity2.version)) {
43572
+ const version2 = parseSemver(identity2.version);
43573
+ if (!version2) {
43526
43574
  return {
43527
43575
  message: `${identity2.name} reported malformed version "${identity2.version}".`,
43528
43576
  hint: "Use a released WarmHub client with a SemVer package version."
43529
43577
  };
43530
43578
  }
43531
- if (compareSemver(identity2.version, minimum) < 0) {
43579
+ if (compareSemver(version2, minimum) < 0) {
43532
43580
  return {
43533
43581
  message: `${identity2.name} ${identity2.version} is older than the backend's minimum supported version ${minimum}.`,
43534
43582
  hint: clientUpgradeHint(identity2.name)
@@ -43556,7 +43604,8 @@ var WARMHUB_CLIENT_OPTION_NAMES = [
43556
43604
  "accessToken",
43557
43605
  "auth",
43558
43606
  "functionLogs",
43559
- "client"
43607
+ "client",
43608
+ "clientFlags"
43560
43609
  ];
43561
43610
  var WARMHUB_CLIENT_OPTION_NAME_SET = new Set(WARMHUB_CLIENT_OPTION_NAMES);
43562
43611
  var ACCESS_TOKEN_OPTION_ALIASES = new Set(["token", "apiKey", "bearer"]);
@@ -43572,6 +43621,17 @@ function validateWarmHubClientOptions(options) {
43572
43621
  throw new TypeError(`Unknown WarmHubClient option "${key}"${hint}`);
43573
43622
  }
43574
43623
  }
43624
+ function normalizeClientFlags(flags) {
43625
+ if (!flags || flags.length === 0) {
43626
+ return [];
43627
+ }
43628
+ for (const token of flags) {
43629
+ if (!isValidClientFlagToken(token)) {
43630
+ throw new TypeError(`Invalid client flag "${token}": expected lowercase tokens matching [a-z0-9-]+.`);
43631
+ }
43632
+ }
43633
+ return [...new Set(flags)].sort();
43634
+ }
43575
43635
  var DEFAULT_API_URL = "https://api.warmhub.ai";
43576
43636
  var UNBATCHED_TRPC_PATHS = new Set([
43577
43637
  "repo.shapeInstanceCounts",
@@ -43891,9 +43951,11 @@ function connectionErrorMessage(url2) {
43891
43951
  function sdkVersionIsBelowMinimum(version2, minimum) {
43892
43952
  if (sdkVersionIsDevelopment(version2))
43893
43953
  return false;
43894
- if (!isValidSemver(version2) || !isValidSemver(minimum))
43954
+ const parsed = parseSemver(version2);
43955
+ const floor = parseSemver(minimum);
43956
+ if (!parsed || !floor)
43895
43957
  return false;
43896
- return compareSemver(version2, minimum) < 0;
43958
+ return compareSemver(parsed, floor) < 0;
43897
43959
  }
43898
43960
  function clientIncompatible(message, hint) {
43899
43961
  return new WarmHubError("CLIENT_INCOMPATIBLE", message, 412, hint);
@@ -43910,10 +43972,22 @@ class WarmHubClient {
43910
43972
  fetchImpl;
43911
43973
  accessToken;
43912
43974
  clientIdentity;
43975
+ clientFlags;
43913
43976
  functionLogMode;
43914
43977
  getToken;
43915
43978
  compatibilityCheck;
43979
+ overrideNoticePrinted = false;
43980
+ noteCompatibilityOverride() {
43981
+ if (this.overrideNoticePrinted)
43982
+ return;
43983
+ this.overrideNoticePrinted = true;
43984
+ console.error(`warmhub: compatibility checks overridden by client flag ${CLIENT_FLAG_COMPATIBILITY_OVERRIDE}; the server remains authoritative.`);
43985
+ }
43916
43986
  assertWriteCompatible() {
43987
+ if (this.clientFlags.includes(CLIENT_FLAG_COMPATIBILITY_OVERRIDE)) {
43988
+ this.noteCompatibilityOverride();
43989
+ return Promise.resolve();
43990
+ }
43917
43991
  if (sdkVersionIsDevelopment(this.clientIdentity.version) && isProductionApiUrl(this.apiUrl, DEFAULT_API_URL)) {
43918
43992
  return Promise.reject(clientIncompatible(`Development client ${this.clientIdentity.name}/${this.clientIdentity.version} cannot write to production.`, "Install a released WarmHub client artifact before writing to api.warmhub.ai."));
43919
43993
  }
@@ -45224,6 +45298,32 @@ class WarmHubClient {
45224
45298
  }
45225
45299
  }
45226
45300
  };
45301
+ view = {
45302
+ evaluate: async (orgName, repoName, wref, opts) => {
45303
+ try {
45304
+ return await this.trpc.view.evaluate.query({
45305
+ orgName,
45306
+ repoName,
45307
+ wref,
45308
+ limit: opts?.limit,
45309
+ cursor: opts?.cursor
45310
+ });
45311
+ } catch (error51) {
45312
+ throw toWarmHubError(error51);
45313
+ }
45314
+ },
45315
+ evaluateIter: (orgName, repoName, wref, opts) => {
45316
+ return paginate((cursor) => this.view.evaluate(orgName, repoName, wref, { ...opts, cursor }), (page) => page.items, opts?.cursor);
45317
+ },
45318
+ evaluateAll: async (orgName, repoName, wref, opts) => {
45319
+ const { max, ...pageOpts } = opts ?? {};
45320
+ return await collectPaginatedPages((cursor) => this.view.evaluate(orgName, repoName, wref, {
45321
+ ...pageOpts,
45322
+ cursor
45323
+ }), (page) => page.items, max, pageOpts.cursor);
45324
+ }
45325
+ };
45326
+ grant = createGrantClient(() => this.trpc, toWarmHubError);
45227
45327
  thing = {
45228
45328
  head: async (orgName, repoName, opts) => {
45229
45329
  try {
@@ -45803,6 +45903,7 @@ class WarmHubClient {
45803
45903
  name: options?.client?.name ?? WARMHUB_SDK_CLIENT_NAME,
45804
45904
  version: options?.client?.version ?? SDK_VERSION
45805
45905
  };
45906
+ this.clientFlags = normalizeClientFlags(options?.clientFlags);
45806
45907
  if (typeof this.accessToken === "function") {
45807
45908
  const provider = this.accessToken;
45808
45909
  this.getToken = async () => await provider();
@@ -45833,7 +45934,8 @@ class WarmHubClient {
45833
45934
  apiUrl: this.apiUrl,
45834
45935
  fetch: this.fetchImpl,
45835
45936
  accessToken,
45836
- client: this.clientIdentity
45937
+ client: this.clientIdentity,
45938
+ clientFlags: this.clientFlags
45837
45939
  });
45838
45940
  }
45839
45941
  actions = this.action;
@@ -45906,6 +46008,9 @@ class WarmHubClient {
45906
46008
  if (!headers.has(CLIENT_HEADER)) {
45907
46009
  headers.set(CLIENT_HEADER, formatClientHeader(this.clientIdentity.name, this.clientIdentity.version));
45908
46010
  }
46011
+ if (this.clientFlags.length > 0 && !headers.has(CLIENT_FLAGS_HEADER)) {
46012
+ headers.set(CLIENT_FLAGS_HEADER, serializeClientFlags(this.clientFlags));
46013
+ }
45909
46014
  }
45910
46015
  async fetchWithAuth(input, init) {
45911
46016
  const fetchImpl = this.fetchImpl ?? globalThis.fetch;
@@ -46173,7 +46278,9 @@ var CONFLICT_SHAPED_CODES = new Set([
46173
46278
  "REPO_PENDING_DELETE",
46174
46279
  "ALREADY_RETRACTED",
46175
46280
  "LEASE_UNAVAILABLE",
46176
- "INCREMENTAL_READ_UNAVAILABLE"
46281
+ "INCREMENTAL_READ_UNAVAILABLE",
46282
+ "VIEW_EVALUATION_UNAVAILABLE",
46283
+ "IDEMPOTENCY_CONFLICT"
46177
46284
  ]);
46178
46285
 
46179
46286
  // ../../packages/warmhub-cli/src/errors-types.ts
@@ -46652,11 +46759,13 @@ function cliErrorFromAllFailed(failures) {
46652
46759
  return bestErr;
46653
46760
  return new CliError(4 /* Backend */, "BACKEND", `All ${failures.length} operations failed`);
46654
46761
  }
46655
- function assertSingleOpSuccess(result) {
46762
+ function requireSingleOpSuccess(result) {
46656
46763
  const op = result.operations[0];
46657
- if (!op || !isFailedOpStatus(op.status))
46658
- return;
46659
- throw cliErrorFromOpFailure(op);
46764
+ if (!op)
46765
+ throw new Error("Commit returned no operation result");
46766
+ if (isFailedOpStatus(op.status))
46767
+ throw cliErrorFromOpFailure(op);
46768
+ return op;
46660
46769
  }
46661
46770
 
46662
46771
  // ../../packages/warmhub-cli/src/args.ts
@@ -48010,9 +48119,11 @@ async function modifyStore(mutator, path) {
48010
48119
  return result;
48011
48120
  });
48012
48121
  }
48013
- async function saveProfileLocked(name, profile, path) {
48122
+ async function saveProfileWithFlagsLocked(name, profile, flags, path) {
48014
48123
  await modifyStore((store) => {
48015
- setProfile(store, name, profile);
48124
+ const stored = hasProfile(store, name) ? store.profiles[name]?.flags : undefined;
48125
+ const resolved = flags ?? (Array.isArray(stored) ? stored : undefined);
48126
+ setProfile(store, name, resolved?.length ? { ...profile, flags: [...resolved] } : profile);
48016
48127
  }, path);
48017
48128
  }
48018
48129
  async function deleteProfileLocked(name, path) {
@@ -48392,7 +48503,8 @@ function createClient(config2, opts = {}) {
48392
48503
  },
48393
48504
  fetch: createBenchmarkAwareFetch(benchmarkId, opts.signal),
48394
48505
  functionLogs: opts.functionLogs,
48395
- client: cliClientIdentity()
48506
+ client: cliClientIdentity(),
48507
+ clientFlags: opts.clientFlags
48396
48508
  });
48397
48509
  }
48398
48510
  function createUnauthenticatedClient(config2, opts = {}) {
@@ -48401,7 +48513,8 @@ function createUnauthenticatedClient(config2, opts = {}) {
48401
48513
  apiUrl: config2.apiUrl,
48402
48514
  fetch: createBenchmarkAwareFetch(benchmarkId, opts.signal),
48403
48515
  functionLogs: opts.functionLogs,
48404
- client: cliClientIdentity()
48516
+ client: cliClientIdentity(),
48517
+ clientFlags: opts.clientFlags
48405
48518
  });
48406
48519
  }
48407
48520
  function wantsStructuredLiveOutput(format) {
@@ -48434,7 +48547,8 @@ async function runLive(opts) {
48434
48547
  auth,
48435
48548
  fetch: createBenchmarkAwareFetch(benchmarkId, controller.signal),
48436
48549
  functionLogs: opts.functionLogs,
48437
- client: cliClientIdentity()
48550
+ client: cliClientIdentity(),
48551
+ clientFlags: opts.clientFlags
48438
48552
  });
48439
48553
  if (opts.signal) {
48440
48554
  if (opts.signal.aborted)
@@ -48516,15 +48630,29 @@ function shouldGuardDomain(domainPath, canonicalVerb, args) {
48516
48630
  }
48517
48631
  return true;
48518
48632
  }
48633
+ async function probeCapabilities(ctx) {
48634
+ try {
48635
+ return await ctx.client.diagnostics.capabilities();
48636
+ } catch {
48637
+ return;
48638
+ }
48639
+ }
48519
48640
  async function checkCompatibility(ctx, domainPath, canonicalVerb, args) {
48520
48641
  if (!shouldGuardDomain(domainPath, canonicalVerb, args))
48521
48642
  return;
48643
+ const clientFlags = ctx.clientFlags ?? [];
48644
+ if (clientFlags.includes(CLIENT_FLAG_COMPATIBILITY_OVERRIDE)) {
48645
+ ctx.err(`compatibility checks overridden by client flag ${CLIENT_FLAG_COMPATIBILITY_OVERRIDE}`);
48646
+ }
48647
+ let capabilities;
48522
48648
  try {
48523
48649
  const diagnostics = ctx.client.diagnostics;
48524
48650
  if (typeof diagnostics.assertCompatible === "function") {
48525
48651
  await diagnostics.assertCompatible();
48652
+ if (clientFlags.length > 0)
48653
+ capabilities = await probeCapabilities(ctx);
48526
48654
  } else {
48527
- await diagnostics.capabilities();
48655
+ capabilities = await diagnostics.capabilities();
48528
48656
  }
48529
48657
  } catch (err) {
48530
48658
  const message = err instanceof Error ? err.message : String(err);
@@ -48533,6 +48661,17 @@ async function checkCompatibility(ctx, domainPath, canonicalVerb, args) {
48533
48661
  } else {
48534
48662
  ctx.err(`Could not verify compatibility: ${message}`);
48535
48663
  }
48664
+ if (clientFlags.length > 0)
48665
+ capabilities = await probeCapabilities(ctx);
48666
+ }
48667
+ if (clientFlags.length === 0 || !capabilities)
48668
+ return;
48669
+ const echoed = capabilities.honoredClientFlags;
48670
+ const honored = new Set(Array.isArray(echoed) ? echoed : []);
48671
+ for (const flagName of clientFlags) {
48672
+ if (honored.has(flagName))
48673
+ continue;
48674
+ ctx.err(`client flag "${flagName}" is not honored by this backend`);
48536
48675
  }
48537
48676
  }
48538
48677
 
@@ -48603,15 +48742,9 @@ function getRepoRef(ctx) {
48603
48742
  return r[r.length - 1];
48604
48743
  return;
48605
48744
  }
48606
- function splitRepoSlug(ref) {
48607
- const parts = ref.split("/");
48608
- if (parts.length !== 2 || !parts[0] || !parts[1])
48609
- return null;
48610
- return { org: parts[0], repo: parts[1] };
48611
- }
48612
48745
  function parseOrgRepo(ref, config2) {
48613
48746
  if (ref?.includes("/")) {
48614
- const parsed = splitRepoSlug(ref);
48747
+ const parsed = parseRepoSlug(ref);
48615
48748
  if (!parsed) {
48616
48749
  throw new CliError(3 /* Config */, "CONFIG", `Invalid repo format "${ref}". Expected "org/repo".`);
48617
48750
  }
@@ -48621,7 +48754,7 @@ function parseOrgRepo(ref, config2) {
48621
48754
  return { org: config2.defaultOrg, repo: ref };
48622
48755
  }
48623
48756
  if (config2.defaultRepo) {
48624
- const parsed = splitRepoSlug(config2.defaultRepo);
48757
+ const parsed = parseRepoSlug(config2.defaultRepo);
48625
48758
  if (!parsed) {
48626
48759
  throw new CliError(3 /* Config */, "CONFIG", `Invalid repo format "${config2.defaultRepo}". Expected "org/repo".`);
48627
48760
  }
@@ -49188,20 +49321,20 @@ function getCacheBaseDir() {
49188
49321
  return override;
49189
49322
  return join7(homedir3(), ".warmhub", "cache", "install-snapshots");
49190
49323
  }
49191
- function isValidSegment(segment) {
49192
- return segment.length > 0 && segment !== "." && segment !== ".." && /^[a-zA-Z0-9._-]+$/.test(segment);
49324
+ function isPathSafeSegment(segment) {
49325
+ return segment !== "." && segment !== ".." && /^[a-zA-Z0-9._-]+$/.test(segment);
49193
49326
  }
49194
- function parseRepoSlug(repoSlug) {
49195
- const segments = repoSlug.split("/");
49196
- if (segments.length !== 2)
49327
+ function parseSnapshotCacheSlug(repoSlug) {
49328
+ const parsed = parseRepoSlug(repoSlug);
49329
+ if (!parsed)
49197
49330
  return null;
49198
- const [org, repo] = segments;
49199
- if (!isValidSegment(org) || !isValidSegment(repo))
49331
+ const { org, repo } = parsed;
49332
+ if (!isPathSafeSegment(org) || !isPathSafeSegment(repo))
49200
49333
  return null;
49201
49334
  return { org, repo, fileName: `${org}--${repo}.json` };
49202
49335
  }
49203
49336
  function getInstallSnapshotCachePath(repoSlug) {
49204
- const parsed = parseRepoSlug(repoSlug);
49337
+ const parsed = parseSnapshotCacheSlug(repoSlug);
49205
49338
  if (!parsed)
49206
49339
  return null;
49207
49340
  return join7(getCacheBaseDir(), parsed.fileName);
@@ -49328,7 +49461,7 @@ async function loadOrPopulateInstallSnapshotCacheForComponent(repoSlug, client,
49328
49461
  if (cached2 && isCacheFresh(cached2, opts))
49329
49462
  return cached2;
49330
49463
  try {
49331
- const parsed = parseRepoSlug(repoSlug);
49464
+ const parsed = parseSnapshotCacheSlug(repoSlug);
49332
49465
  if (!parsed)
49333
49466
  return null;
49334
49467
  const activeItems = filterActiveItems(await fetchAllSummaries(client, parsed.org, parsed.repo));
@@ -49358,7 +49491,7 @@ async function ensureFreshInstallSnapshotCache(repoSlug, client, opts) {
49358
49491
  }
49359
49492
  }
49360
49493
  async function refreshInstallSnapshotCache(repoSlug, client, opts) {
49361
- const parsed = parseRepoSlug(repoSlug);
49494
+ const parsed = parseSnapshotCacheSlug(repoSlug);
49362
49495
  if (!parsed) {
49363
49496
  throw new Error(`Invalid repo slug for install snapshot cache: '${repoSlug}'`);
49364
49497
  }
@@ -49446,15 +49579,15 @@ function filterActiveItems(items) {
49446
49579
  return items.filter((i) => i.active && i.state !== "uninstalled" && i.state !== "paused" && i.state !== "error");
49447
49580
  }
49448
49581
  function extractRegisteredRef(ref) {
49449
- if (typeof ref !== "string" || ref.length === 0)
49582
+ if (typeof ref !== "string")
49450
49583
  return null;
49451
- const segments = ref.split("/");
49452
- if (segments.length !== 2)
49453
- return null;
49454
- const [org, name] = segments;
49455
- if (!org || !name)
49584
+ const parsed = parseComponentRef(ref);
49585
+ if (!parsed)
49456
49586
  return null;
49457
- return { ownerOrgName: org, registeredComponentName: name };
49587
+ return {
49588
+ ownerOrgName: parsed.org,
49589
+ registeredComponentName: parsed.name
49590
+ };
49458
49591
  }
49459
49592
 
49460
49593
  // ../../packages/warmhub-cli/src/domain-help.ts
@@ -50047,7 +50180,7 @@ function parseAbout(raw) {
50047
50180
  return raw;
50048
50181
  }
50049
50182
  const tag = raw.slice(0, colonIdx).toLowerCase();
50050
- if (!COLLECTION_TAGS.includes(tag)) {
50183
+ if (!COLLECTION_TAGS.some((candidate) => candidate === tag)) {
50051
50184
  return raw;
50052
50185
  }
50053
50186
  throw new CliError(2 /* UserInput */, "USER_INPUT", COLLECTION_ABOUT_REMOVED_MESSAGE, undefined, "Use wh commit submit --file with a named collection add followed by an assertion add.");
@@ -50192,10 +50325,7 @@ var handleRevise = async (ctx, { flags, args }) => {
50192
50325
  data
50193
50326
  }
50194
50327
  ], { committer: flags.committer });
50195
- const result = commitResult.operations[0];
50196
- if (!result)
50197
- throw new Error("Commit returned no operation result");
50198
- assertSingleOpSuccess(commitResult);
50328
+ const result = requireSingleOpSuccess(commitResult);
50199
50329
  writeOutput(ctx, commitResult, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result, {
50200
50330
  marker: "~",
50201
50331
  color: c.yellow,
@@ -50220,14 +50350,10 @@ var handleRetract = async (ctx, { flags, args }) => {
50220
50350
  ], {
50221
50351
  committer: flags.committer
50222
50352
  });
50223
- const result = commitResult.operations[0];
50224
- if (!result)
50225
- throw new Error("Commit returned no operation result");
50226
- assertSingleOpSuccess(commitResult);
50353
+ const result = requireSingleOpSuccess(commitResult);
50227
50354
  writeOutput(ctx, commitResult, () => {
50228
- const op = result;
50229
50355
  renderCommitterEcho(ctx.out, ctx.colors, flags.committer);
50230
- ctx.out(`${ctx.colors.red}-${ctx.colors.reset} ${displayName(ctx.colors, op?.name ?? name)}`);
50356
+ ctx.out(`${ctx.colors.red}-${ctx.colors.reset} ${displayName(ctx.colors, result.name)}`);
50231
50357
  });
50232
50358
  };
50233
50359
  var handleCreate = async (ctx, { flags, args }) => {
@@ -50254,10 +50380,7 @@ var handleCreate = async (ctx, { flags, args }) => {
50254
50380
  }
50255
50381
  ];
50256
50382
  const commitResult = await ctx.client.commit.apply(org, repo, message ?? `assert ${shape}`, operations, { committer });
50257
- const result = commitResult.operations[0];
50258
- if (!result)
50259
- throw new Error("Commit returned no operation result");
50260
- assertSingleOpSuccess(commitResult);
50383
+ const result = requireSingleOpSuccess(commitResult);
50261
50384
  writeOutput(ctx, commitResult, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result, {
50262
50385
  marker: "+",
50263
50386
  color: c.green,
@@ -50420,6 +50543,7 @@ var handleAbout = async (ctx, { flags, args }) => {
50420
50543
  inactivityTimeoutMs: ctx.inactivityTimeoutMs,
50421
50544
  functionLogs: ctx.functionLogMode,
50422
50545
  profile: ctx.profile,
50546
+ clientFlags: ctx.clientFlags,
50423
50547
  signal: ctx.signal
50424
50548
  });
50425
50549
  return;
@@ -50566,10 +50690,7 @@ var handleCreate2 = async (ctx, { flags, args }) => {
50566
50690
  data
50567
50691
  }
50568
50692
  ], { committer });
50569
- const result = commitResult.operations[0];
50570
- if (!result)
50571
- throw new Error("Commit returned no operation result");
50572
- assertSingleOpSuccess(commitResult);
50693
+ const result = requireSingleOpSuccess(commitResult);
50573
50694
  writeOutput(ctx, commitResult, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result, {
50574
50695
  marker: "+",
50575
50696
  color: c.green,
@@ -51090,6 +51211,7 @@ var handleHistory = async (ctx, { flags, args }) => {
51090
51211
  inactivityTimeoutMs: ctx.inactivityTimeoutMs,
51091
51212
  functionLogs: ctx.functionLogMode,
51092
51213
  profile: ctx.profile,
51214
+ clientFlags: ctx.clientFlags,
51093
51215
  signal: ctx.signal
51094
51216
  });
51095
51217
  return;
@@ -51192,8 +51314,9 @@ var VALID_KINDS = [
51192
51314
  function validateKind(value, flagName = "--kind") {
51193
51315
  if (value === undefined)
51194
51316
  return;
51195
- if (VALID_KINDS.includes(value))
51196
- return value;
51317
+ const parsed = VALID_KINDS.find((candidate) => candidate === value);
51318
+ if (parsed)
51319
+ return parsed;
51197
51320
  const message = `Invalid ${flagName} "${value}". Supported kinds: ${VALID_KINDS.join(", ")}.`;
51198
51321
  const hint = /^[A-Z]/.test(value) ? `Did you mean --shape ${value} --kind assertion?` : `Example: ${flagName} assertion`;
51199
51322
  throw new CliError(2 /* UserInput */, "USER_INPUT", message, undefined, hint);
@@ -51396,6 +51519,7 @@ var handleHead = async (ctx, { flags, args }) => {
51396
51519
  inactivityTimeoutMs: ctx.inactivityTimeoutMs,
51397
51520
  functionLogs: ctx.functionLogMode,
51398
51521
  profile: ctx.profile,
51522
+ clientFlags: ctx.clientFlags,
51399
51523
  signal: ctx.signal
51400
51524
  });
51401
51525
  return;
@@ -51585,6 +51709,7 @@ var handleQuery = async (ctx, { flags }) => {
51585
51709
  inactivityTimeoutMs: ctx.inactivityTimeoutMs,
51586
51710
  functionLogs: ctx.functionLogMode,
51587
51711
  profile: ctx.profile,
51712
+ clientFlags: ctx.clientFlags,
51588
51713
  signal: ctx.signal
51589
51714
  });
51590
51715
  return;
@@ -51868,14 +51993,10 @@ var handleThingRetract = async (ctx, { flags, args }) => {
51868
51993
  ...leaseId ? { leaseId } : {}
51869
51994
  }
51870
51995
  ], { committer });
51871
- const result = commitResult.operations[0];
51872
- if (!result)
51873
- throw new Error("Commit returned no operation result");
51874
- assertSingleOpSuccess(commitResult);
51996
+ const result = requireSingleOpSuccess(commitResult);
51875
51997
  writeOutput(ctx, commitResult, () => {
51876
- const op = result;
51877
51998
  renderCommitterEcho(ctx.out, c, committer);
51878
- ctx.out(`${c.red}-${c.reset} ${displayName(c, op?.name ?? name)}`);
51999
+ ctx.out(`${c.red}-${c.reset} ${displayName(c, result.name)}`);
51879
52000
  });
51880
52001
  };
51881
52002
 
@@ -51918,10 +52039,7 @@ var handleRevise2 = async (ctx, { flags, args }) => {
51918
52039
  ...leaseId ? { leaseId } : {}
51919
52040
  }
51920
52041
  ], { committer });
51921
- const result = commitResult.operations[0];
51922
- if (!result)
51923
- throw new Error("Commit returned no operation result");
51924
- assertSingleOpSuccess(commitResult);
52042
+ const result = requireSingleOpSuccess(commitResult);
51925
52043
  writeOutput(ctx, commitResult, () => renderSingleOpSuccess(ctx.out, c, ctx.chars, result, {
51926
52044
  marker: "~",
51927
52045
  color: c.yellow,
@@ -52292,6 +52410,7 @@ async function runSingleView(ctx, wref, flags) {
52292
52410
  inactivityTimeoutMs: ctx.inactivityTimeoutMs,
52293
52411
  functionLogs: ctx.functionLogMode,
52294
52412
  profile: ctx.profile,
52413
+ clientFlags: ctx.clientFlags,
52295
52414
  signal: ctx.signal
52296
52415
  });
52297
52416
  return;
@@ -52362,7 +52481,7 @@ var handleView = async (ctx, { flags, args, terminator }) => {
52362
52481
  }
52363
52482
  if (isBatch)
52364
52483
  return runBatchView(ctx, wrefs, flags);
52365
- const singleWref = wrefs[0];
52484
+ const [singleWref] = wrefs;
52366
52485
  return runSingleView(ctx, singleWref, flags);
52367
52486
  };
52368
52487
 
@@ -52576,6 +52695,7 @@ var handleView2 = async (ctx, { flags, args }) => {
52576
52695
  inactivityTimeoutMs: ctx.inactivityTimeoutMs,
52577
52696
  functionLogs: ctx.functionLogMode,
52578
52697
  profile: ctx.profile,
52698
+ clientFlags: ctx.clientFlags,
52579
52699
  signal: ctx.signal
52580
52700
  });
52581
52701
  return;
@@ -52632,6 +52752,7 @@ var handleHistory2 = async (ctx, { flags, args }) => {
52632
52752
  inactivityTimeoutMs: ctx.inactivityTimeoutMs,
52633
52753
  functionLogs: ctx.functionLogMode,
52634
52754
  profile: ctx.profile,
52755
+ clientFlags: ctx.clientFlags,
52635
52756
  signal: ctx.signal
52636
52757
  });
52637
52758
  return;
@@ -52756,6 +52877,7 @@ var handleList = async (ctx, { flags, args }) => {
52756
52877
  inactivityTimeoutMs: ctx.inactivityTimeoutMs,
52757
52878
  functionLogs: ctx.functionLogMode,
52758
52879
  profile: ctx.profile,
52880
+ clientFlags: ctx.clientFlags,
52759
52881
  signal: ctx.signal
52760
52882
  });
52761
52883
  return;
@@ -52799,6 +52921,7 @@ var handleList = async (ctx, { flags, args }) => {
52799
52921
  inactivityTimeoutMs: ctx.inactivityTimeoutMs,
52800
52922
  functionLogs: ctx.functionLogMode,
52801
52923
  profile: ctx.profile,
52924
+ clientFlags: ctx.clientFlags,
52802
52925
  signal: ctx.signal
52803
52926
  });
52804
52927
  return;
@@ -52903,8 +53026,99 @@ var ASSERTION_DOMAIN = defineDomain({
52903
53026
  }
52904
53027
  });
52905
53028
 
53029
+ // ../../packages/warmhub-cli/src/cli-context.ts
53030
+ function resolveClientFlags(profileFlags, env = process.env) {
53031
+ const candidates = [
53032
+ ...Array.isArray(profileFlags) ? profileFlags : [],
53033
+ ...(env.WH_CLIENT_FLAGS ?? "").split(",")
53034
+ ];
53035
+ const flags = new Set;
53036
+ const dropped = [];
53037
+ for (const raw of candidates) {
53038
+ const token = typeof raw === "string" ? raw.trim() : "";
53039
+ if (!token)
53040
+ continue;
53041
+ if (isValidClientFlagToken(token))
53042
+ flags.add(token);
53043
+ else
53044
+ dropped.push(token);
53045
+ }
53046
+ return { flags: [...flags].sort(), dropped };
53047
+ }
53048
+ function resolveCliContext(args) {
53049
+ const { invocation, format } = args;
53050
+ const config2 = args.config ?? loadConfig();
53051
+ const apiUrlFlag = invocation.flags["api-url"];
53052
+ const explicitApiUrl = typeof apiUrlFlag === "string" ? apiUrlFlag : undefined;
53053
+ const profileFlag = invocation.flags.profile;
53054
+ const apiUrl = explicitApiUrl ?? process.env.WARMHUB_API_URL ?? config2.apiUrl;
53055
+ config2.apiUrl = apiUrl;
53056
+ const explicitProfile = (typeof profileFlag === "string" ? profileFlag : undefined) ?? config2.profile;
53057
+ const effectiveProfile = explicitProfile ?? "default";
53058
+ const overridesBypassProfile = !explicitProfile && !!process.env.WH_TOKEN && (!!process.env.WARMHUB_API_URL || !!explicitApiUrl);
53059
+ let profileData = null;
53060
+ if (!overridesBypassProfile) {
53061
+ try {
53062
+ profileData = getProfile(effectiveProfile);
53063
+ } catch (err) {
53064
+ if (explicitProfile)
53065
+ throw err;
53066
+ const reason = err instanceof Error ? err.message : String(err);
53067
+ if (format === "json" || format === "jsonl") {
53068
+ process.stderr.write(`${JSON.stringify({
53069
+ level: "warning",
53070
+ kind: "auth-file-unreadable",
53071
+ message: `could not read auth.json: ${reason}`
53072
+ })}
53073
+ `);
53074
+ } else {
53075
+ process.stderr.write(`warning: could not read auth.json (${reason})
53076
+ `);
53077
+ }
53078
+ }
53079
+ }
53080
+ if (profileData) {
53081
+ if (profileData.apiUrl && !explicitApiUrl) {
53082
+ config2.apiUrl = profileData.apiUrl;
53083
+ }
53084
+ } else if (explicitProfile) {
53085
+ const isAuthLogin = invocation.kind === "static" && invocation.commandPath[0] === "auth" && invocation.commandPath[1] === "login";
53086
+ if (!isAuthLogin) {
53087
+ const available = listProfiles();
53088
+ const availableHint = available.length > 0 ? `Available profiles: ${available.join(", ")}.` : "No profiles found.";
53089
+ throw new CliError(5 /* Auth */, "AUTH", `Auth profile "${explicitProfile}" does not exist.`, undefined, `${availableHint}
53090
+ Run \`wh auth login --profile ${explicitProfile}\` to create it.`);
53091
+ }
53092
+ }
53093
+ const { flags: clientFlags, dropped: droppedFlags } = resolveClientFlags(profileData?.flags);
53094
+ for (const token of droppedFlags) {
53095
+ process.stderr.write(`warning: ignoring malformed client flag "${token}"
53096
+ `);
53097
+ }
53098
+ const client = args.client ?? createClient(config2, {
53099
+ functionLogs: args.functionLogs,
53100
+ profile: effectiveProfile,
53101
+ signal: args.signal,
53102
+ clientFlags
53103
+ });
53104
+ return { config: config2, profile: effectiveProfile, client, clientFlags };
53105
+ }
53106
+
52906
53107
  // ../../packages/warmhub-cli/src/domains/auth-shared.ts
52907
- async function loginWithToken(ctx, profile) {
53108
+ function clientForStoredFlags(ctx, profile) {
53109
+ const { flags } = resolveClientFlags(getProfile(profile)?.flags);
53110
+ const active = ctx.clientFlags ?? [];
53111
+ if (flags.length === active.length && flags.every((token, i) => token === active[i])) {
53112
+ return ctx.client;
53113
+ }
53114
+ return createClient(ctx.config, {
53115
+ functionLogs: ctx.functionLogMode,
53116
+ profile,
53117
+ signal: ctx.signal,
53118
+ clientFlags: flags
53119
+ });
53120
+ }
53121
+ async function loginWithToken(ctx, profile, explicitFlags) {
52908
53122
  const c = ctx.colors;
52909
53123
  if (process.stdin.isTTY) {
52910
53124
  throw new CliError(2 /* UserInput */, "USER_INPUT", "No token provided on stdin.", undefined, 'Pipe a JWT token via stdin: echo "$TOKEN" | wh auth login --with-token');
@@ -52932,7 +53146,7 @@ async function loginWithToken(ctx, profile) {
52932
53146
  if (Date.now() >= new Date(expiresAt).getTime() - EXPIRY_BUFFER_MS) {
52933
53147
  throw new CliError(5 /* Auth */, "AUTH", `Token is already expired (at ${new Date(expiresAt).toLocaleString()}).`, undefined, "Provide a valid, non-expired JWT.");
52934
53148
  }
52935
- await saveProfileLocked(profile, {
53149
+ await saveProfileWithFlagsLocked(profile, {
52936
53150
  tokens: {
52937
53151
  accessToken: jwt2,
52938
53152
  refreshToken: "",
@@ -52941,9 +53155,9 @@ async function loginWithToken(ctx, profile) {
52941
53155
  source: "token"
52942
53156
  },
52943
53157
  apiUrl: ctx.config.apiUrl
52944
- });
53158
+ }, explicitFlags);
52945
53159
  try {
52946
- await ctx.client.auth.sync();
53160
+ await clientForStoredFlags(ctx, profile).auth.sync();
52947
53161
  } catch (err) {
52948
53162
  ctx.err(`${c.yellow}Warning: could not sync user record: ${err instanceof Error ? err.message : String(err)}${c.reset}`);
52949
53163
  }
@@ -53030,7 +53244,7 @@ async function pollForDeviceToken(params) {
53030
53244
  poll().catch(reject);
53031
53245
  });
53032
53246
  }
53033
- function renderTokenInfo(ctx, info, profileName, apiUrl, identityWref) {
53247
+ function renderTokenInfo(ctx, info, profileName, apiUrl, identityWref, flags) {
53034
53248
  const c = ctx.colors;
53035
53249
  const prefix = profileName ? `${c.bold}${profileName}${c.reset}: ` : "";
53036
53250
  const sourceLabel = {
@@ -53065,6 +53279,9 @@ function renderTokenInfo(ctx, info, profileName, apiUrl, identityWref) {
53065
53279
  ctx.status(` ${c.dim}Identity:${c.reset} ${identityWref}`);
53066
53280
  }
53067
53281
  }
53282
+ if (flags?.length) {
53283
+ ctx.status(` ${c.dim}Client flags:${c.reset} ${flags.join(", ")}`);
53284
+ }
53068
53285
  }
53069
53286
  async function fetchIdentityWref(ctx) {
53070
53287
  if (process.env.WH_TOKEN)
@@ -53088,6 +53305,10 @@ function openBrowser(url2) {
53088
53305
  var loginFlags = {
53089
53306
  "with-token": flag.boolean({
53090
53307
  description: "Read a JWT token from stdin instead of using the browser flow"
53308
+ }),
53309
+ flag: flag.string({
53310
+ multiple: true,
53311
+ description: "Client flag to store on this profile. Repeatable. Validated " + "server-side; the backend honors only configured flags."
53091
53312
  })
53092
53313
  };
53093
53314
  function authStatusEntry(info, options) {
@@ -53098,6 +53319,7 @@ function authStatusEntry(info, options) {
53098
53319
  canRefresh: info.canRefresh,
53099
53320
  email: info.email ?? null,
53100
53321
  expiresAt: info.expiresAt ?? null,
53322
+ flags: options.flags ?? [],
53101
53323
  identityWref: options.identityWref ?? null,
53102
53324
  profile: options.profile ?? null,
53103
53325
  source: info.source
@@ -53110,10 +53332,23 @@ function authStatusOutput(activeProfile, entries) {
53110
53332
  entries
53111
53333
  };
53112
53334
  }
53335
+ var GENERIC_CLIENT_FLAG_HINT = "Use lowercase tokens matching [a-z0-9-]+, e.g. `wh auth login --flag <name>`.";
53336
+ function invalidClientFlagMessage(token) {
53337
+ const base = `Invalid client flag "${token}": expected lowercase tokens matching [a-z0-9-]+`;
53338
+ const normalized = token.trim().toLowerCase();
53339
+ return isValidClientFlagToken(normalized) ? `${base} (did you mean "${normalized}"?)` : `${base}.`;
53340
+ }
53113
53341
  var handleLogin = async (ctx, { flags }) => {
53114
53342
  const profile = flags.profile ?? ctx.config.profile ?? "default";
53343
+ const requestedFlags = (flags.flag ?? []).map((t) => t.trim());
53344
+ for (const token of requestedFlags) {
53345
+ if (!isValidClientFlagToken(token)) {
53346
+ throw new CliError(2 /* UserInput */, "USER_INPUT", invalidClientFlagMessage(token), undefined, GENERIC_CLIENT_FLAG_HINT);
53347
+ }
53348
+ }
53349
+ const explicitFlags = requestedFlags.length > 0 ? [...new Set(requestedFlags)].sort() : undefined;
53115
53350
  if (flags["with-token"]) {
53116
- return loginWithToken(ctx, profile);
53351
+ return loginWithToken(ctx, profile, explicitFlags);
53117
53352
  }
53118
53353
  const c = ctx.colors;
53119
53354
  let clientId;
@@ -53121,7 +53356,8 @@ var handleLogin = async (ctx, { flags }) => {
53121
53356
  clientId = await ctx.client.auth.getClientId();
53122
53357
  } catch {
53123
53358
  clientId = await createUnauthenticatedClient(ctx.config, {
53124
- functionLogs: ctx.functionLogMode
53359
+ functionLogs: ctx.functionLogMode,
53360
+ clientFlags: ctx.clientFlags
53125
53361
  }).auth.getClientId();
53126
53362
  }
53127
53363
  if (!clientId) {
@@ -53185,7 +53421,7 @@ var handleLogin = async (ctx, { flags }) => {
53185
53421
  } catch {
53186
53422
  expiresAt = new Date(Date.now() + 5 * 60 * 1000).toISOString();
53187
53423
  }
53188
- await saveProfileLocked(profile, {
53424
+ await saveProfileWithFlagsLocked(profile, {
53189
53425
  tokens: {
53190
53426
  accessToken: tokenResponse.access_token,
53191
53427
  refreshToken: tokenResponse.refresh_token,
@@ -53196,9 +53432,9 @@ var handleLogin = async (ctx, { flags }) => {
53196
53432
  source: "device"
53197
53433
  },
53198
53434
  apiUrl: ctx.config.apiUrl
53199
- });
53435
+ }, explicitFlags);
53200
53436
  try {
53201
- await ctx.client.auth.sync();
53437
+ await clientForStoredFlags(ctx, profile).auth.sync();
53202
53438
  } catch (err) {
53203
53439
  ctx.err(`${c.yellow}Warning: could not sync user record: ${err instanceof Error ? err.message : String(err)}${c.reset}`);
53204
53440
  }
@@ -53238,10 +53474,11 @@ var handleStatus = async (ctx, { flags }) => {
53238
53474
  const entry = authStatusEntry(info, {
53239
53475
  active: true,
53240
53476
  apiUrl: prof.apiUrl,
53477
+ flags: Array.isArray(prof.flags) ? prof.flags : [],
53241
53478
  identityWref,
53242
53479
  profile: selectedProfile
53243
53480
  });
53244
- writeOutput(ctx, authStatusOutput(selectedProfile, [entry]), () => renderTokenInfo(ctx, info, selectedProfile, prof.apiUrl, identityWref));
53481
+ writeOutput(ctx, authStatusOutput(selectedProfile, [entry]), () => renderTokenInfo(ctx, info, selectedProfile, prof.apiUrl, identityWref, entry.flags));
53245
53482
  return;
53246
53483
  }
53247
53484
  const envToken = process.env.WH_TOKEN;
@@ -53270,13 +53507,15 @@ var handleStatus = async (ctx, { flags }) => {
53270
53507
  canRefresh: source === "device" && !!tokens.refreshToken
53271
53508
  };
53272
53509
  const identityWref = !info.expired && name === activeProfile ? await fetchIdentityWref(ctx) : null;
53510
+ const profileFlags = Array.isArray(prof.flags) ? prof.flags : [];
53273
53511
  entries.push(authStatusEntry(info, {
53274
53512
  active: !envToken && name === activeProfile,
53275
53513
  apiUrl: prof.apiUrl,
53514
+ flags: profileFlags,
53276
53515
  identityWref,
53277
53516
  profile: name
53278
53517
  }));
53279
- prettyEntries.push(() => renderTokenInfo(ctx, info, name, prof.apiUrl, identityWref));
53518
+ prettyEntries.push(() => renderTokenInfo(ctx, info, name, prof.apiUrl, identityWref, profileFlags));
53280
53519
  }
53281
53520
  }
53282
53521
  writeOutput(ctx, authStatusOutput(envToken ? null : activeProfile, entries), () => {
@@ -53781,9 +54020,8 @@ function requireMembers(members, example) {
53781
54020
  }
53782
54021
  }
53783
54022
  function renderMutation(ctx, result) {
53784
- assertSingleOpSuccess(result);
53785
- const operation = result.operations[0];
53786
- if (!operation || !("version" in operation) || typeof operation.version !== "number") {
54023
+ const operation = requireSingleOpSuccess(result);
54024
+ if (!("version" in operation) || typeof operation.version !== "number") {
53787
54025
  throw new Error("Collection mutation returned no version-bearing operation");
53788
54026
  }
53789
54027
  const isNoop = operation.operation === "noop";
@@ -54023,10 +54261,11 @@ var collectionStatsFlags = {
54023
54261
  version: flag.number({ description: "Specific collection version number" })
54024
54262
  };
54025
54263
  function validateCollectionType(value) {
54026
- if (!value || !SUPPORTED_COLLECTION_TYPES.includes(value)) {
54264
+ const parsed = SUPPORTED_COLLECTION_TYPES.find((candidate) => candidate === value);
54265
+ if (!parsed) {
54027
54266
  usageError(`Usage: wh collection create --type ${CANONICAL_COLLECTION_TYPE_USAGE} --members <wref...>`, 'wh collection create --type set --name audited --members Location/a,Location/b -m "audit snapshot"');
54028
54267
  }
54029
- return value;
54268
+ return parsed;
54030
54269
  }
54031
54270
  function validateDiffMode(value) {
54032
54271
  if (value === undefined)
@@ -54052,7 +54291,7 @@ function collectionQuerySourceFromFlags(flags) {
54052
54291
  function parseSourceRepoFlag(value) {
54053
54292
  if (!value)
54054
54293
  return;
54055
- const parsed = splitRepoSlug(value);
54294
+ const parsed = parseRepoSlug(value);
54056
54295
  if (!parsed) {
54057
54296
  usageError("--source-repo must be an org/repo slug", "wh collection create --type set --name wake-voters --source-repo data/nc-voters --shape Voter --where county=Wake");
54058
54297
  }
@@ -54089,7 +54328,7 @@ function isMissingCollectionMemberError(error51, type) {
54089
54328
  function collectionTypeFromWref2(wref) {
54090
54329
  const local = wref.replace(/^wh:[^/]+\/[^/]+\//, "").replace(/@(?:HEAD|ALL|v\d+)$/, "");
54091
54330
  const shape = local.split("/")[0]?.toLowerCase();
54092
- return SUPPORTED_COLLECTION_TYPES.includes(shape) ? shape : undefined;
54331
+ return SUPPORTED_COLLECTION_TYPES.find((candidate) => candidate === shape);
54093
54332
  }
54094
54333
  function parseCollectionReadRepo(ctx, wrefs) {
54095
54334
  const allDurable = wrefs.length > 0 && wrefs.every(looksLikeDurableId);
@@ -54685,6 +54924,7 @@ function assertNoNulBytes(data, locator) {
54685
54924
 
54686
54925
  // ../../packages/warmhub-cli/src/domains/commit-submit-template.ts
54687
54926
  import { writeFile } from "node:fs/promises";
54927
+ var WRITE_TEMPLATE_KINDS = ["thing", "assertion"];
54688
54928
  function zeroValueForField(fieldSpec) {
54689
54929
  if (Array.isArray(fieldSpec))
54690
54930
  return [];
@@ -54773,20 +55013,21 @@ var handleTemplate = async (ctx, { flags, args }) => {
54773
55013
  if (operationType !== "add" && operationType !== "revise" && operationType !== "retract") {
54774
55014
  throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid --operation "${operationType}". Must be "add", "revise", or "retract".`);
54775
55015
  }
54776
- const validKinds = operationType === "retract" ? COMMIT_OPERATION_KINDS : ["thing", "assertion"];
54777
- if (!validKinds.includes(flags.kind ?? "thing")) {
55016
+ const requestedKind = flags.kind ?? "thing";
55017
+ const validKinds = operationType === "retract" ? COMMIT_OPERATION_KINDS : WRITE_TEMPLATE_KINDS;
55018
+ const templateKind = validKinds.find((candidate) => candidate === requestedKind);
55019
+ if (templateKind === undefined) {
54778
55020
  throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid --kind "${flags.kind}". Must be one of: ${validKinds.join(", ")}.`);
54779
55021
  }
54780
55022
  const count = Math.max(1, flags.count ?? 1);
54781
55023
  const operations = [];
54782
55024
  for (const shapeName of shapeNames) {
54783
55025
  if (operationType === "retract") {
54784
- const kind2 = flags.kind ?? "thing";
54785
55026
  for (let i = 0;i < count; i++) {
54786
55027
  operations.push({
54787
55028
  operation: "retract",
54788
- kind: kind2,
54789
- name: kind2 === "shape" ? shapeName : `${shapeName}/FILL_IN`
55029
+ kind: templateKind,
55030
+ name: templateKind === "shape" ? shapeName : `${shapeName}/FILL_IN`
54790
55031
  });
54791
55032
  }
54792
55033
  continue;
@@ -54795,9 +55036,8 @@ var handleTemplate = async (ctx, { flags, args }) => {
54795
55036
  const shapeVersion = shape.version;
54796
55037
  const shapeData = shapeVersion?.data;
54797
55038
  const fields = shapeData?.fields ?? {};
54798
- const kind = flags.kind ?? "thing";
54799
55039
  let aboutPlaceholder;
54800
- if (kind === "assertion") {
55040
+ if (templateKind === "assertion") {
54801
55041
  aboutPlaceholder = flags.about ? parseCollectionAboutFlag(flags.about) : "Shape/FILL_IN";
54802
55042
  }
54803
55043
  const data = buildTemplateData(fields);
@@ -54805,13 +55045,13 @@ var handleTemplate = async (ctx, { flags, args }) => {
54805
55045
  for (let i = 0;i < count; i++) {
54806
55046
  const op = operationType === "add" ? {
54807
55047
  operation: "add",
54808
- kind,
55048
+ kind: templateKind,
54809
55049
  name: `${shapeName}/${nameSuffix(i)}`,
54810
55050
  ...aboutPlaceholder ? { about: aboutPlaceholder } : {},
54811
55051
  data
54812
55052
  } : {
54813
55053
  operation: "revise",
54814
- kind,
55054
+ kind: templateKind,
54815
55055
  name: `${shapeName}/FILL_IN`,
54816
55056
  data
54817
55057
  };
@@ -55481,17 +55721,19 @@ var handleSubmit = async (ctx, { flags, args }) => {
55481
55721
  "shape",
55482
55722
  "collection"
55483
55723
  ];
55484
- for (const k of kinds) {
55485
- if (!validKinds.includes(k)) {
55724
+ const operationKinds = kinds.map((k) => {
55725
+ const parsed = validKinds.find((candidate) => candidate === k);
55726
+ if (!parsed) {
55486
55727
  throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid --kind "${k}". Must be one of: ${validKinds.join(", ")}`);
55487
55728
  }
55488
- }
55729
+ return parsed;
55730
+ });
55489
55731
  const validCollectionTypes = ["arc", "bond", "set", "list", "pair"];
55490
55732
  const canonicalCollectionTypes2 = ["arc", "bond", "set", "list"];
55491
- if (flags.type && !validCollectionTypes.includes(flags.type)) {
55733
+ const collectionType = validCollectionTypes.find((candidate) => candidate === flags.type);
55734
+ if (flags.type !== undefined && collectionType === undefined) {
55492
55735
  throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid --type "${flags.type}". Use one of: ${canonicalCollectionTypes2.join(", ")}`, undefined, "wh commit submit --type arc --name route --members Location/a,Location/b");
55493
55736
  }
55494
- const collectionType = flags.type;
55495
55737
  const jsonlFile = opsFile?.endsWith(".jsonl") === true;
55496
55738
  const operationSource = resolveCommitOperationSource({
55497
55739
  stream: streamInput,
@@ -55510,7 +55752,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
55510
55752
  shape: shapes.length > 0,
55511
55753
  about: abouts.length > 0,
55512
55754
  reason: reasons.length > 0,
55513
- kind: kinds.length > 0,
55755
+ kind: operationKinds.length > 0,
55514
55756
  name: flags.name !== undefined,
55515
55757
  members: flags.members !== undefined
55516
55758
  });
@@ -55586,12 +55828,12 @@ var handleSubmit = async (ctx, { flags, args }) => {
55586
55828
  dataJsons,
55587
55829
  shapes,
55588
55830
  abouts,
55589
- kinds
55831
+ kinds: operationKinds
55590
55832
  });
55591
55833
  } else if (operationSource === "--retract") {
55592
55834
  operations = buildRetractOperations({
55593
55835
  retractNames,
55594
- kinds,
55836
+ kinds: operationKinds,
55595
55837
  reasons,
55596
55838
  expectedVersion,
55597
55839
  leaseId: leaseIdFlag
@@ -55600,12 +55842,12 @@ var handleSubmit = async (ctx, { flags, args }) => {
55600
55842
  if (dataJsons.length > 1) {
55601
55843
  throw new CliError(2 /* UserInput */, "USER_INPUT", `--revise supports a single operation, but --data was repeated ${dataJsons.length} times.`, undefined, "Use --file <path.json> for multi-revision writes.");
55602
55844
  }
55603
- if (kinds.length > 1) {
55604
- throw new CliError(2 /* UserInput */, "USER_INPUT", `--revise supports a single operation, but --kind was repeated ${kinds.length} times.`, undefined, "Use --file <path.json> for multi-revision writes.");
55845
+ if (operationKinds.length > 1) {
55846
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `--revise supports a single operation, but --kind was repeated ${operationKinds.length} times.`, undefined, "Use --file <path.json> for multi-revision writes.");
55605
55847
  }
55606
55848
  const rawData = dataJsons[0];
55607
55849
  const data = rawData !== undefined ? parseJsonObject(rawData, "--data") : undefined;
55608
- const kindFlag = kinds[0];
55850
+ const kindFlag = operationKinds[0];
55609
55851
  const kind = kindFlag ?? "thing";
55610
55852
  operations = [
55611
55853
  {
@@ -56018,8 +56260,7 @@ function bindComponentMethodArgs(invocation, method) {
56018
56260
  }
56019
56261
  const coerced = coerceArg(arg, raw);
56020
56262
  if (!coerced.ok) {
56021
- if (coerced.error)
56022
- addError(record2.index, coerced.error);
56263
+ addError(record2.index, coerced.error);
56023
56264
  continue;
56024
56265
  }
56025
56266
  if (!Object.hasOwn(args, arg.name))
@@ -56037,7 +56278,7 @@ function bindComponentMethodArgs(invocation, method) {
56037
56278
  const coerced = coerceArg(arg, arg.default);
56038
56279
  if (coerced.ok) {
56039
56280
  args[arg.name] = coerced.value;
56040
- } else if (coerced.error) {
56281
+ } else {
56041
56282
  addError(Number.POSITIVE_INFINITY, coerced.error);
56042
56283
  }
56043
56284
  continue;
@@ -56397,63 +56638,62 @@ function formatReservedNameWarning(name) {
56397
56638
  // ../../packages/warmhub-cli/src/manifest/parser.ts
56398
56639
  import { existsSync as existsSync8, readFileSync as readFileSync9 } from "node:fs";
56399
56640
  import { resolve } from "node:path";
56400
- function parseComponentPackage(dirPath) {
56401
- const rootDir = resolve(dirPath);
56402
- const errors3 = [];
56403
- const warnings = [];
56404
- const componentJsonPath = resolve(rootDir, "warmhub", "component.json");
56405
- if (!existsSync8(componentJsonPath)) {
56406
- errors3.push(`Missing warmhub/component.json at ${componentJsonPath}`);
56407
- return { ok: false, errors: errors3, warnings };
56641
+ function loadDocument(rootDir, fileName, validate) {
56642
+ const path2 = resolve(rootDir, "warmhub", fileName);
56643
+ if (!existsSync8(path2)) {
56644
+ return {
56645
+ valid: false,
56646
+ errors: [`Missing warmhub/${fileName} at ${path2}`],
56647
+ warnings: []
56648
+ };
56408
56649
  }
56409
- let componentRaw;
56410
- try {
56411
- componentRaw = JSON.parse(readFileSync9(componentJsonPath, "utf-8"));
56412
- } catch (err) {
56413
- errors3.push(`Failed to parse warmhub/component.json: ${err instanceof Error ? err.message : String(err)}`);
56414
- return { ok: false, errors: errors3, warnings };
56415
- }
56416
- const componentResult = validateComponentJson(componentRaw);
56417
- errors3.push(...componentResult.errors);
56418
- warnings.push(...componentResult.warnings);
56419
- const manifestJsonPath = resolve(rootDir, "warmhub", "manifest.json");
56420
- if (!existsSync8(manifestJsonPath)) {
56421
- errors3.push(`Missing warmhub/manifest.json at ${manifestJsonPath}`);
56422
- return { ok: false, errors: errors3, warnings };
56423
- }
56424
- let manifestRaw;
56650
+ let raw;
56425
56651
  try {
56426
- manifestRaw = JSON.parse(readFileSync9(manifestJsonPath, "utf-8"));
56652
+ raw = JSON.parse(readFileSync9(path2, "utf-8"));
56427
56653
  } catch (err) {
56428
- errors3.push(`Failed to parse warmhub/manifest.json: ${err instanceof Error ? err.message : String(err)}`);
56429
- return { ok: false, errors: errors3, warnings };
56430
- }
56431
- const manifestResult = validateManifestJson(manifestRaw);
56432
- errors3.push(...manifestResult.errors);
56433
- warnings.push(...manifestResult.warnings);
56434
- if (errors3.length > 0) {
56435
- return { ok: false, errors: errors3, warnings };
56654
+ return {
56655
+ valid: false,
56656
+ errors: [
56657
+ `Failed to parse warmhub/${fileName}: ${err instanceof Error ? err.message : String(err)}`
56658
+ ],
56659
+ warnings: []
56660
+ };
56436
56661
  }
56437
- if (!componentResult.value || !manifestResult.value) {
56662
+ return validate(raw);
56663
+ }
56664
+ function parseComponentPackage(dirPath) {
56665
+ const rootDir = resolve(dirPath);
56666
+ const component = loadDocument(rootDir, "component.json", validateComponentJson);
56667
+ const manifest = loadDocument(rootDir, "manifest.json", validateManifestJson);
56668
+ const warnings = [...component.warnings, ...manifest.warnings];
56669
+ if (!component.valid && !manifest.valid) {
56438
56670
  return {
56439
56671
  ok: false,
56440
- errors: ["Validated component package is missing parsed values"],
56672
+ errors: [...component.errors, ...manifest.errors],
56441
56673
  warnings
56442
56674
  };
56443
56675
  }
56676
+ if (!component.valid) {
56677
+ return { ok: false, errors: component.errors, warnings };
56678
+ }
56679
+ if (!manifest.valid) {
56680
+ return { ok: false, errors: manifest.errors, warnings };
56681
+ }
56444
56682
  return {
56445
56683
  ok: true,
56446
- errors: [],
56447
56684
  warnings,
56448
56685
  package: {
56449
- meta: componentResult.value,
56450
- manifest: manifestResult.value,
56686
+ meta: component.value,
56687
+ manifest: manifest.value,
56451
56688
  rootDir
56452
56689
  }
56453
56690
  };
56454
56691
  }
56455
56692
 
56456
56693
  // ../../packages/warmhub-cli/src/manifest/validate.ts
56694
+ function hasBlockingFindings(findings) {
56695
+ return findings.some((finding) => finding.level === "error");
56696
+ }
56457
56697
  function crossValidate(pkg) {
56458
56698
  const findings = [];
56459
56699
  const { meta: meta3, manifest } = pkg;
@@ -56472,8 +56712,7 @@ function crossValidate(pkg) {
56472
56712
  });
56473
56713
  }
56474
56714
  findings.push(...validateManifestSemantics(manifest));
56475
- const hasErrors = findings.some((f) => f.level === "error");
56476
- return { valid: !hasErrors, findings };
56715
+ return { findings };
56477
56716
  }
56478
56717
  function validateComponentPackage(pkg) {
56479
56718
  return crossValidate(pkg);
@@ -56632,14 +56871,11 @@ function resolveRegisteredComponentRef(ref, usage, example) {
56632
56871
  if (!ref) {
56633
56872
  usageError(usage, example);
56634
56873
  }
56635
- const parts = ref.split("/");
56636
- if (parts.length !== 2 || !parts[0] || !parts[1]) {
56874
+ const parsed = parseComponentRef(ref);
56875
+ if (!parsed) {
56637
56876
  usageError(`Invalid component reference '${ref}'. Expected '<org>/<name>' with no extra slashes and no empty parts.`, example);
56638
56877
  }
56639
- return {
56640
- orgName: parts[0],
56641
- componentName: parts[1]
56642
- };
56878
+ return { orgName: parsed.org, componentName: parsed.name };
56643
56879
  }
56644
56880
  function resolveRegistryVisibility(args) {
56645
56881
  if (args.isPrivate && args.isPublic) {
@@ -56845,13 +57081,9 @@ var handleValidate = async (ctx, { args }) => {
56845
57081
  writeOutput(ctx, result2, () => renderValidationResult(ctx, result2));
56846
57082
  throw new CliError(2 /* UserInput */, "USER_INPUT", "Component package validation failed");
56847
57083
  }
56848
- const parsedPackage = parseResult.package;
56849
- if (!parsedPackage) {
56850
- throw new CliError(1 /* Runtime */, "UNKNOWN", "Component package validation returned no package");
56851
- }
56852
- const crossResult = validateComponentPackage(parsedPackage);
57084
+ const crossResult = validateComponentPackage(parseResult.package);
56853
57085
  const result = {
56854
- valid: crossResult.valid,
57086
+ valid: !hasBlockingFindings(crossResult.findings),
56855
57087
  errors: [],
56856
57088
  warnings: parseResult.warnings,
56857
57089
  findings: crossResult.findings
@@ -58305,7 +58537,7 @@ async function collectChecks(ctx) {
58305
58537
  const repoFlag = getRepoRef(ctx);
58306
58538
  const hasRepoFlag = repoFlag !== undefined;
58307
58539
  const repo = repoFlag ?? ctx.config.defaultRepo;
58308
- const repoParts = repo !== undefined ? splitRepoSlug(repo) : null;
58540
+ const repoParts = repo !== undefined ? parseRepoSlug(repo) : null;
58309
58541
  const repoForDisplay = repo !== undefined ? escapeTerminalTextForDisplay(repo) : undefined;
58310
58542
  const repoSource = hasRepoFlag ? "flag" : ctx.config.configSource?.repo;
58311
58543
  const repoProvenance = repoSource === "env" ? " (from WARMHUB_REPO)" : repoSource === "wh-file" ? " (from .wh file)" : repoSource === "flag" ? " (from --repo flag)" : "";
@@ -58638,7 +58870,7 @@ var handleDoctor2 = async (ctx, { flags }) => {
58638
58870
  ctx.out(` ${c.dim}${line}${c.reset}`);
58639
58871
  }
58640
58872
  }
58641
- if (check2.fix && check2.status !== "ok") {
58873
+ if (check2.fix) {
58642
58874
  for (const line of check2.fix.split(`
58643
58875
  `)) {
58644
58876
  ctx.out(` ${c.dim}${line}${c.reset}`);
@@ -58684,6 +58916,120 @@ var DOCTOR_DOMAIN = defineDomain({
58684
58916
  handler: handleDoctor2
58685
58917
  });
58686
58918
 
58919
+ // ../../packages/warmhub-cli/src/domains/grant.ts
58920
+ var createFlags5 = {
58921
+ key: flag.string({ description: "issuer-scoped idempotency key" }),
58922
+ coverage: flag.string({
58923
+ description: "inline coverage JSON ({include, exclude?})"
58924
+ }),
58925
+ op: flag.string({
58926
+ description: "operation to grant (repeatable)",
58927
+ multiple: true
58928
+ })
58929
+ };
58930
+ var listFlags3 = {
58931
+ limit: flag.number({ description: "max records (default: 50, max: 100)" }),
58932
+ cursor: flag.string({ description: "grant keyset cursor" })
58933
+ };
58934
+ var revokeFlags2 = {
58935
+ reason: flag.string({ description: "revocation audit reason" })
58936
+ };
58937
+ function repo(ctx) {
58938
+ return parseOrgRepo(getRepoRef(ctx), ctx.config);
58939
+ }
58940
+ var handleCreate4 = async (ctx, { args, flags }) => {
58941
+ const [principalKind, principalId] = args;
58942
+ if (!principalKind || !principalId || !flags.key || !flags.op?.length) {
58943
+ usageError("Usage: wh grant create <member|pat|component> <principal-id> --key KEY --op OP [--op OP] --coverage JSON", `wh grant create component install-1:7 --key provision --op things:read --coverage '{"include":["Lesson/**"]}'`);
58944
+ }
58945
+ if (!flags.coverage) {
58946
+ usageError("Grant create requires --coverage.", `wh grant create component install-1:7 --key provision --op things:read --coverage '{"include":["Lesson/**"]}'`);
58947
+ }
58948
+ if (!["member", "pat", "component"].includes(principalKind)) {
58949
+ usageError("Grant grantee kind must be member, pat, or component.", `wh grant create component install-1:7 --key provision --op things:read --coverage '{"include":["Lesson/**"]}'`);
58950
+ }
58951
+ let coverage;
58952
+ try {
58953
+ coverage = JSON.parse(flags.coverage);
58954
+ } catch {
58955
+ usageError("--coverage must be valid JSON.", `wh grant create component install-1:7 --key provision --op things:read --coverage '{"include":["Lesson/**"]}'`);
58956
+ }
58957
+ const { org, repo: repoName } = repo(ctx);
58958
+ const result = await ctx.client.grant.create(org, repoName, {
58959
+ idempotencyKey: flags.key,
58960
+ grantee: {
58961
+ principalId,
58962
+ principalKind
58963
+ },
58964
+ coverage,
58965
+ ops: flags.op
58966
+ });
58967
+ writeOutput(ctx, result, () => ctx.out(JSON.stringify(result, null, 2)));
58968
+ };
58969
+ var handleGet = async (ctx, { args }) => {
58970
+ const grantId = args[0];
58971
+ if (!grantId) {
58972
+ usageError("Usage: wh grant get <grant-id>", "wh grant get 019b57b6-7a42-7000-8000-000000000000");
58973
+ }
58974
+ const { org, repo: repoName } = repo(ctx);
58975
+ const result = await ctx.client.grant.get(org, repoName, grantId);
58976
+ writeOutput(ctx, result, () => ctx.out(JSON.stringify(result, null, 2)));
58977
+ };
58978
+ var handleList4 = async (ctx, { flags }) => {
58979
+ const { org, repo: repoName } = repo(ctx);
58980
+ const limit = Math.min(flags.limit ?? 50, 100);
58981
+ const result = await ctx.client.grant.list(org, repoName, {
58982
+ limit,
58983
+ cursor: flags.cursor
58984
+ });
58985
+ writePageOutput(ctx, result.items, { limit, nextCursor: result.nextCursor ?? null }, () => ctx.out(JSON.stringify(result.items, null, 2)));
58986
+ };
58987
+ var handleRevoke2 = async (ctx, { args, flags }) => {
58988
+ const grantId = args[0];
58989
+ if (!grantId) {
58990
+ usageError("Usage: wh grant revoke <grant-id> [--reason TEXT]", "wh grant revoke 019b57b6-7a42-7000-8000-000000000000 --reason superseded");
58991
+ }
58992
+ const { org, repo: repoName } = repo(ctx);
58993
+ const result = await ctx.client.grant.revoke(org, repoName, grantId, {
58994
+ reason: flags.reason
58995
+ });
58996
+ writeOutput(ctx, result, () => ctx.out(JSON.stringify(result, null, 2)));
58997
+ };
58998
+ var GRANT_DOMAIN = defineDomain({
58999
+ name: "grant",
59000
+ summary: "Immutable repository Grant administration",
59001
+ group: "resource",
59002
+ verbs: {
59003
+ create: {
59004
+ prime: true,
59005
+ summary: "Create or replay an issuer-scoped Grant request",
59006
+ args: "<member|pat|component> <principal-id>",
59007
+ flags: createFlags5,
59008
+ handler: handleCreate4
59009
+ },
59010
+ get: {
59011
+ prime: true,
59012
+ summary: "Get one active or revoked Grant",
59013
+ args: "<grant-id>",
59014
+ handler: handleGet
59015
+ },
59016
+ list: {
59017
+ prime: true,
59018
+ summary: "List active and revoked Grants",
59019
+ args: "",
59020
+ flags: listFlags3,
59021
+ handler: handleList4
59022
+ },
59023
+ revoke: {
59024
+ prime: true,
59025
+ summary: "Revoke a Grant idempotently",
59026
+ args: "<grant-id>",
59027
+ flags: revokeFlags2,
59028
+ handler: handleRevoke2
59029
+ }
59030
+ }
59031
+ });
59032
+
58687
59033
  // ../../packages/warmhub-cli/src/domains/init.ts
58688
59034
  import { basename as basename4 } from "node:path";
58689
59035
 
@@ -58692,7 +59038,7 @@ async function onboardRepo(ctx, repoRef, description) {
58692
59038
  if (!repoRef?.includes("/")) {
58693
59039
  throw new CliError(2 /* UserInput */, "USER_INPUT", "Usage: wh init [org/repo] [--description <desc>]", undefined, "Example: wh init my-org/my-repo");
58694
59040
  }
58695
- const parsed = splitRepoSlug(repoRef);
59041
+ const parsed = parseRepoSlug(repoRef);
58696
59042
  if (!parsed) {
58697
59043
  throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid repo format "${repoRef}". Expected "org/repo".`, undefined, "Example: wh init my-org/my-repo");
58698
59044
  }
@@ -58890,8 +59236,8 @@ function parseSince(raw, usage, example) {
58890
59236
  var handleNotifications = async (ctx, { flags }) => {
58891
59237
  const usage = "Usage: wh notifications [--repo org/repo] [--limit n] [--since <epoch-ms|iso>]";
58892
59238
  const example = "wh notifications --repo myorg/myrepo --since 2026-03-30T12:00:00Z";
58893
- const { org, repo } = resolveRepoContext(ctx);
58894
- const result = await ctx.client.action.listNotifications(org, repo, {
59239
+ const { org, repo: repo2 } = resolveRepoContext(ctx);
59240
+ const result = await ctx.client.action.listNotifications(org, repo2, {
58895
59241
  since: parseSince(flags.since, usage, example),
58896
59242
  limit: flags.limit
58897
59243
  });
@@ -59321,11 +59667,11 @@ var handleUpdate2 = async (ctx, { args, flags }) => {
59321
59667
  };
59322
59668
 
59323
59669
  // ../../packages/warmhub-cli/src/domains/org.ts
59324
- var createFlags5 = {
59670
+ var createFlags6 = {
59325
59671
  "display-name": flag.string({ description: "Display name for the org" }),
59326
59672
  description: flag.string({ short: "d", description: "Org description" })
59327
59673
  };
59328
- var handleCreate4 = async (ctx, { flags, args }) => {
59674
+ var handleCreate5 = async (ctx, { flags, args }) => {
59329
59675
  const name = args[0];
59330
59676
  if (!name) {
59331
59677
  usageError('Usage: wh org create <name> [--display-name "..."] [--description "..."]', 'wh org create caryden --display-name "Carl Ryden" -d "A great org"');
@@ -59367,12 +59713,12 @@ var handleView5 = async (ctx, { args }) => {
59367
59713
  ctx.out(`${c.dim}Created: ${new Date(result.createdAt).toISOString().slice(0, 16)}${c.reset}`);
59368
59714
  });
59369
59715
  };
59370
- var listFlags3 = {
59716
+ var listFlags4 = {
59371
59717
  "include-archived": flag.boolean({
59372
59718
  description: "Include archived organizations"
59373
59719
  })
59374
59720
  };
59375
- var handleList4 = async (ctx, { flags }) => {
59721
+ var handleList5 = async (ctx, { flags }) => {
59376
59722
  const c = ctx.colors;
59377
59723
  const result = await ctx.client.org.list({
59378
59724
  includeArchived: flags["include-archived"]
@@ -59479,9 +59825,9 @@ var ORG_DOMAIN = defineDomain({
59479
59825
  prime: true,
59480
59826
  summary: "Create a new organization",
59481
59827
  args: "<name>",
59482
- flags: createFlags5,
59828
+ flags: createFlags6,
59483
59829
  examples: ['wh org create caryden --display-name "Carl Ryden"'],
59484
- handler: handleCreate4
59830
+ handler: handleCreate5
59485
59831
  },
59486
59832
  view: {
59487
59833
  prime: true,
@@ -59494,9 +59840,9 @@ var ORG_DOMAIN = defineDomain({
59494
59840
  prime: true,
59495
59841
  summary: "List all organizations",
59496
59842
  args: "",
59497
- flags: listFlags3,
59843
+ flags: listFlags4,
59498
59844
  examples: ["wh org list", "wh org list --include-archived"],
59499
- handler: handleList4
59845
+ handler: handleList5
59500
59846
  },
59501
59847
  update: {
59502
59848
  summary: "Update org settings",
@@ -59538,7 +59884,7 @@ var ORG_DOMAIN = defineDomain({
59538
59884
  });
59539
59885
 
59540
59886
  // ../../packages/warmhub-cli/src/domains/prime-content.md
59541
- var prime_content_default = "# WarmHub CLI Context\n> **Context Recovery**: Run `wh prime` after compaction or new session\n\n## Environment\n{{REPO_LINE}}\n\n## Core Concepts\n- **Thing**: A named entity versioned by writes. **Assertion**: A thing that makes a shape-validated claim about another thing.\n- **Shape**: A thing defining data structure; every other thing has one. **Write**: One or more add/revise/retract operations with per-operation results.\n- **wref**: A reference to a thing. Local: `Player` (the shape) or `Player/alice` (a thing with that shape). Cross-repo: `wh:org/repo/Shape` or `wh:org/repo/Shape/name`.\n\n## Versioned Wrefs\n- `Shape` addresses the shape itself; `Shape/name` addresses a thing with that shape. `@vN` pins either.\n- Floating write refs to retracted targets fail; existing pinned versions remain valid.\n- Rename invalidates old spellings, including `@vN`; the new name resolves history.\n- Untyped wrefs accept any thing. `wref<T>` requires the target's shape to be `T`; a shape has no shape, so never satisfies it. `wref?` coalesces only `thing_absent`, never a missing shape.\n\n## Key Workflows\n\n**Write data** (discover shapes → scaffold ops → submit):\n```bash\nwh shape list --repo org/repo # list available shapes\nwh shape view ShapeName --repo org/repo # inspect fields\nwh shape template ShapeName -o ops.json --repo org/repo # scaffold write ops (supports --kind assertion)\n# edit ops.json — fill FILL_IN placeholders — then:\nwh commit submit --file ops.json -m \"msg\" --repo org/repo # submit operations (bare `wh commit` also works)\n# or single assertion (no file needed):\nwh assertion create --shape ShapeName --about Target/name --name my-assertion --data '{\"field\":1}' --repo org/repo\n# Relay failed operation details when present. Never hand-guess ops JSON — use `wh shape template <Shape>`.\n```\n\n**Read data:**\n```bash\nwh thing list --repo org/repo # all things at HEAD\nwh thing view Shape/name --repo org/repo # inspect a thing\nwh thing query --shape MyShape --repo org/repo # find things by shape\nwh thing about Shape --repo org/repo # assertions about a shape\nwh assertion list --repo org/repo # all assertions at HEAD\nwh thing history Shape/name --repo org/repo # version history\n\n# Batch read — wh thing view is variadic (max 500 wrefs/call):\nwh thing view Player/alice Player/bob # variadic positionals\nwh thing view --file wrefs.txt --json # one wref per line\ncat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped* requested wref\n```\n\n## Wref Quick Reference\n\nWrites use explicit names and wrefs. Untyped fields, collection members,\nassertion `about`, and committers accept any thing. Create a deterministic\ntarget before referencing it in the same commit.\n\n## Command Reference\n\n**Global flags**: `--repo`, `--format`, `--json`, `--live`\n### thing — Thing operations\n- `wh thing list [--shape] [--kind] [--match] [--include-retracted]` — Current HEAD state\n- `wh thing view [<wref>...] [--file <path>] [--version] [--depth] [--include-retracted] [--data-mode auto|full]` — Thing details. Variadic (max 500). `--version` implies `--include-retracted`. Batch JSON returns `{ requested, items, missing }`; jsonl emits one row per deduped requested wref. Large Set/List bodies summarize by default; use `--data-mode full` for canonical collection JSON.\n- `wh thing history [wref] [--shape] [--about] [--include-retracted]` — Version history\n- `wh thing resolve <wref>` — Resolve a wref to its canonical thing identity\n- `wh thing create <name|Shape/name> (--data|--file) [--shape]` — Create\n- `wh thing revise <name> [--data] [--message] [--committer] [--expected-version]` — Revise (CONFLICT if HEAD≠n)\n- `wh thing retract <wref> -m <message> [--reason] [--kind] [--expected-version]` — Retract\n- `wh thing query [--shape] [--kind] [--about] [--match]` — Query by filters\n- `wh thing search <query> [--shape] [--kind] [--about] [--mode]` — Search text\n- `wh thing rename <Shape/oldName> <newName>` — Rename\n- `wh thing refs <wref> [--inbound] [--outbound] [--field]` — Show field references; use `wh thing about` for assertions about the target thing\n- `wh thing about <wref> [--shape] [--match] [--depth] [--resolve-collections] [--role from|to|ends] [--limit] [--include-retracted]` — Show assertions about the target identity; `--resolve-collections` expands bare/@HEAD/@ALL members, `--role` filters direction; not pinned @vN\n\n### commit — Write operations\n- `wh commit submit [--ops|--file|--add|--revise|--retract] [--kind] [--data] [--reason] [--expected-version] [--chunk-size] [--skip-existing] [--progress] [--stream-id]` — Submit operations (bare `wh commit` is equivalent). Use `--file ops.jsonl --stream-id <id> --chunk-size 5000 --skip-existing` for bulk ingest.\n- `wh shape template <shape> [shape2 ...] [--kind] [--operation add|revise|retract] [-o file]` — Generate sample ops\n\n### assertion — Assertion operations\n- `wh assertion list [--about wref] [--shape] [--match] [--include-retracted]` — Browse assertions\n- `wh assertion view <wref> [--version] [--include-retracted]` — Assertion details\n- `wh assertion create --shape <s> --name <n> --about <wref> [--data] [-m] [--committer]` — Create assertion\n- `wh assertion revise <wref> --data <json> [--message] [--committer]` — Revise assertion\n- `wh assertion retract <wref> -m <message> [--reason] [--committer] [--expected-version]` — Retract assertion\n- `wh assertion history <wref> [--include-retracted]` — Assertion history\n\n### shape — Shape management\n- `wh shape list [--match] [--include-retracted]` — List all shapes\n- `wh shape view <name> [--include-retracted]` — Shape details\n- `wh shape revise <name> (--fields|--file)`\n- `wh shape create <name> (--fields|--file)`\n- `wh shape retract <name> -m <message> [--reason] [--expected-version]` — Retract shape\n- `wh shape history <name> [--include-retracted]` — Shape history\n- `wh shape rename <oldName> <newName>` — Rename shape\n\n### repo — Repository management\n- `wh repo create <org/name> [--display-name] [--description] [--visibility]` — Create repo\n- `wh repo list [org]` — List repos\n- `wh repo view [org/repo]` — Repo details\n\n### org — Organization management\n- `wh org create <name> [--display-name]` — Create a new organization\n- `wh org view <name>` — View organization details (alias: info)\n- `wh org list` — List all organizations\n\n### sub — Subscription management\n- `wh sub create <name> [flags]` — Create a subscription\n- `wh sub view <name>` — View subscription details\n- `wh sub list` — List all subscriptions\n- `wh sub log <name>` — Tail subscription delivery feed\n- `wh sub attempts <runId>` — Show attempt history for a run\n- `wh sub pause <name>` — Pause a subscription\n- `wh sub resume <name>` — Resume a paused subscription\n- `wh sub bind <name> [--credentials]` — Bind a credential set to a subscription for webhook auth\n- `wh sub unbind <name>` — Remove credential binding from a subscription\n- `wh sub delete <name>` — Retire; name reserved\n\n### notifications — Action notification listing\n- `wh notifications [--limit] [--since]` — List repo-scoped action notifications\n\n### credential — Credential set management\n- `wh credential create <name> [--repo org/repo | --org org] [--scope] [--description]` — Create an empty credential set\n- `wh credential list [--repo org/repo | --org org]` — List credential sets accessible from a repo or org\n- `wh credential view <name> [--repo org/repo | --org org]` — View a credential set (key names only, no values)\n- `wh credential delete <name> [--repo org/repo | --org org]` — Delete a credential set and its Vault object\n- `wh credential set <setName> [<keyName>] [--repo org/repo | --org org] [--value]` — Set credential key(s). With `<keyName>`: single-key form (reads value from `--value` or stdin). Without `<keyName>`: batch form (reads JSON object from stdin, e.g. `{\"KEY\":\"val\"}`)\n- `wh credential unset <setName> <keyName> [--repo org/repo | --org org]` — Remove a key from a credential set\n- `wh credential audit <setName> [--repo org/repo | --org org]` — View audit log for a credential set\n- `wh credential revoke <setName> [--repo org/repo | --org org] [--reason]` — Revoke a credential set (blocks new binds and stops bound webhook deliveries)\n\n### component — Component management\n- `wh component validate <path>` — Validate package\n- `wh component install <org/name>` — Install a registered component\n- `wh component register <name> --org <org> --manifest <path> [flags]` — Register component identity\n- `wh component unregister <org/name>` — Remove a registered component identity\n- `wh component registry list --org <org>` — List registered components\n- `wh component registry view <org/name>` — View a registered component\n- `wh component registry update <org/name> [flags]` — Update a registered component\n- `wh component list` — List installed components\n- `wh component update <org/name>` — Update installed component\n- `wh component view <org/name>` — Show component details (alias: show)\n- `wh component doctor <org/name>` — Run component health checks\n- `wh component teardown <org/name>` — Pause component subscriptions\n\n### Getting More Info\n- `wh help` — help overview\n- `wh <domain>` — domain verbs\n- `wh <domain> <verb> --help` — verb flags and examples\n- `wh help --format json` — `CliSpecV2` (`schemaVersion: 2`): global/contextual/root tables and command overrides\n\n## Common Workflows\n\n**Explore a repo:**\n```bash\nwh thing list --repo org/repo # see all things in HEAD\nwh thing view Shape/name --repo org/repo # inspect a specific thing\nwh thing history Shape/name --repo org/repo # inspect version history\nwh thing about Shape/name # assertions about thing/shape\n```\n\n**Create an assertion** (most common write):\n```bash\n# --about takes an untyped target wref: Shape or Shape/name.\nwh assertion create --shape MyShape --about TargetShape/target-name \\\n --name my-assertion --data '{\"field_a\":1,\"field_b\":\"value\"}' --repo org/repo\n# Output includes per-operation status; relay failures when present.\n```\n\n**Create via write entrypoint** (alternative, supports batches and streams):\n```bash\nwh commit submit --add my-item --shape MyShape --kind assertion \\\n --about TargetShape/target-name --data '{\"field_a\":1}' --repo org/repo\n```\n\n**Batch write via file** (generate template → edit → submit):\n```bash\nwh shape template Hypothesis Evidence -o ops.json # add --kind assertion --about TargetShape/name for assertions\n# edit ops.json — fill FILL_IN placeholders\nwh commit submit --file ops.json -m \"batch update\" # submit all operations (bare `wh commit` is equivalent)\n# --file format: docs.warmhub.ai/cli-reference/commit-operations\n```\n\n**Bulk write (JSONL stream, >1k ops)** — one chunked stream beats per-record commits (~60× faster):\n```bash\nwh shape template MyShape -o ops.jsonl # one op per line (.jsonl)\nID=\"bulk-$(date +%s)\" # caller id for chunk correlation\nwh commit submit --file ops.jsonl --stream-id \"$ID\" --chunk-size 5000 \\\n --skip-existing --progress -m \"bulk ingest\" --repo org/repo\n# --chunk-size: ops per append chunk (default 1000, max 10000); chunk≈1 is ~60× slower\n# --skip-existing: skips already-written add ops (drops per-row read-before-write)\n# --stream-id identifies the submission but provides no receipt or resume.\n# After an outcome-unknown append, stop writes and reconcile attempted + unsent\n# work from a later verified checkpoint; never blindly replay revise/retract.\n```\n\n**Create collections:**\n```bash\nwh commit submit --type arc --name route --members Location/a,Location/b --repo org/repo\nwh assertion create --shape Supports --name route-support --about Arc/route --data '{\"confidence\":0.8}' --repo org/repo\n```\n\n**Modify data:**\n```bash\nwh thing revise Shape/name --data '{\"x\":5,\"y\":3}' -m \"update\" --repo org/repo\nwh thing retract Shape/old-item -m \"withdrawn\" --reason \"data feed contaminated\" --repo org/repo\n```\n\n**Query and filter:**\n```bash\nwh thing query --shape MyShape # by shape\nwh thing query --kind assertion --about Shape/name # by kind + target\nwh thing history Shape/name --limit 10 # version history\n```\n\n## Built-in Content shape\n\nWarmHub repos expose three well-known content wrefs:\n- `Content/Readme` — stored markdown for humans\n- `Content/Agents` — stored markdown guidance for AI agents\n- `Content/LlmsTxt` — synthesized per-request sitemap (read-only)\n\nFetch via `wh repo content get --kind readme|agents|llms-txt`,\n`client.repo.getReadme/getAgents/getLlmsTxt`, MCP `warmhub_repo_content_get`,\nor raw HTTP `GET /{org}/{repo}/readme.md|agents.md|llms.txt`.\nSee `wh repo describe` → `additionalInformation` for the discovery field.\n\n## Query Discipline\n- Plan the repo, shapes, and wrefs you need before the first query.\n- Gather the needed facts from one repo before switching to another.\n- Do the queries first, then write one complete answer.\n\n## Agent Tips\n- **Always run commands for live data** — this context describes the CLI, not repo contents\n- **Before writing, discover wrefs** — run `wh thing list` or `wh shape list`\n- **Shape field types**: `string`, `number`, `boolean`, `wref`, arrays, optionals, nested objects\n- **Write commands return per-operation results** — relay failures and affected wrefs to the user\n- **Pass data inline** with `--data '{...}'` — do NOT create temp files\n- Add `--json` to any command for machine-readable JSON output\n- **Aliases teach canonical commands** — executing aliases emit a status hint; misleading lifecycle aliases reject and point to `retract`\n- Writes go through `wh commit submit` (or bare `wh commit`) or wrappers (`create`, `revise`, `retract`, `assertion create`). `retract` irreversibly withdraws an identity and creates a history entry.\n- Use `wh doctor` to check environment health\n";
59887
+ var prime_content_default = "# WarmHub CLI Context\n> **Context Recovery**: Run `wh prime` after compaction or new session\n\n## Environment\n{{REPO_LINE}}\n\n## Core Concepts\n- **Thing**: A named entity versioned by writes. **Assertion**: A thing that makes a shape-validated claim about another thing.\n- **Shape**: A thing defining data structure; every other thing has one. **Write**: One or more add/revise/retract operations with per-operation results.\n- **wref**: A reference to a thing. Local: `Player` (the shape) or `Player/alice` (a thing with that shape). Cross-repo: `wh:org/repo/Shape` or `wh:org/repo/Shape/name`.\n\n## Versioned Wrefs\n- `Shape` addresses the shape itself; `Shape/name` addresses a thing with that shape. `@vN` pins either.\n- Floating write refs to retracted targets fail; existing pinned versions remain valid.\n- Rename invalidates old spellings, including `@vN`; the new name resolves history.\n- Untyped wrefs accept any thing. `wref<T>` requires the target's shape to be `T`; a shape has no shape, so never satisfies it. `wref?` coalesces only `thing_absent`, never a missing shape.\n\n## Key Workflows\n\n**Write data** (discover shapes → scaffold ops → submit):\n```bash\nwh shape list --repo org/repo # list available shapes\nwh shape view ShapeName --repo org/repo # inspect fields\nwh shape template ShapeName -o ops.json --repo org/repo # scaffold write ops (supports --kind assertion)\n# edit ops.json — fill FILL_IN placeholders — then:\nwh commit submit --file ops.json -m \"msg\" --repo org/repo # submit operations (bare `wh commit` also works)\n# or single assertion (no file needed):\nwh assertion create --shape ShapeName --about Target/name --name my-assertion --data '{\"field\":1}' --repo org/repo\n# Relay failed operation details when present. Never hand-guess ops JSON — use `wh shape template <Shape>`.\n```\n\n**Read data:**\n```bash\nwh thing list --repo org/repo # all things at HEAD\nwh thing view Shape/name --repo org/repo # inspect a thing\nwh thing query --shape MyShape --repo org/repo # find things by shape\nwh thing about Shape --repo org/repo # assertions about a shape\nwh assertion list --repo org/repo # all assertions at HEAD\nwh thing history Shape/name --repo org/repo # version history\n\n# Batch read — wh thing view is variadic (max 500 wrefs/call):\nwh thing view Player/alice Player/bob # variadic positionals\nwh thing view --file wrefs.txt --json # one wref per line\ncat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped* requested wref\n```\n\n## Wref Quick Reference\n\nWrites use explicit names and wrefs. Untyped fields, collection members,\nassertion `about`, and committers accept any thing. Create a deterministic\ntarget before referencing it in the same commit.\n\n## Command Reference\n\n**Global flags**: `--repo`, `--format`, `--json`, `--live`\n### thing — Things\n- `wh thing list [--shape] [--kind] [--match] [--include-retracted]` — Current HEAD state\n- `wh thing view [<wref>...] [--file <path>] [--version] [--depth] [--include-retracted] [--data-mode auto|full]` — Thing details. Variadic (max 500). `--version` implies `--include-retracted`. Batch JSON returns `{ requested, items, missing }`; jsonl emits one row per deduped requested wref. Large Set/List bodies summarize by default; use `--data-mode full` for canonical collection JSON.\n- `wh thing history [wref] [--shape] [--about] [--include-retracted]` — Version history\n- `wh thing resolve <wref>` — Resolve a wref to its canonical thing identity\n- `wh thing create <name|Shape/name> (--data|--file) [--shape]` — Create\n- `wh thing revise <name> [--data] [--message] [--committer] [--expected-version]` — Revise (CONFLICT if HEAD≠n)\n- `wh thing retract <wref> -m <message> [--reason] [--kind] [--expected-version]` — Retract\n- `wh thing query [--shape] [--kind] [--about] [--match]` — Query by filters\n- `wh thing search <query> [--shape] [--kind] [--about] [--mode]` — Search text\n- `wh thing rename <Shape/oldName> <newName>` — Rename\n- `wh thing refs <wref> [--inbound] [--outbound] [--field]` — Show field references; use `wh thing about` for assertions about the target thing\n- `wh thing about <wref> [--shape] [--match] [--depth] [--resolve-collections] [--role from|to|ends] [--limit] [--include-retracted]` — Show assertions about the target identity; `--resolve-collections` expands bare/@HEAD/@ALL members, `--role` filters direction; not pinned @vN\n\n- `wh view evaluate VIEW [--limit N] [--cursor TOK] [--all]`\n### commit — Write operations\n- `wh commit submit [--ops|--file|--add|--revise|--retract] [--kind] [--data] [--reason] [--expected-version] [--chunk-size] [--skip-existing] [--progress] [--stream-id]` — Submit operations (bare `wh commit` is equivalent). Use `--file ops.jsonl --stream-id <id> --chunk-size 5000 --skip-existing` for bulk ingest.\n- `wh shape template <shape> [shape2 ...] [--kind] [--operation add|revise|retract] [-o file]` — Generate sample ops\n\n### assertion — Assertion operations\n- `wh assertion list [--about wref] [--shape] [--match] [--include-retracted]` — Browse assertions\n- `wh assertion view <wref> [--version] [--include-retracted]` — Assertion details\n- `wh assertion create --shape <s> --name <n> --about <wref> [--data] [-m] [--committer]` — Create assertion\n- `wh assertion revise <wref> --data <json> [--message] [--committer]` — Revise assertion\n- `wh assertion retract <wref> -m <message> [--reason] [--committer] [--expected-version]` — Retract assertion\n- `wh assertion history <wref> [--include-retracted]` — Assertion history\n\n### shape — Shape management\n- `wh shape list [--match] [--include-retracted]` — List all shapes\n- `wh shape view <name> [--include-retracted]` — Shape details\n- `wh shape revise <name> (--fields|--file)`\n- `wh shape create <name> (--fields|--file)`\n- `wh shape retract <name> -m <message> [--reason] [--expected-version]` — Retract shape\n- `wh shape history <name> [--include-retracted]` — Shape history\n- `wh shape rename <oldName> <newName>` — Rename shape\n\n### repo — Repository management\n- `wh repo create <org/name> [--display-name] [--description] [--visibility]` — Create repo\n- `wh repo list [org]` — List repos\n- `wh repo view [org/repo]` — Repo details\n\n### org — Organization management\n- `wh org create <name> [--display-name]` — Create a new organization\n- `wh org view <name>` — View organization details (alias: info)\n- `wh org list` — List all organizations\n\n### sub — Subscription management\n- `wh sub create <name> [flags]` — Create a subscription\n- `wh sub view <name>` — View subscription details\n- `wh sub list` — List all subscriptions\n- `wh sub log <name>` — Tail subscription delivery feed\n- `wh sub attempts <runId>` — Show attempt history for a run\n- `wh sub pause <name>` — Pause a subscription\n- `wh sub resume <name>` — Resume a paused subscription\n- `wh sub bind <name> [--credentials]` — Bind a credential set to a subscription for webhook auth\n- `wh sub unbind <name>` — Remove credential binding from a subscription\n- `wh sub delete <name>` — Retire; name reserved\n\n### notifications — Action notification listing\n- `wh notifications [--limit] [--since]` — List repo-scoped action notifications\n\n### credential — Credential set management\n- `wh credential create <name> [--repo org/repo | --org org] [--scope] [--description]` — Create an empty credential set\n- `wh credential list [--repo org/repo | --org org]` — List credential sets accessible from a repo or org\n- `wh credential view <name> [--repo org/repo | --org org]` — View a credential set (key names only, no values)\n- `wh credential delete <name> [--repo org/repo | --org org]` — Delete a credential set and its Vault object\n- `wh credential set <setName> [<keyName>] [--repo org/repo | --org org] [--value]` — Set credential key(s). With `<keyName>`: single-key form (reads value from `--value` or stdin). Without `<keyName>`: batch form (reads JSON object from stdin, e.g. `{\"KEY\":\"val\"}`)\n- `wh credential unset <setName> <keyName> [--repo org/repo | --org org]` — Remove a key from a credential set\n- `wh credential audit <setName> [--repo org/repo | --org org]` — View audit log for a credential set\n- `wh credential revoke <setName> [--repo org/repo | --org org] [--reason]` — Revoke a credential set (blocks new binds and stops bound webhook deliveries)\n\n### component — Component management\n- `wh component validate <path>` — Validate package\n- `wh component install <org/name>` — Install a registered component\n- `wh component register <name> --org <org> --manifest <path> [flags]` — Register component identity\n- `wh component unregister <org/name>` — Remove a registered component identity\n- `wh component registry list --org <org>` — List registered components\n- `wh component registry view <org/name>` — View a registered component\n- `wh component registry update <org/name> [flags]` — Update a registered component\n- `wh component list` — List installed components\n- `wh component update <org/name>` — Update installed component\n- `wh component view <org/name>` — Show component details (alias: show)\n- `wh component doctor <org/name>` — Run component health checks\n- `wh component teardown <org/name>` — Pause component subscriptions\n\n### Getting More Info\n- `wh help` — help overview\n- `wh <domain>` — domain verbs\n- `wh <domain> <verb> --help` — verb flags and examples\n- `wh help --format json` — `CliSpecV2` (`schemaVersion: 2`): global/contextual/root tables and command overrides\n\n## Common Workflows\n\n**Explore a repo:**\n```bash\nwh thing list --repo org/repo # see all things in HEAD\nwh thing view Shape/name --repo org/repo # inspect a specific thing\nwh thing history Shape/name --repo org/repo # inspect version history\nwh thing about Shape/name # assertions about thing/shape\n```\n\n**Create an assertion** (most common write):\n```bash\n# --about takes an untyped target wref: Shape or Shape/name.\nwh assertion create --shape MyShape --about TargetShape/target-name \\\n --name my-assertion --data '{\"field_a\":1,\"field_b\":\"value\"}' --repo org/repo\n# Output includes per-operation status; relay failures when present.\n```\n\n**Create via write entrypoint** (alternative, supports batches and streams):\n```bash\nwh commit submit --add my-item --shape MyShape --kind assertion \\\n --about TargetShape/target-name --data '{\"field_a\":1}' --repo org/repo\n```\n\n**Batch write via file** (generate template → edit → submit):\n```bash\nwh shape template Hypothesis Evidence -o ops.json # add --kind assertion --about TargetShape/name for assertions\n# edit ops.json — fill FILL_IN placeholders\nwh commit submit --file ops.json -m \"batch update\" # submit all operations (bare `wh commit` is equivalent)\n# --file format: docs.warmhub.ai/cli-reference/commit-operations\n```\n\n**Bulk write (JSONL stream, >1k ops)** — one chunked stream beats per-record commits (~60× faster):\n```bash\nwh shape template MyShape -o ops.jsonl # one op per line (.jsonl)\nID=\"bulk-$(date +%s)\" # caller id for chunk correlation\nwh commit submit --file ops.jsonl --stream-id \"$ID\" --chunk-size 5000 \\\n --skip-existing --progress -m \"bulk ingest\" --repo org/repo\n# --chunk-size: ops per append chunk (default 1000, max 10000); chunk≈1 is ~60× slower\n# --skip-existing: skips already-written add ops (drops per-row read-before-write)\n# --stream-id identifies the submission but provides no receipt or resume.\n# After an outcome-unknown append, stop writes and reconcile attempted + unsent\n# work from a later verified checkpoint; never blindly replay revise/retract.\n```\n\n**Create collections:**\n```bash\nwh commit submit --type arc --name route --members Location/a,Location/b --repo org/repo\nwh assertion create --shape Supports --name route-support --about Arc/route --data '{\"confidence\":0.8}' --repo org/repo\n```\n\n**Modify data:**\n```bash\nwh thing revise Shape/name --data '{\"x\":5,\"y\":3}' -m \"update\" --repo org/repo\nwh thing retract Shape/old-item -m \"withdrawn\" --reason \"data feed contaminated\" --repo org/repo\n```\n\n**Query and filter:**\n```bash\nwh thing query --shape MyShape # by shape\nwh thing query --kind assertion --about Shape/name # by kind + target\nwh thing history Shape/name --limit 10 # version history\n```\n\n## Built-in Content shape\n\nWarmHub repos expose three well-known content wrefs:\n- `Content/Readme` — stored markdown for humans\n- `Content/Agents` — stored markdown guidance for AI agents\n- `Content/LlmsTxt` — synthesized per-request sitemap (read-only)\n\nFetch via `wh repo content get --kind readme|agents|llms-txt`,\n`client.repo.getReadme/getAgents/getLlmsTxt`, MCP `warmhub_repo_content_get`,\nor raw HTTP `GET /{org}/{repo}/readme.md|agents.md|llms.txt`.\nSee `wh repo describe` → `additionalInformation` for the discovery field.\n\n## Query Discipline\n- Plan the repo, shapes, and wrefs you need before the first query.\n- Gather the needed facts from one repo before switching to another.\n- Do the queries first, then write one complete answer.\n\n## Agent Tips\n- **Always run commands for live data** — this context describes the CLI, not repo contents\n- **Before writing, discover wrefs** — run `wh thing list` or `wh shape list`\n- **Shape field types**: `string`, `number`, `boolean`, `wref`, arrays, optionals, nested objects\n- **Write commands return per-operation results** — relay failures and affected wrefs to the user\n- **Pass data inline** with `--data '{...}'` — do NOT create temp files\n- Add `--json` to any command for machine-readable JSON output\n- **Aliases teach canonical commands** — executing aliases emit a status hint; misleading lifecycle aliases reject and point to `retract`\n- Writes go through `wh commit submit` (or bare `wh commit`) or wrappers (`create`, `revise`, `retract`, `assertion create`). `retract` irreversibly withdraws an identity and creates a history entry.\n- Use `wh doctor` to check environment health\n";
59542
59888
 
59543
59889
  // ../../packages/warmhub-cli/src/domains/prime.ts
59544
59890
  function buildMarkdown(config2) {
@@ -60819,13 +61165,13 @@ function printCheckpoint(ctx, result) {
60819
61165
  ctx.out(`Failure: ${result.failureCode}`);
60820
61166
  });
60821
61167
  }
60822
- async function waitForCompletion(ctx, org, repo, initial) {
61168
+ async function waitForCompletion(ctx, org, repo2, initial) {
60823
61169
  let result = initial;
60824
61170
  let delayMs = 200;
60825
61171
  while (result.state === "queued" || result.state === "running") {
60826
61172
  ctx.status(`Checkpoint ${result.checkpointId} is ${result.state}; waiting…`);
60827
61173
  await delay2(delayMs, ctx.signal);
60828
- result = await checkpointClient(ctx).status(org, repo, {
61174
+ result = await checkpointClient(ctx).status(org, repo2, {
60829
61175
  checkpointId: result.checkpointId
60830
61176
  });
60831
61177
  delayMs = Math.min(delayMs * 2, 5000);
@@ -60850,27 +61196,27 @@ function delay2(ms, signal) {
60850
61196
  });
60851
61197
  }
60852
61198
  var handleGenerate = async (ctx, { args, flags }) => {
60853
- const { org, repo } = repoFor(ctx, args);
60854
- const result = await checkpointClient(ctx).generate(org, repo, {
61199
+ const { org, repo: repo2 } = repoFor(ctx, args);
61200
+ const result = await checkpointClient(ctx).generate(org, repo2, {
60855
61201
  atLeastRepoSeq: requireSequence(flags["at-least-repo-seq"], "--at-least-repo-seq")
60856
61202
  });
60857
- printCheckpoint(ctx, flags.wait ? await waitForCompletion(ctx, org, repo, result) : result);
61203
+ printCheckpoint(ctx, flags.wait ? await waitForCompletion(ctx, org, repo2, result) : result);
60858
61204
  };
60859
61205
  var handleStatus2 = async (ctx, { args, flags }) => {
60860
- const { org, repo } = repoFor(ctx, args);
60861
- printCheckpoint(ctx, await checkpointClient(ctx).status(org, repo, selectCheckpoint(flags)));
61206
+ const { org, repo: repo2 } = repoFor(ctx, args);
61207
+ printCheckpoint(ctx, await checkpointClient(ctx).status(org, repo2, selectCheckpoint(flags)));
60862
61208
  };
60863
61209
  var handleLatest = async (ctx, { args }) => {
60864
- const { org, repo } = repoFor(ctx, args);
60865
- printCheckpoint(ctx, await checkpointClient(ctx).latest(org, repo));
61210
+ const { org, repo: repo2 } = repoFor(ctx, args);
61211
+ printCheckpoint(ctx, await checkpointClient(ctx).latest(org, repo2));
60866
61212
  };
60867
61213
  var handleRetry = async (ctx, { args, flags }) => {
60868
61214
  if (!flags.checkpoint) {
60869
61215
  usageError("--checkpoint is required for retry.", `wh repo checkpoint retry acme/widgets --checkpoint ${CHECKPOINT_ID_EXAMPLE}`);
60870
61216
  }
60871
- const { org, repo } = repoFor(ctx, args);
60872
- const result = await checkpointClient(ctx).retry(org, repo, flags.checkpoint);
60873
- printCheckpoint(ctx, flags.wait ? await waitForCompletion(ctx, org, repo, result) : result);
61217
+ const { org, repo: repo2 } = repoFor(ctx, args);
61218
+ const result = await checkpointClient(ctx).retry(org, repo2, flags.checkpoint);
61219
+ printCheckpoint(ctx, flags.wait ? await waitForCompletion(ctx, org, repo2, result) : result);
60874
61220
  };
60875
61221
  var handleDownload = async (ctx, { args, flags }) => {
60876
61222
  if (!flags.output) {
@@ -60879,8 +61225,8 @@ var handleDownload = async (ctx, { args, flags }) => {
60879
61225
  if (flags.output === "-" && ctx.format !== "pretty") {
60880
61226
  throw new CliError(2 /* UserInput */, "USER_INPUT", "Binary stdout requires --format pretty; JSON and JSONL cannot carry artifact bytes.");
60881
61227
  }
60882
- const { org, repo } = repoFor(ctx, args);
60883
- const access = await checkpointClient(ctx).getAccess(org, repo, {
61228
+ const { org, repo: repo2 } = repoFor(ctx, args);
61229
+ const access = await checkpointClient(ctx).getAccess(org, repo2, {
60884
61230
  checkpoint: selectArtifactCheckpoint(flags, CHECKPOINT_DOWNLOAD_EXAMPLE),
60885
61231
  artifact: selectArtifact(flags, CHECKPOINT_DOWNLOAD_EXAMPLE)
60886
61232
  });
@@ -60895,8 +61241,8 @@ var handleDownload = async (ctx, { args, flags }) => {
60895
61241
  ctx.status(`Downloaded checkpoint artifact to ${flags.output}`);
60896
61242
  };
60897
61243
  var handleAccess = async (ctx, { args, flags }) => {
60898
- const { org, repo } = repoFor(ctx, args);
60899
- printAccess(ctx, await checkpointClient(ctx).getAccess(org, repo, {
61244
+ const { org, repo: repo2 } = repoFor(ctx, args);
61245
+ printAccess(ctx, await checkpointClient(ctx).getAccess(org, repo2, {
60900
61246
  checkpoint: selectArtifactCheckpoint(flags, CHECKPOINT_ACCESS_EXAMPLE),
60901
61247
  artifact: selectArtifact(flags, CHECKPOINT_ACCESS_EXAMPLE)
60902
61248
  }));
@@ -61104,24 +61450,22 @@ function parseExplicitOrgRepoArg(ref, usage, example) {
61104
61450
  if (!ref?.includes("/")) {
61105
61451
  usageError(usage, example);
61106
61452
  }
61107
- const parts = ref.split("/");
61108
- if (parts.length !== 2 || !parts[0] || !parts[1]) {
61453
+ const parsed = parseRepoSlug(ref);
61454
+ if (!parsed) {
61109
61455
  usageError(`Invalid repo format "${ref}". Expected "org/repo" with no extra slashes or empty segments.`, example);
61110
61456
  }
61111
- const [orgName, repoName] = parts;
61112
- return { orgName, repoName };
61457
+ return { orgName: parsed.org, repoName: parsed.repo };
61113
61458
  }
61114
61459
  function resolveOrgRepoArg(ref, orgFlag) {
61115
61460
  if (ref?.includes("/")) {
61116
- const parts = ref.split("/");
61117
- if (parts.length !== 2 || !parts[0] || !parts[1]) {
61461
+ const parsed = parseRepoSlug(ref);
61462
+ if (!parsed) {
61118
61463
  usageError(`Invalid repo format '${ref}'. Expected '<org>/<name>' with no extra slashes and no empty parts.`, "wh repo create myorg/myrepo");
61119
61464
  }
61120
- const [orgName, repoName] = parts;
61121
- if (orgFlag && orgFlag !== orgName) {
61122
- usageError(`Conflicting org: positional '${orgName}' vs --org '${orgFlag}'`, "wh repo create myorg/myrepo");
61465
+ if (orgFlag && orgFlag !== parsed.org) {
61466
+ usageError(`Conflicting org: positional '${parsed.org}' vs --org '${orgFlag}'`, "wh repo create myorg/myrepo");
61123
61467
  }
61124
- return { orgName, repoName };
61468
+ return { orgName: parsed.org, repoName: parsed.repo };
61125
61469
  }
61126
61470
  if (ref && orgFlag) {
61127
61471
  return {
@@ -61137,10 +61481,11 @@ function nameStrings(items) {
61137
61481
  }
61138
61482
 
61139
61483
  // ../../packages/warmhub-cli/src/domains/repo/content.ts
61140
- var READ_ONLY_KINDS = new Set(["llms-txt"]);
61141
61484
  var CONTENT_KINDS = ["readme", "agents", "llms-txt"];
61485
+ var CONTENT_KIND_LIST = CONTENT_KINDS.join(", ");
61486
+ var READ_ONLY_KINDS = new Set(["llms-txt"]);
61142
61487
  var kindFlagDef = flag.string({
61143
- description: "Which content kind to operate on (readme, agents, llms-txt)"
61488
+ description: `Which content kind to operate on (${CONTENT_KIND_LIST})`
61144
61489
  });
61145
61490
  var contentGetFlags = {
61146
61491
  kind: kindFlagDef
@@ -61160,19 +61505,20 @@ var promptFlags = {
61160
61505
  };
61161
61506
  function requireKind(kind) {
61162
61507
  if (!kind) {
61163
- throw new CliError(2 /* UserInput */, "USER_INPUT", "--kind is required. Choose one of: readme, agents, llms-txt", undefined, "Example: wh repo content get myorg/myrepo --kind readme");
61508
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `--kind is required. Choose one of: ${CONTENT_KIND_LIST}`, undefined, "Example: wh repo content get myorg/myrepo --kind readme");
61164
61509
  }
61165
- if (!CONTENT_KINDS.includes(kind)) {
61166
- throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid --kind '${kind}'. Choose one of: readme, agents, llms-txt`);
61510
+ const parsed = CONTENT_KINDS.find((candidate) => candidate === kind);
61511
+ if (!parsed) {
61512
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid --kind '${kind}'. Choose one of: ${CONTENT_KIND_LIST}`);
61167
61513
  }
61168
- return kind;
61514
+ return parsed;
61169
61515
  }
61170
61516
  var handleContentGet = async (ctx, { args, flags }) => {
61171
61517
  const kind = requireKind(flags.kind);
61172
- const { org, repo } = parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
61518
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
61173
61519
  switch (kind) {
61174
61520
  case "readme": {
61175
- const result = await ctx.client.repo.getReadme(org, repo);
61521
+ const result = await ctx.client.repo.getReadme(org, repo2);
61176
61522
  const content = result?.data?.content;
61177
61523
  const text = typeof content === "string" ? content : "";
61178
61524
  writeOutput(ctx, result, () => {
@@ -61181,7 +61527,7 @@ var handleContentGet = async (ctx, { args, flags }) => {
61181
61527
  break;
61182
61528
  }
61183
61529
  case "agents": {
61184
- const result = await ctx.client.repo.getAgents(org, repo);
61530
+ const result = await ctx.client.repo.getAgents(org, repo2);
61185
61531
  const content = result?.data?.content;
61186
61532
  const text = typeof content === "string" ? content : "";
61187
61533
  writeOutput(ctx, result, () => {
@@ -61190,7 +61536,7 @@ var handleContentGet = async (ctx, { args, flags }) => {
61190
61536
  break;
61191
61537
  }
61192
61538
  case "llms-txt": {
61193
- const result = await ctx.client.repo.getLlmsTxt(org, repo);
61539
+ const result = await ctx.client.repo.getLlmsTxt(org, repo2);
61194
61540
  writeOutput(ctx, result, () => {
61195
61541
  ctx.out(result.data.content);
61196
61542
  });
@@ -61203,26 +61549,26 @@ var handleContentSet = async (ctx, { args, flags }) => {
61203
61549
  if (READ_ONLY_KINDS.has(kind)) {
61204
61550
  throw new CliError(2 /* UserInput */, "USER_INPUT", `--kind ${kind} is read-only; \`set\` is rejected.`, undefined, `Use \`wh repo content get [org/repo] --kind ${kind}\` (or set --repo)`);
61205
61551
  }
61206
- const { org, repo } = parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
61552
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
61207
61553
  const inputContent = await readContentInput(flags.file, flags.content, ctx.stdin);
61208
61554
  const eventRequestId = flags["event-request-id"] ?? createOperationEventRequestId();
61209
61555
  ctx.status(`Operation event request: ${eventRequestId}`);
61210
61556
  switch (kind) {
61211
61557
  case "readme": {
61212
- const result = await ctx.client.repo.setReadme(org, repo, inputContent, {
61558
+ const result = await ctx.client.repo.setReadme(org, repo2, inputContent, {
61213
61559
  eventRequestId
61214
61560
  });
61215
61561
  writeOutput(ctx, result, () => {
61216
- ctx.status(`Content/Readme updated in ${org}/${repo}`);
61562
+ ctx.status(`Content/Readme updated in ${org}/${repo2}`);
61217
61563
  });
61218
61564
  break;
61219
61565
  }
61220
61566
  case "agents": {
61221
- const result = await ctx.client.repo.setAgents(org, repo, inputContent, {
61567
+ const result = await ctx.client.repo.setAgents(org, repo2, inputContent, {
61222
61568
  eventRequestId
61223
61569
  });
61224
61570
  writeOutput(ctx, result, () => {
61225
- ctx.status(`Content/Agents updated in ${org}/${repo}`);
61571
+ ctx.status(`Content/Agents updated in ${org}/${repo2}`);
61226
61572
  });
61227
61573
  break;
61228
61574
  }
@@ -61236,24 +61582,24 @@ var handleContentPrompt = async (ctx, { args, flags }) => {
61236
61582
  throw new CliError(2 /* UserInput */, "USER_INPUT", `--kind ${kind} is read-only; \`prompt\` is rejected.`, undefined, `Use \`wh repo content get [org/repo] --kind ${kind}\` (or set --repo)`);
61237
61583
  }
61238
61584
  const promptKind = kind;
61239
- const { org, repo } = parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
61585
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
61240
61586
  const [repoInfo, shapesPage, stats, thingsPage] = await Promise.all([
61241
- ctx.client.repo.get(org, repo),
61242
- ctx.client.shape.list(org, repo),
61243
- ctx.client.repo.getStats(org, repo),
61244
- ctx.client.thing.query(org, repo, { limit: 30 })
61587
+ ctx.client.repo.get(org, repo2),
61588
+ ctx.client.shape.list(org, repo2),
61589
+ ctx.client.repo.getStats(org, repo2),
61590
+ ctx.client.thing.query(org, repo2, { limit: 30 })
61245
61591
  ]);
61246
61592
  const { prompt, saveCommand } = buildContentPrompt({
61247
61593
  kind: promptKind,
61248
61594
  org,
61249
- repo,
61595
+ repo: repo2,
61250
61596
  description: repoInfo.description ?? null,
61251
61597
  byKind: stats.byKind,
61252
61598
  byShape: stats.byShape,
61253
61599
  shapeNames: nameStrings(shapesPage.items),
61254
61600
  sampleThingNames: nameStrings(thingsPage.items)
61255
61601
  });
61256
- writeOutput(ctx, { kind: promptKind, org, repo, prompt, saveCommand }, () => {
61602
+ writeOutput(ctx, { kind: promptKind, org, repo: repo2, prompt, saveCommand }, () => {
61257
61603
  ctx.out(prompt);
61258
61604
  });
61259
61605
  ctx.status(`Next: draft the content, then run:
@@ -61309,7 +61655,7 @@ var CONTENT_SUBDOMAIN = defineDomain({
61309
61655
  });
61310
61656
 
61311
61657
  // ../../packages/warmhub-cli/src/domains/repo/create.ts
61312
- var createFlags6 = {
61658
+ var createFlags7 = {
61313
61659
  "display-name": flag.string({
61314
61660
  description: "Display name for the repo"
61315
61661
  }),
@@ -61322,7 +61668,7 @@ var createFlags6 = {
61322
61668
  description: "Org name (tolerance fallback; prefer the `<org/name>` positional form)"
61323
61669
  })
61324
61670
  };
61325
- var handleCreate5 = async (ctx, { flags, args }) => {
61671
+ var handleCreate6 = async (ctx, { flags, args }) => {
61326
61672
  const ref = args[0];
61327
61673
  const orgFlag = flags.org;
61328
61674
  const resolved = resolveOrgRepoArg(ref, orgFlag);
@@ -61426,7 +61772,7 @@ var repoListFlags = {
61426
61772
  };
61427
61773
  var DEFAULT_REPO_LIST_LIMIT = 50;
61428
61774
  var MAX_REPO_LIST_LIMIT = 200;
61429
- var handleList5 = async (ctx, { flags, args }) => {
61775
+ var handleList6 = async (ctx, { flags, args }) => {
61430
61776
  const orgName = args[0] ?? ctx.config.defaultOrg;
61431
61777
  if (!orgName) {
61432
61778
  usageError("Usage: wh repo list <org> (or set WARMHUB_ORG)", "wh repo list myorg");
@@ -61552,15 +61898,15 @@ var describeFlags = {
61552
61898
  };
61553
61899
  var handleDescribe = async (ctx, { args, flags }) => {
61554
61900
  const repoRef = args[0];
61555
- const { org, repo } = parseOrgRepo(repoRef, ctx.config);
61901
+ const { org, repo: repo2 } = parseOrgRepo(repoRef, ctx.config);
61556
61902
  const c = ctx.colors;
61557
61903
  const showIndexedFields = flags["indexed-fields"] === true;
61558
61904
  const [repoInfo, license, shapesPage, stats, indexedFields] = await Promise.all([
61559
- ctx.client.repo.get(org, repo),
61560
- ctx.client.repo.getLicense(org, repo),
61561
- ctx.client.shape.list(org, repo),
61562
- ctx.client.repo.getStats(org, repo),
61563
- showIndexedFields ? ctx.client.repo.index.describe(org, repo) : null
61905
+ ctx.client.repo.get(org, repo2),
61906
+ ctx.client.repo.getLicense(org, repo2),
61907
+ ctx.client.shape.list(org, repo2),
61908
+ ctx.client.repo.getStats(org, repo2),
61909
+ showIndexedFields ? ctx.client.repo.index.describe(org, repo2) : null
61564
61910
  ]);
61565
61911
  const shapes = shapesPage.items;
61566
61912
  const byShape = Object.fromEntries([
@@ -61578,7 +61924,7 @@ var handleDescribe = async (ctx, { args, flags }) => {
61578
61924
  } : null;
61579
61925
  const payload = {
61580
61926
  org,
61581
- repo,
61927
+ repo: repo2,
61582
61928
  description: repoInfo.description ?? null,
61583
61929
  license,
61584
61930
  counts: {
@@ -61600,7 +61946,7 @@ var handleDescribe = async (ctx, { args, flags }) => {
61600
61946
  ...indexedFieldsPublic ? { indexedFields: indexedFieldsPublic } : {}
61601
61947
  };
61602
61948
  writeOutput(ctx, payload, () => {
61603
- ctx.out(`${c.bold}${org}/${repo}${c.reset}`);
61949
+ ctx.out(`${c.bold}${org}/${repo2}${c.reset}`);
61604
61950
  if (repoInfo.description) {
61605
61951
  ctx.out(` ${escapeTerminalTextForDisplay(repoInfo.description)}`);
61606
61952
  }
@@ -61728,12 +62074,12 @@ var handleRepoSearch = async (ctx, { flags, args }) => {
61728
62074
  // ../../packages/warmhub-cli/src/domains/repo/view.ts
61729
62075
  var handleView6 = async (ctx, { args }) => {
61730
62076
  const repoRef = args[0];
61731
- const { org, repo } = parseOrgRepo(repoRef, ctx.config);
62077
+ const { org, repo: repo2 } = parseOrgRepo(repoRef, ctx.config);
61732
62078
  const c = ctx.colors;
61733
62079
  const [repoInfo, stats, configureStats] = await Promise.all([
61734
- ctx.client.repo.get(org, repo),
61735
- ctx.client.repo.getStats(org, repo),
61736
- ctx.client.repo.getConfigureStats(org, repo).catch((err) => {
62080
+ ctx.client.repo.get(org, repo2),
62081
+ ctx.client.repo.getStats(org, repo2),
62082
+ ctx.client.repo.getConfigureStats(org, repo2).catch((err) => {
61737
62083
  if (err instanceof WarmHubError && (err.kind === "FORBIDDEN" || err.kind === "UNAUTHENTICATED")) {
61738
62084
  return null;
61739
62085
  }
@@ -61741,7 +62087,7 @@ var handleView6 = async (ctx, { args }) => {
61741
62087
  })
61742
62088
  ]);
61743
62089
  writeOutput(ctx, { ...repoInfo, stats, configureStats }, () => {
61744
- ctx.out(`${c.bold}${org}/${repo}${c.reset}`);
62090
+ ctx.out(`${c.bold}${org}/${repo2}${c.reset}`);
61745
62091
  if (repoInfo.displayName && repoInfo.displayName !== repoInfo.name) {
61746
62092
  ctx.out(` ${escapeTerminalTextForDisplay(repoInfo.displayName)}`);
61747
62093
  }
@@ -61763,7 +62109,7 @@ var handleVisibility = async (ctx, { args }) => {
61763
62109
  if (!orgRepo || !newVisibility || !orgRepo.includes("/") || newVisibility !== "public" && newVisibility !== "private") {
61764
62110
  usageError("Usage: wh repo visibility <org/repo> <public|private>", "wh repo visibility myorg/myrepo public");
61765
62111
  }
61766
- const parsed = splitRepoSlug(orgRepo);
62112
+ const parsed = parseRepoSlug(orgRepo);
61767
62113
  if (!parsed) {
61768
62114
  usageError("Usage: wh repo visibility <org/repo> <public|private>", "wh repo visibility myorg/myrepo public");
61769
62115
  }
@@ -61785,14 +62131,14 @@ var REPO_DOMAIN = defineDomain({
61785
62131
  prime: true,
61786
62132
  summary: "Create a new repo",
61787
62133
  args: "<org/name>",
61788
- flags: createFlags6,
62134
+ flags: createFlags7,
61789
62135
  examples: [
61790
62136
  "wh repo create myorg/myrepo",
61791
62137
  'wh repo create myorg/myrepo -d "My repo"',
61792
62138
  'wh repo create myorg/myrepo --display-name "My Repo"',
61793
62139
  'wh repo create myorg/myrepo --visibility private -d "Private repo"'
61794
62140
  ],
61795
- handler: handleCreate5
62141
+ handler: handleCreate6
61796
62142
  },
61797
62143
  list: {
61798
62144
  prime: true,
@@ -61804,7 +62150,7 @@ var REPO_DOMAIN = defineDomain({
61804
62150
  "wh repo list myorg",
61805
62151
  "wh repo list myorg --include-archived"
61806
62152
  ],
61807
- handler: handleList5
62153
+ handler: handleList6
61808
62154
  },
61809
62155
  search: {
61810
62156
  prime: true,
@@ -61931,7 +62277,7 @@ var handleHistory3 = async (ctx, { flags, args }) => {
61931
62277
  if (!shapeName) {
61932
62278
  usageError("Usage: wh shape history <name>", "wh shape history Location");
61933
62279
  }
61934
- const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62280
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx), ctx.config);
61935
62281
  const limit = flags.limit;
61936
62282
  const cursor = flags.cursor;
61937
62283
  const all = flags.all;
@@ -61947,7 +62293,7 @@ var handleHistory3 = async (ctx, { flags, args }) => {
61947
62293
  if (ctx.liveMode) {
61948
62294
  await runLive({
61949
62295
  apiUrl: ctx.config.apiUrl,
61950
- poll: (c) => c.shape.history(org, repo, bareName, {
62296
+ poll: (c) => c.shape.history(org, repo2, bareName, {
61951
62297
  includeRetracted,
61952
62298
  limit: pageLimit,
61953
62299
  cursor
@@ -61962,6 +62308,7 @@ var handleHistory3 = async (ctx, { flags, args }) => {
61962
62308
  inactivityTimeoutMs: ctx.inactivityTimeoutMs,
61963
62309
  functionLogs: ctx.functionLogMode,
61964
62310
  profile: ctx.profile,
62311
+ clientFlags: ctx.clientFlags,
61965
62312
  signal: ctx.signal
61966
62313
  });
61967
62314
  return;
@@ -61971,7 +62318,7 @@ var handleHistory3 = async (ctx, { flags, args }) => {
61971
62318
  let thing;
61972
62319
  let nextCursor;
61973
62320
  do {
61974
- const page = await ctx.client.shape.history(org, repo, bareName, {
62321
+ const page = await ctx.client.shape.history(org, repo2, bareName, {
61975
62322
  includeRetracted,
61976
62323
  limit: pageLimit,
61977
62324
  cursor: next
@@ -61993,7 +62340,7 @@ var handleHistory3 = async (ctx, { flags, args }) => {
61993
62340
  };
61994
62341
 
61995
62342
  // ../../packages/warmhub-cli/src/domains/shape/list.ts
61996
- var listFlags4 = {
62343
+ var listFlags5 = {
61997
62344
  match: flag.string({ description: "Filter by name glob pattern" }),
61998
62345
  component: flag.string({
61999
62346
  description: "Filter to shapes owned by this component (Org/Name ref)"
@@ -62005,15 +62352,15 @@ var listFlags4 = {
62005
62352
  description: "Include retracted shapes"
62006
62353
  })
62007
62354
  };
62008
- var handleList6 = async (ctx, { flags }) => {
62009
- const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62355
+ var handleList7 = async (ctx, { flags }) => {
62356
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62010
62357
  const c = ctx.colors;
62011
62358
  const match = flags.match;
62012
62359
  const componentRef = flags.component;
62013
62360
  const excludeComponents = !!flags["exclude-components"];
62014
62361
  const includeRetracted = flags["include-retracted"];
62015
62362
  validateComponentFilters(componentRef, excludeComponents, "wh shape list --component acme/veritas", "wh shape list --exclude-components");
62016
- const result = await ctx.client.shape.list(org, repo, {
62363
+ const result = await ctx.client.shape.list(org, repo2, {
62017
62364
  match,
62018
62365
  componentRef,
62019
62366
  excludeComponents,
@@ -62025,7 +62372,7 @@ var handleList6 = async (ctx, { flags }) => {
62025
62372
  ctx.status(`${c.dim}No shapes registered${c.reset}`);
62026
62373
  return;
62027
62374
  }
62028
- ctx.out(`${c.bold}Shapes${c.reset} ${c.cyan}${org}/${repo}${c.reset}`);
62375
+ ctx.out(`${c.bold}Shapes${c.reset} ${c.cyan}${org}/${repo2}${c.reset}`);
62029
62376
  for (const item of items) {
62030
62377
  const shape = item;
62031
62378
  const name = shape.name;
@@ -62069,9 +62416,9 @@ var handleView7 = async (ctx, { flags, args }) => {
62069
62416
  if (!shapeName) {
62070
62417
  usageError("Usage: wh shape view <name>", "wh shape view location");
62071
62418
  }
62072
- const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62419
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62073
62420
  const c = ctx.colors;
62074
- const result = await ctx.client.shape.get(org, repo, shapeName, {
62421
+ const result = await ctx.client.shape.get(org, repo2, shapeName, {
62075
62422
  includeRetracted: flags["include-retracted"]
62076
62423
  });
62077
62424
  writeOutput(ctx, result, () => {
@@ -62108,7 +62455,7 @@ var handleView7 = async (ctx, { flags, args }) => {
62108
62455
  var fieldsFileFlag = flag.string({
62109
62456
  description: "read fields from a JSON object file (portable alternative to inline --fields)"
62110
62457
  });
62111
- var createFlags7 = {
62458
+ var createFlags8 = {
62112
62459
  "event-request-id": operationEventRequestIdFlag,
62113
62460
  fields: flag.string({ description: FIELDS_FLAG_DESCRIPTION }),
62114
62461
  file: fieldsFileFlag,
@@ -62131,9 +62478,8 @@ var renameFlags3 = {
62131
62478
  "event-request-id": operationEventRequestIdFlag
62132
62479
  };
62133
62480
  function shapeChangeFromReceipt(receipt) {
62134
- assertSingleOpSuccess(receipt);
62135
- const entry = receipt.operations[0];
62136
- if (!entry || entry.operation === "rename" || !("version" in entry) || typeof entry.version !== "number" || !("dataHash" in entry) || typeof entry.dataHash !== "string") {
62481
+ const entry = requireSingleOpSuccess(receipt);
62482
+ if (entry.operation === "rename" || !("version" in entry) || typeof entry.version !== "number" || !("dataHash" in entry) || typeof entry.dataHash !== "string") {
62137
62483
  throw new Error("Shape mutation returned no version-bearing operation");
62138
62484
  }
62139
62485
  return {
@@ -62191,7 +62537,7 @@ var retractFlags3 = {
62191
62537
  description: "Committer wref (shape or shaped thing; e.g. Agent/bot-1)"
62192
62538
  })
62193
62539
  };
62194
- var handleCreate6 = async (ctx, { flags, args }) => {
62540
+ var handleCreate7 = async (ctx, { flags, args }) => {
62195
62541
  const shapeName = args[0];
62196
62542
  if (!shapeName) {
62197
62543
  usageError("Usage: wh shape create <name> (--fields '<json>' | --file <path>)", `wh shape create Location --fields '{"x":"number","y":"number"}'`, "wh shape create Location --file fields.json", `wh shape create Tags --fields '{"labels":["string"],"scores":["number"]}'`, `wh shape create Player --fields '{"name":"string","position":{"x":"number","y":"number"}}'`, `wh shape create Review --fields '{"score":"number","reason?":"string"}'`);
@@ -62203,14 +62549,14 @@ var handleCreate6 = async (ctx, { flags, args }) => {
62203
62549
  missingMessage: "Usage: wh shape create <name> (--fields '<json>' | --file <path>)",
62204
62550
  example: "wh shape create Location --file fields.json"
62205
62551
  });
62206
- const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62552
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62207
62553
  const c = ctx.colors;
62208
62554
  const eventRequestId = flags["event-request-id"] ?? createOperationEventRequestId();
62209
62555
  ctx.status(`Operation event request: ${eventRequestId}`);
62210
62556
  const opts = { eventRequestId };
62211
62557
  if (flags.description !== undefined)
62212
62558
  opts.description = flags.description;
62213
- const response = await ctx.client.shape.create(org, repo, shapeName, fields, opts);
62559
+ const response = await ctx.client.shape.create(org, repo2, shapeName, fields, opts);
62214
62560
  const result = shapeChangeFromReceipt(response.receipt);
62215
62561
  writeOutput(ctx, response, () => {
62216
62562
  if (result.operation === "noop") {
@@ -62232,9 +62578,9 @@ var handleRevise3 = async (ctx, { flags, args }) => {
62232
62578
  missingMessage: "Usage: wh shape revise <name> (--fields '<json>' | --file <path>)",
62233
62579
  example: "wh shape revise Location --file fields.json"
62234
62580
  });
62235
- const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62581
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62236
62582
  const c = ctx.colors;
62237
- const previousShape = flags["show-diff"] ? await ctx.client.shape.get(org, repo, shapeName) : undefined;
62583
+ const previousShape = flags["show-diff"] ? await ctx.client.shape.get(org, repo2, shapeName) : undefined;
62238
62584
  const previousVersion = previousShape?.version?.version;
62239
62585
  const previousFields = previousShape ? fieldsFromShapeData(previousShape.version?.data) : undefined;
62240
62586
  const eventRequestId = flags["event-request-id"] ?? createOperationEventRequestId();
@@ -62242,7 +62588,7 @@ var handleRevise3 = async (ctx, { flags, args }) => {
62242
62588
  const opts = { eventRequestId };
62243
62589
  if (flags.description !== undefined)
62244
62590
  opts.description = flags.description;
62245
- const response = await ctx.client.shape.revise(org, repo, shapeName, newFields, opts);
62591
+ const response = await ctx.client.shape.revise(org, repo2, shapeName, newFields, opts);
62246
62592
  const result = shapeChangeFromReceipt(response.receipt);
62247
62593
  let diff;
62248
62594
  if (previousFields) {
@@ -62250,7 +62596,7 @@ var handleRevise3 = async (ctx, { flags, args }) => {
62250
62596
  if (result.operation === "noop") {
62251
62597
  committedBaseFields = newFields;
62252
62598
  } else if (previousVersion !== result.version - 1) {
62253
- const committedBase = await ctx.client.thing.get(org, repo, shapeName, result.version - 1);
62599
+ const committedBase = await ctx.client.thing.get(org, repo2, shapeName, result.version - 1);
62254
62600
  committedBaseFields = fieldsFromShapeData(committedBase.data);
62255
62601
  }
62256
62602
  diff = diffShapeFields(committedBaseFields, newFields);
@@ -62270,10 +62616,10 @@ var handleRetract2 = async (ctx, { flags, args }) => {
62270
62616
  if (!shapeName) {
62271
62617
  usageError("Usage: wh shape retract <name> [--expected-version <n>]", "wh shape retract Location");
62272
62618
  }
62273
- const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62619
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62274
62620
  const expectedVersion = parsePositiveIntFlag(flags["expected-version"], "--expected-version", "wh shape retract Location --expected-version 3");
62275
62621
  const c = ctx.colors;
62276
- const commitResult = await ctx.client.commit.apply(org, repo, flags.message ?? `retract shape ${shapeName}`, [
62622
+ const commitResult = await ctx.client.commit.apply(org, repo2, flags.message ?? `retract shape ${shapeName}`, [
62277
62623
  {
62278
62624
  operation: "retract",
62279
62625
  kind: "shape",
@@ -62282,10 +62628,7 @@ var handleRetract2 = async (ctx, { flags, args }) => {
62282
62628
  ...expectedVersion !== undefined ? { expectedVersion } : {}
62283
62629
  }
62284
62630
  ], { committer: flags.committer });
62285
- const result = commitResult.operations[0];
62286
- if (!result)
62287
- throw new Error("Commit returned no operation result");
62288
- assertSingleOpSuccess(commitResult);
62631
+ requireSingleOpSuccess(commitResult);
62289
62632
  writeOutput(ctx, commitResult, () => {
62290
62633
  renderCommitterEcho(ctx.out, c, flags.committer);
62291
62634
  ctx.out(`${c.red}Retracted${c.reset} ${c.magenta}${shapeName}${c.reset}`);
@@ -62297,11 +62640,11 @@ var handleShapeRename = async (ctx, { flags, args }) => {
62297
62640
  if (!oldName || !newName) {
62298
62641
  usageError("Usage: wh shape rename <oldName> <newName>", "wh shape rename Location Place");
62299
62642
  }
62300
- const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62643
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx), ctx.config);
62301
62644
  const c = ctx.colors;
62302
62645
  const eventRequestId = flags["event-request-id"] ?? createOperationEventRequestId();
62303
62646
  ctx.status(`Operation event request: ${eventRequestId}`);
62304
- const response = await ctx.client.shape.rename(org, repo, oldName, newName, {
62647
+ const response = await ctx.client.shape.rename(org, repo2, oldName, newName, {
62305
62648
  eventRequestId
62306
62649
  });
62307
62650
  writeOutput(ctx, response, () => {
@@ -62319,9 +62662,9 @@ var SHAPE_DOMAIN = defineDomain({
62319
62662
  prime: true,
62320
62663
  summary: "List all shapes",
62321
62664
  args: "",
62322
- flags: listFlags4,
62665
+ flags: listFlags5,
62323
62666
  examples: ["wh shape list", 'wh shape list --match "Game*"'],
62324
- handler: handleList6
62667
+ handler: handleList7
62325
62668
  },
62326
62669
  view: {
62327
62670
  prime: true,
@@ -62348,14 +62691,14 @@ var SHAPE_DOMAIN = defineDomain({
62348
62691
  prime: true,
62349
62692
  summary: "Create a new shape",
62350
62693
  args: "<name>",
62351
- flags: createFlags7,
62694
+ flags: createFlags8,
62352
62695
  examples: [
62353
62696
  `wh shape create GameConfig --repo org/repo --fields '{"x":"number"}'`,
62354
62697
  "wh shape create GameConfig --repo org/repo --file fields.json",
62355
62698
  `wh shape create Player --fields '{"name":{"type":"string","minLength":1,"maxLength":40},"role":{"type":"string","enum":["dm","player"]},"level":{"type":"number","minimum":1,"integer":true},"home":{"type":"wref","shape":"Location"},"tags":{"type":"array","items":"string","minItems":1}}'`
62356
62699
  ],
62357
62700
  notes: [...FIELD_CONSTRAINTS_NOTES],
62358
- handler: handleCreate6
62701
+ handler: handleCreate7
62359
62702
  },
62360
62703
  retract: {
62361
62704
  prime: true,
@@ -62403,7 +62746,7 @@ var SHAPE_DOMAIN = defineDomain({
62403
62746
  var orgScopeFlag = flag.string({
62404
62747
  description: `org slug for org-scoped events (${ORG_SCOPED_EVENT_TYPES.join(", ")}); use instead of --repo`
62405
62748
  });
62406
- var createFlags8 = {
62749
+ var createFlags9 = {
62407
62750
  on: flag.string({
62408
62751
  description: "Shape to subscribe to"
62409
62752
  }),
@@ -62441,27 +62784,27 @@ var createFlags8 = {
62441
62784
  })
62442
62785
  };
62443
62786
  var updateFlags4 = {
62444
- on: createFlags8.on,
62445
- kind: createFlags8.kind,
62446
- filter: createFlags8.filter,
62447
- cronspec: createFlags8.cronspec,
62448
- timezone: createFlags8.timezone,
62787
+ on: createFlags9.on,
62788
+ kind: createFlags9.kind,
62789
+ filter: createFlags9.filter,
62790
+ cronspec: createFlags9.cronspec,
62791
+ timezone: createFlags9.timezone,
62449
62792
  "webhook-url": flag.string({
62450
62793
  description: "Webhook destination URL"
62451
62794
  }),
62452
- url: createFlags8.url,
62453
- "fallback-webhook-url": createFlags8["fallback-webhook-url"],
62795
+ url: createFlags9.url,
62796
+ "fallback-webhook-url": createFlags9["fallback-webhook-url"],
62454
62797
  "clear-fallback-webhook-url": flag.boolean({
62455
62798
  description: "Clear the fallback webhook URL"
62456
62799
  }),
62457
- "allow-trace-reentry": createFlags8["allow-trace-reentry"],
62458
- name: createFlags8.name,
62800
+ "allow-trace-reentry": createFlags9["allow-trace-reentry"],
62801
+ name: createFlags9.name,
62459
62802
  org: orgScopeFlag
62460
62803
  };
62461
62804
  var logFlags = {
62462
62805
  limit: flag.number({ description: "Max deliveries to return" })
62463
62806
  };
62464
- var listFlags5 = {
62807
+ var listFlags6 = {
62465
62808
  limit: flag.number({ description: "Max subscriptions to return" }),
62466
62809
  org: orgScopeFlag
62467
62810
  };
@@ -62532,9 +62875,9 @@ function parseEventType(raw, _usage, example) {
62532
62875
  if (raw === undefined) {
62533
62876
  return COMMIT_EVENT_TYPE;
62534
62877
  }
62535
- if (SUBSCRIBABLE_EVENT_TYPES.includes(raw)) {
62536
- return raw;
62537
- }
62878
+ const parsed = SUBSCRIBABLE_EVENT_TYPES.find((candidate) => candidate === raw);
62879
+ if (parsed)
62880
+ return parsed;
62538
62881
  usageError(`--event must be one of: ${SUBSCRIBABLE_EVENT_TYPES.join(", ")}`, example);
62539
62882
  }
62540
62883
  function buildSubscriptionPatchArgs(flags, usage, example) {
@@ -62594,8 +62937,8 @@ function resolveSubScope(ctx, flags, correctiveExample) {
62594
62937
  if (typeof flags.org === "string" && flags.org) {
62595
62938
  return { orgName: flags.org };
62596
62939
  }
62597
- const { org, repo } = resolveRepoContext(ctx);
62598
- return { orgName: org, repoName: repo };
62940
+ const { org, repo: repo2 } = resolveRepoContext(ctx);
62941
+ return { orgName: org, repoName: repo2 };
62599
62942
  }
62600
62943
  function rejectConflictingSubScope(ctx, flags, correctiveExample) {
62601
62944
  if (flags.org !== undefined && ctx.invocation.flags.repo !== undefined) {
@@ -62607,7 +62950,7 @@ function scopeLabel(scope) {
62607
62950
  }
62608
62951
 
62609
62952
  // ../../packages/warmhub-cli/src/domains/sub/handlers-create.ts
62610
- var handleCreate7 = async (ctx, { flags, args }) => {
62953
+ var handleCreate8 = async (ctx, { flags, args }) => {
62611
62954
  const name = args[0] ?? flags.name;
62612
62955
  const usage = `Usage: wh sub create <name> (--repo org/repo | --org org) [--event ${SUBSCRIBABLE_EVENT_TYPES.join("|")}] [options]`;
62613
62956
  const example = `wh sub create signal-hook --repo myorg/myrepo --on Signal --filter '{"shape":"Signal"}' --webhook-url https://example.com/hook`;
@@ -62651,12 +62994,12 @@ var handleCreate7 = async (ctx, { flags, args }) => {
62651
62994
  if (flags.org !== undefined) {
62652
62995
  usageError(`Flag --org cannot be used with repo-scoped ${eventType} subscriptions`, `wh sub create repo-hook --repo myorg/myrepo --event ${eventType} --webhook-url https://example.com/hook`);
62653
62996
  }
62654
- const { org, repo } = resolveRepoContext(ctx);
62997
+ const { org, repo: repo2 } = resolveRepoContext(ctx);
62655
62998
  if (eventType !== "commit") {
62656
62999
  rejectCommitOnlyFlags(flags, eventType);
62657
63000
  const result2 = await ctx.client.subscription.create({
62658
63001
  orgName: org,
62659
- repoName: repo,
63002
+ repoName: repo2,
62660
63003
  name,
62661
63004
  eventType,
62662
63005
  kind,
@@ -62665,7 +63008,7 @@ var handleCreate7 = async (ctx, { flags, args }) => {
62665
63008
  });
62666
63009
  writeOutput(ctx, result2, () => {
62667
63010
  const c = ctx.colors;
62668
- ctx.status(`${c.green}Created subscription${c.reset} ${c.cyan}${name}${c.reset} on ${c.cyan}${org}/${repo}${c.reset} (${eventType})`);
63011
+ ctx.status(`${c.green}Created subscription${c.reset} ${c.cyan}${name}${c.reset} on ${c.cyan}${org}/${repo2}${c.reset} (${eventType})`);
62669
63012
  });
62670
63013
  return;
62671
63014
  }
@@ -62673,7 +63016,7 @@ var handleCreate7 = async (ctx, { flags, args }) => {
62673
63016
  const sourceRepoRef = typeof flags.source === "string" ? flags.source : undefined;
62674
63017
  const result = await ctx.client.subscription.create({
62675
63018
  orgName: org,
62676
- repoName: repo,
63019
+ repoName: repo2,
62677
63020
  name,
62678
63021
  webhookUrl,
62679
63022
  fallbackWebhookUrl: createArgs.fallbackWebhookUrl,
@@ -62685,7 +63028,7 @@ var handleCreate7 = async (ctx, { flags, args }) => {
62685
63028
  });
62686
63029
  writeOutput(ctx, result, () => {
62687
63030
  const c = ctx.colors;
62688
- ctx.status(`${c.green}Created subscription${c.reset} ${c.cyan}${name}${c.reset} on ${c.cyan}${org}/${repo}${c.reset}`);
63031
+ ctx.status(`${c.green}Created subscription${c.reset} ${c.cyan}${name}${c.reset} on ${c.cyan}${org}/${repo2}${c.reset}`);
62689
63032
  });
62690
63033
  };
62691
63034
  var handleUpdate4 = async (ctx, { flags, args }) => {
@@ -62861,7 +63204,7 @@ function renderSubscriptionLog(out, statusOut, c, subscriptionName, result) {
62861
63204
  }
62862
63205
 
62863
63206
  // ../../packages/warmhub-cli/src/domains/sub/handlers-management.ts
62864
- var handleList7 = async (ctx, { flags }) => {
63207
+ var handleList8 = async (ctx, { flags }) => {
62865
63208
  const scope = resolveSubScope(ctx, flags, "wh sub list --repo myorg/myrepo");
62866
63209
  const label = scopeLabel(scope);
62867
63210
  const all = await ctx.client.subscription.list(scope);
@@ -62961,11 +63304,11 @@ var handleLog = async (ctx, { flags, args }) => {
62961
63304
  usageError("Usage: wh sub log <name> [--repo org/repo]", "wh sub log my-sub --repo myorg/myrepo");
62962
63305
  }
62963
63306
  const org = scope.orgName;
62964
- const repo = scope.repoName;
63307
+ const repo2 = scope.repoName;
62965
63308
  if (ctx.liveMode) {
62966
63309
  await runLive({
62967
63310
  apiUrl: ctx.config.apiUrl,
62968
- poll: (c) => c.action.liveFeed(org, repo, name, { limit: flags.limit }),
63311
+ poll: (c) => c.action.liveFeed(org, repo2, name, { limit: flags.limit }),
62969
63312
  render: (result2) => renderSubscriptionLog(ctx.out, ctx.status, ctx.colors, name, result2),
62970
63313
  out: ctx.out,
62971
63314
  err: ctx.err,
@@ -62976,11 +63319,12 @@ var handleLog = async (ctx, { flags, args }) => {
62976
63319
  inactivityTimeoutMs: ctx.inactivityTimeoutMs,
62977
63320
  functionLogs: ctx.functionLogMode,
62978
63321
  profile: ctx.profile,
63322
+ clientFlags: ctx.clientFlags,
62979
63323
  signal: ctx.signal
62980
63324
  });
62981
63325
  return;
62982
63326
  }
62983
- const result = await ctx.client.action.liveFeed(org, repo, name, {
63327
+ const result = await ctx.client.action.liveFeed(org, repo2, name, {
62984
63328
  limit: flags.limit
62985
63329
  });
62986
63330
  writeOutput(ctx, result, () => renderSubscriptionLog(ctx.out, ctx.status, ctx.colors, name, result));
@@ -62990,8 +63334,8 @@ var handleAttempts = async (ctx, { args }) => {
62990
63334
  if (!runIdArg) {
62991
63335
  usageError("Usage: wh sub attempts <runId> [--repo org/repo]", "wh sub attempts 019d90f0-1111-7000-8000-000000000001 --repo myorg/myrepo");
62992
63336
  }
62993
- const { org, repo } = resolveRepoContext(ctx);
62994
- const result = await ctx.client.action.getRunAttempts(org, repo, runIdArg);
63337
+ const { org, repo: repo2 } = resolveRepoContext(ctx);
63338
+ const result = await ctx.client.action.getRunAttempts(org, repo2, runIdArg);
62995
63339
  writeOutput(ctx, result, () => {
62996
63340
  const c = ctx.colors;
62997
63341
  if (!result.length) {
@@ -63025,7 +63369,7 @@ var SUB_DOMAIN = defineDomain({
63025
63369
  prime: true,
63026
63370
  summary: "Create a subscription",
63027
63371
  args: "<name>",
63028
- flags: createFlags8,
63372
+ flags: createFlags9,
63029
63373
  examples: [
63030
63374
  "# Create a webhook subscription for things of a shape",
63031
63375
  ` $ wh sub create signal-hook --repo myorg/myrepo --on Signal --kind webhook --filter '{"shape":"Signal"}' --webhook-url https://example.com/hook`,
@@ -63051,7 +63395,7 @@ var SUB_DOMAIN = defineDomain({
63051
63395
  ' $ echo "tok_secret" | wh credential set webhook-keys WEBHOOK_BEARER_TOKEN --repo myorg/myrepo',
63052
63396
  " $ wh sub bind signal-hook --credentials webhook-keys --repo myorg/myrepo"
63053
63397
  ],
63054
- handler: handleCreate7
63398
+ handler: handleCreate8
63055
63399
  },
63056
63400
  update: {
63057
63401
  status: "live",
@@ -63086,14 +63430,14 @@ var SUB_DOMAIN = defineDomain({
63086
63430
  prime: true,
63087
63431
  summary: "List all subscriptions",
63088
63432
  args: "",
63089
- flags: listFlags5,
63433
+ flags: listFlags6,
63090
63434
  examples: [
63091
63435
  "wh sub list --repo myorg/myrepo",
63092
63436
  "wh sub list --limit 10",
63093
63437
  "# Org-scoped metadata subscriptions",
63094
63438
  " $ wh sub list --org myorg"
63095
63439
  ],
63096
- handler: handleList7
63440
+ handler: handleList8
63097
63441
  },
63098
63442
  log: {
63099
63443
  status: "live",
@@ -63272,7 +63616,7 @@ function tokenStatus(pat) {
63272
63616
  return "expired";
63273
63617
  return "active";
63274
63618
  }
63275
- var createFlags9 = {
63619
+ var createFlags10 = {
63276
63620
  name: flag.string({ short: "n", description: "Token name" }),
63277
63621
  scope: flag.string({
63278
63622
  short: "s",
@@ -63293,7 +63637,7 @@ var createFlags9 = {
63293
63637
  var nameFlags = {
63294
63638
  name: flag.string({ short: "n", description: "Token name" })
63295
63639
  };
63296
- var listFlags6 = {
63640
+ var listFlags7 = {
63297
63641
  all: flag.boolean({
63298
63642
  short: "a",
63299
63643
  description: "Include expired and revoked tokens (default: active only)"
@@ -63331,7 +63675,7 @@ function formatScopes(scopes) {
63331
63675
  return `${base}${formatAllowedMatches(e.allowedMatches)}`;
63332
63676
  }).join(" ");
63333
63677
  }
63334
- var handleCreate8 = async (ctx, { flags }) => {
63678
+ var handleCreate9 = async (ctx, { flags }) => {
63335
63679
  if (!flags.name) {
63336
63680
  usageError("Usage: wh token create --name <name> [flags]", "wh token create --name ci-bot --scope myorg/myrepo=role:editor --expires 90d");
63337
63681
  }
@@ -63380,7 +63724,7 @@ var handleCreate8 = async (ctx, { flags }) => {
63380
63724
  ctx.status(` expires: ${new Date(result.expiresAt).toISOString().slice(0, 16)}`);
63381
63725
  });
63382
63726
  };
63383
- var handleList8 = async (ctx, { flags }) => {
63727
+ var handleList9 = async (ctx, { flags }) => {
63384
63728
  const c = ctx.colors;
63385
63729
  const items = await ctx.client.token.list({ includeInactive: flags.all });
63386
63730
  writePageOutput(ctx, items, { limit: items.length, nextCursor: null }, () => {
@@ -63400,7 +63744,7 @@ var handleList8 = async (ctx, { flags }) => {
63400
63744
  }
63401
63745
  });
63402
63746
  };
63403
- var handleGet = async (ctx, { flags }) => {
63747
+ var handleGet2 = async (ctx, { flags }) => {
63404
63748
  if (!flags.name) {
63405
63749
  usageError("Usage: wh token get --name <name>", "wh token get --name ci-bot");
63406
63750
  }
@@ -63424,7 +63768,7 @@ var handleGet = async (ctx, { flags }) => {
63424
63768
  }
63425
63769
  });
63426
63770
  };
63427
- var handleRevoke2 = async (ctx, { flags }) => {
63771
+ var handleRevoke3 = async (ctx, { flags }) => {
63428
63772
  if (!flags.name) {
63429
63773
  usageError("Usage: wh token revoke --name <name>", "wh token revoke --name ci-bot");
63430
63774
  }
@@ -63442,7 +63786,7 @@ var TOKEN_DOMAIN = defineDomain({
63442
63786
  create: {
63443
63787
  summary: "Create a new personal access token",
63444
63788
  args: "",
63445
- flags: createFlags9,
63789
+ flags: createFlags10,
63446
63790
  examples: [
63447
63791
  "wh token create --name ci-bot --scope myorg/myrepo=repo:read,repo:write",
63448
63792
  "wh token create --name ci-bot --scope myorg/myrepo=role:editor",
@@ -63451,32 +63795,32 @@ var TOKEN_DOMAIN = defineDomain({
63451
63795
  `wh token create --name scoped --scopes-json '[{"resource":"myorg/myrepo","permissions":["repo:read"],"allowedMatches":["Signal/*"]}]'`,
63452
63796
  `wh token create --name global-reader --scopes-json '[{"permissions":["repo:read"]}]'`
63453
63797
  ],
63454
- handler: handleCreate8
63798
+ handler: handleCreate9
63455
63799
  },
63456
63800
  list: {
63457
63801
  summary: "List your personal access tokens (active by default)",
63458
63802
  args: "",
63459
- flags: listFlags6,
63803
+ flags: listFlags7,
63460
63804
  examples: [
63461
63805
  "wh token list",
63462
63806
  "wh token list --all",
63463
63807
  "wh token list --json"
63464
63808
  ],
63465
- handler: handleList8
63809
+ handler: handleList9
63466
63810
  },
63467
63811
  get: {
63468
63812
  summary: "View a token by name",
63469
63813
  args: "",
63470
63814
  flags: nameFlags,
63471
63815
  examples: ["wh token get --name ci-bot"],
63472
- handler: handleGet
63816
+ handler: handleGet2
63473
63817
  },
63474
63818
  revoke: {
63475
63819
  summary: "Revoke a token by name",
63476
63820
  args: "",
63477
63821
  flags: nameFlags,
63478
63822
  examples: ["wh token revoke --name ci-bot"],
63479
- handler: handleRevoke2
63823
+ handler: handleRevoke3
63480
63824
  }
63481
63825
  }
63482
63826
  });
@@ -64102,14 +64446,14 @@ var handleUse = async (ctx, { args, flags }) => {
64102
64446
  });
64103
64447
  return;
64104
64448
  }
64105
- const parts = repoArg.split("/");
64106
- if (parts.length !== 2 || !parts[0] || !parts[1]) {
64449
+ const parsed = parseRepoSlug(repoArg);
64450
+ if (!parsed) {
64107
64451
  throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid repo format "${repoArg}". Expected "org/repo" (exactly one slash).`, undefined, "Example: wh use myorg/myrepo");
64108
64452
  }
64109
- const [org, repo] = parts;
64453
+ const { org, repo: repo2 } = parsed;
64110
64454
  const repoNotFoundMessage = `Repo "${repoArg}" not found`;
64111
64455
  try {
64112
- await ctx.client.repo.get(org, repo);
64456
+ await ctx.client.repo.get(org, repo2);
64113
64457
  } catch (e) {
64114
64458
  if (!(e instanceof WarmHubError) || e.kind !== "NOT_FOUND" || e.errorCode !== "NOT_FOUND" || e.message !== repoNotFoundMessage) {
64115
64459
  throw e;
@@ -64144,6 +64488,69 @@ var USE_DOMAIN = defineDomain({
64144
64488
  handler: handleUse
64145
64489
  });
64146
64490
 
64491
+ // ../../packages/warmhub-cli/src/domains/view.ts
64492
+ var evaluateFlags = {
64493
+ limit: flag.number({
64494
+ description: "Max results per page (default: 50, max: 500)"
64495
+ }),
64496
+ cursor: flag.string({ description: "Opaque pagination cursor" }),
64497
+ all: flag.boolean({ description: "Fetch all pages" })
64498
+ };
64499
+ var handleEvaluate = async (ctx, { args, flags }) => {
64500
+ const wref = args[0]?.trim();
64501
+ if (!wref) {
64502
+ usageError("Usage: wh view evaluate <wref> [--limit N] [--cursor TOKEN] [--all]", "wh view evaluate View/active-users --limit 50");
64503
+ }
64504
+ if (flags.cursor && !flags.limit) {
64505
+ usageError("Usage: wh view evaluate <wref> --limit N --cursor TOKEN", "wh view evaluate View/active-users --limit 50 --cursor <token>");
64506
+ }
64507
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx), ctx.config);
64508
+ const boundedLimit = Math.min(flags.limit ?? DEFAULT_PAGE_LIMIT, MAX_PAGE_LIMIT);
64509
+ const pageLimit = flags.all ? Math.min(flags.limit ?? AUTO_PAGE_LIMIT, MAX_PAGE_LIMIT) : boundedLimit;
64510
+ if (flags.all) {
64511
+ const items = await ctx.client.view.evaluateAll(org, repo2, wref, {
64512
+ limit: pageLimit,
64513
+ cursor: flags.cursor
64514
+ });
64515
+ writePageOutput(ctx, items, { limit: pageLimit, nextCursor: null }, () => {
64516
+ ctx.out(`${ctx.colors.bold}View ${escapeTerminalTextForDisplay(wref)}${ctx.colors.reset}`);
64517
+ renderQueryResults(ctx.out, ctx.colors, { items });
64518
+ });
64519
+ return;
64520
+ }
64521
+ const result = await ctx.client.view.evaluate(org, repo2, wref, {
64522
+ limit: boundedLimit,
64523
+ cursor: flags.cursor
64524
+ });
64525
+ if (result.nextCursor) {
64526
+ emitPartialPageHint(ctx, result.items.length, result.nextCursor, boundedLimit);
64527
+ }
64528
+ writePageOutput(ctx, result.items, { limit: boundedLimit, nextCursor: result.nextCursor ?? null }, () => {
64529
+ const selected = `${result.view.wref}@v${result.view.version}`;
64530
+ ctx.out(`${ctx.colors.bold}View ${escapeTerminalTextForDisplay(selected)}${ctx.colors.reset}`);
64531
+ renderQueryResults(ctx.out, ctx.colors, result);
64532
+ });
64533
+ };
64534
+ var VIEW_DOMAIN = defineDomain({
64535
+ name: "view",
64536
+ summary: "Stored View operations",
64537
+ group: "resource",
64538
+ verbs: {
64539
+ evaluate: {
64540
+ prime: true,
64541
+ summary: "Evaluate a stored View against live repository results",
64542
+ args: "<wref>",
64543
+ flags: evaluateFlags,
64544
+ examples: [
64545
+ "wh view evaluate View/active-users",
64546
+ "wh view evaluate View/active-users@v3 --limit 50",
64547
+ "wh view evaluate View/active-users --all"
64548
+ ],
64549
+ handler: handleEvaluate
64550
+ }
64551
+ }
64552
+ });
64553
+
64147
64554
  // ../../packages/warmhub-cli/src/domains/index.ts
64148
64555
  function registerAllDomains(registry3) {
64149
64556
  registry3.register(AUTH_DOMAIN);
@@ -64166,6 +64573,8 @@ function registerAllDomains(registry3) {
64166
64573
  registry3.register(TOKEN_DOMAIN);
64167
64574
  registry3.register(COMPONENT_DOMAIN);
64168
64575
  registry3.register(USE_DOMAIN);
64576
+ registry3.register(VIEW_DOMAIN);
64577
+ registry3.register(GRANT_DOMAIN);
64169
64578
  }
64170
64579
 
64171
64580
  // ../../packages/warmhub-cli/src/production-domain-registry.ts
@@ -64365,8 +64774,8 @@ async function printRootHelp(ctx) {
64365
64774
  }
64366
64775
  let repoSlug;
64367
64776
  try {
64368
- const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
64369
- repoSlug = `${org}/${repo}`;
64777
+ const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx), ctx.config);
64778
+ repoSlug = `${org}/${repo2}`;
64370
64779
  } catch {
64371
64780
  repoSlug = undefined;
64372
64781
  }
@@ -65403,60 +65812,6 @@ var catalog = {
65403
65812
  function prepareCliInvocation(argv) {
65404
65813
  return prepare(argv, resolver, catalog);
65405
65814
  }
65406
- // ../../packages/warmhub-cli/src/cli-context.ts
65407
- function resolveCliContext(args) {
65408
- const { invocation, format } = args;
65409
- const config2 = args.config ?? loadConfig();
65410
- const apiUrlFlag = invocation.flags["api-url"];
65411
- const explicitApiUrl = typeof apiUrlFlag === "string" ? apiUrlFlag : undefined;
65412
- const profileFlag = invocation.flags.profile;
65413
- const apiUrl = explicitApiUrl ?? process.env.WARMHUB_API_URL ?? config2.apiUrl;
65414
- config2.apiUrl = apiUrl;
65415
- const explicitProfile = (typeof profileFlag === "string" ? profileFlag : undefined) ?? config2.profile;
65416
- const effectiveProfile = explicitProfile ?? "default";
65417
- const overridesBypassProfile = !explicitProfile && !!process.env.WH_TOKEN && (!!process.env.WARMHUB_API_URL || !!explicitApiUrl);
65418
- let profileData = null;
65419
- if (!overridesBypassProfile) {
65420
- try {
65421
- profileData = getProfile(effectiveProfile);
65422
- } catch (err) {
65423
- if (explicitProfile)
65424
- throw err;
65425
- const reason = err instanceof Error ? err.message : String(err);
65426
- if (format === "json" || format === "jsonl") {
65427
- process.stderr.write(`${JSON.stringify({
65428
- level: "warning",
65429
- kind: "auth-file-unreadable",
65430
- message: `could not read auth.json: ${reason}`
65431
- })}
65432
- `);
65433
- } else {
65434
- process.stderr.write(`warning: could not read auth.json (${reason})
65435
- `);
65436
- }
65437
- }
65438
- }
65439
- if (profileData) {
65440
- if (profileData.apiUrl && !explicitApiUrl) {
65441
- config2.apiUrl = profileData.apiUrl;
65442
- }
65443
- } else if (explicitProfile) {
65444
- const isAuthLogin = invocation.kind === "static" && invocation.commandPath[0] === "auth" && invocation.commandPath[1] === "login";
65445
- if (!isAuthLogin) {
65446
- const available = listProfiles();
65447
- const availableHint = available.length > 0 ? `Available profiles: ${available.join(", ")}.` : "No profiles found.";
65448
- throw new CliError(5 /* Auth */, "AUTH", `Auth profile "${explicitProfile}" does not exist.`, undefined, `${availableHint}
65449
- Run \`wh auth login --profile ${explicitProfile}\` to create it.`);
65450
- }
65451
- }
65452
- const client = args.client ?? createClient(config2, {
65453
- functionLogs: args.functionLogs,
65454
- profile: effectiveProfile,
65455
- signal: args.signal
65456
- });
65457
- return { config: config2, profile: effectiveProfile, client };
65458
- }
65459
-
65460
65815
  // ../../packages/warmhub-cli/src/confirm-prompt.ts
65461
65816
  function confirmPrompt(message, opts = {}) {
65462
65817
  const input = opts.input ?? process.stdin;
@@ -65504,8 +65859,8 @@ function selectedRepo(flags, config2) {
65504
65859
  }
65505
65860
  }
65506
65861
  try {
65507
- const { org, repo } = parseOrgRepo(repoRef, config2);
65508
- return `${org}/${repo}`;
65862
+ const { org, repo: repo2 } = parseOrgRepo(repoRef, config2);
65863
+ return `${org}/${repo2}`;
65509
65864
  } catch {
65510
65865
  return;
65511
65866
  }
@@ -65703,10 +66058,11 @@ async function runPreparedCli(rawArgv, prepared, opts) {
65703
66058
  requestedMode: requestedFunctionLogs
65704
66059
  });
65705
66060
  const localOnlyCommand = isLocalOnlyInvocation(invocation);
65706
- const { config: config2, client, profile } = localOnlyCommand ? {
66061
+ const { config: config2, client, profile, clientFlags } = localOnlyCommand ? {
65707
66062
  config: loadConfig(),
65708
66063
  client: createLocalOnlyClient(),
65709
- profile: "default"
66064
+ profile: "default",
66065
+ clientFlags: []
65710
66066
  } : resolveCliContext({
65711
66067
  invocation,
65712
66068
  format,
@@ -65726,6 +66082,7 @@ async function runPreparedCli(rawArgv, prepared, opts) {
65726
66082
  config: config2,
65727
66083
  invocation,
65728
66084
  profile,
66085
+ clientFlags,
65729
66086
  colors,
65730
66087
  chars,
65731
66088
  format,
@@ -65843,7 +66200,7 @@ function resolveLogLevel(flagLevel, env) {
65843
66200
  // package.json
65844
66201
  var package_default3 = {
65845
66202
  name: "@warmhub/cli",
65846
- version: "0.88.0",
66203
+ version: "0.89.0",
65847
66204
  private: false,
65848
66205
  type: "module",
65849
66206
  description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -65987,9 +66344,9 @@ async function performRegisteredInstall(args) {
65987
66344
  }
65988
66345
  function mapInstallError(error51, componentRef, verb) {
65989
66346
  if (isMissingRegistrationError(error51)) {
65990
- const [ownerOrg, name] = componentRef.split("/");
66347
+ const parsed = parseComponentRef(componentRef);
65991
66348
  const backendCode = warmHubErrorBackendCode(error51);
65992
- return new CliError(2 /* UserInput */, "USER_INPUT", `No component registered as ${componentRef}`, undefined, `Register it first with 'wh component register ${name ?? componentRef} --org ${ownerOrg ?? "<org>"} --manifest <path>'.`, undefined, backendCode ?? "NOT_FOUND");
66349
+ return new CliError(2 /* UserInput */, "USER_INPUT", `No component registered as ${componentRef}`, undefined, `Register it first with 'wh component register ${parsed?.name ?? componentRef} --org ${parsed?.org ?? "<org>"} --manifest <path>'.`, undefined, backendCode ?? "NOT_FOUND");
65993
66350
  }
65994
66351
  if (isMissingManifestPermissionError(error51)) {
65995
66352
  const backendCode = warmHubErrorBackendCode(error51) ?? warmHubErrorKind(error51);
@@ -66462,5 +66819,5 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
66462
66819
  version: package_default3.version
66463
66820
  }) : interceptedExitCode;
66464
66821
 
66465
- //# debugId=964BFCCE631EA49D64756E2164756E21
66466
- //# warmhub-cli-build-info {"cliVersion":"0.88.0","sdkVersion":"0.86.0"}
66822
+ //# debugId=0D9B1F5B8E62352264756E2164756E21
66823
+ //# warmhub-cli-build-info {"cliVersion":"0.89.0","sdkVersion":"0.87.0"}