@warmhub/cli 0.89.0 → 0.91.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/wh.js +225 -37
  2. package/package.json +1 -1
package/dist/wh.js CHANGED
@@ -19567,6 +19567,7 @@ function resolveManifestCredentialName(name, ctx) {
19567
19567
  var REPO_AUTH_SCOPES = [
19568
19568
  "repo:read",
19569
19569
  "repo:checkpoint-read",
19570
+ "repo:checkpoint-generate",
19570
19571
  "repo:write",
19571
19572
  "repo:configure",
19572
19573
  "repo:admin",
@@ -42940,8 +42941,8 @@ function normalizeOptionalName(value) {
42940
42941
 
42941
42942
  // ../../packages/sdk-ts/src/operation-normalize.ts
42942
42943
  function toBackendStreamOperation(operation) {
42943
- if (operation.expectedVersion !== undefined && operation.operation !== "revise" && operation.operation !== "retract") {
42944
- throw new Error("expectedVersion is only valid on revise or retract operations — set an explicit operation discriminator");
42944
+ if (operation.expectedVersion !== undefined && operation.operation !== "revise" && operation.operation !== "retract" && operation.operation !== "reaffirm") {
42945
+ throw new Error("expectedVersion is only valid on revise, retract, or reaffirm operations — set an explicit operation discriminator");
42945
42946
  }
42946
42947
  if (operation.operation === "retract") {
42947
42948
  return {
@@ -42953,6 +42954,17 @@ function toBackendStreamOperation(operation) {
42953
42954
  ...operation.leaseId ? { leaseId: operation.leaseId } : {}
42954
42955
  };
42955
42956
  }
42957
+ if (operation.operation === "reaffirm") {
42958
+ return {
42959
+ operation: "reaffirm",
42960
+ name: operation.name,
42961
+ ...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
42962
+ ...operation.kind ? { kind: operation.kind } : {},
42963
+ ...operation.add ? { add: operation.add } : {},
42964
+ ...operation.remove ? { remove: operation.remove } : {},
42965
+ ...operation.leaseId ? { leaseId: operation.leaseId } : {}
42966
+ };
42967
+ }
42956
42968
  if (operation.operation === "rename") {
42957
42969
  return {
42958
42970
  operation: "rename",
@@ -42970,6 +42982,9 @@ function toBackendStreamOperation(operation) {
42970
42982
  if (Object.hasOwn(operation, "active")) {
42971
42983
  throw new Error(`${kind2} revise operation no longer supports 'active' — use retract('${name}') instead`);
42972
42984
  }
42985
+ if (kind2 !== "assertion" && operation.affirmedTargets !== undefined) {
42986
+ throw new Error(`${kind2} revise operation does not support 'affirmedTargets' — it applies only to assertions; set kind: 'assertion' explicitly`);
42987
+ }
42973
42988
  if (kind2 === "collection") {
42974
42989
  return normalizeBackendCollectionRevise(operation, "commit.apply");
42975
42990
  }
@@ -42982,6 +42997,7 @@ function toBackendStreamOperation(operation) {
42982
42997
  kind: "assertion",
42983
42998
  name,
42984
42999
  data: operation.data,
43000
+ ...operation.affirmedTargets ? { affirmedTargets: operation.affirmedTargets } : {},
42985
43001
  ...operation.expectedVersion !== undefined ? { expectedVersion: operation.expectedVersion } : {},
42986
43002
  ...operation.leaseId ? { leaseId: operation.leaseId } : {}
42987
43003
  };
@@ -43000,6 +43016,9 @@ function toBackendStreamOperation(operation) {
43000
43016
  if (kind !== "collection" && (("type" in operation) && operation.type !== undefined || ("members" in operation) && operation.members !== undefined)) {
43001
43017
  throw new Error(`add operation '${operation.name ?? ""}' has collection fields but resolved kind '${kind}' — collection adds require both 'type' and 'members', or set kind: 'collection'`);
43002
43018
  }
43019
+ if (kind !== "assertion" && operation.affirmedTargets !== undefined) {
43020
+ throw new Error(`${kind} add operation does not support 'affirmedTargets' — it applies only to assertions; set kind: 'assertion' explicitly`);
43021
+ }
43003
43022
  if (kind === "collection") {
43004
43023
  return normalizeBackendCollectionAdd({ ...operation, skipExisting }, "commit.apply");
43005
43024
  }
@@ -43022,6 +43041,7 @@ function toBackendStreamOperation(operation) {
43022
43041
  name: operation.name,
43023
43042
  about: operation.about,
43024
43043
  data: operation.data,
43044
+ ...operation.affirmedTargets ? { affirmedTargets: operation.affirmedTargets } : {},
43025
43045
  ...skipExisting === true ? { skipExisting } : {}
43026
43046
  };
43027
43047
  }
@@ -43406,11 +43426,12 @@ function aggregateSubmittedStreamResult(input) {
43406
43426
  operations: input.results.map((result) => ({
43407
43427
  ...result.opIndex !== undefined ? { opIndex: result.opIndex } : {},
43408
43428
  name: result.name ?? "",
43409
- operation: result.operation === "revise" || result.operation === "retract" || result.operation === "rename" || result.operation === "noop" ? result.operation : "add",
43429
+ operation: result.operation === "revise" || result.operation === "retract" || result.operation === "reaffirm" || result.operation === "rename" || result.operation === "noop" ? result.operation : "add",
43410
43430
  dataHash: result.dataHash ?? "",
43411
43431
  version: result.version ?? 0,
43412
43432
  status: streamAppendResultStatus(result),
43413
43433
  error: result.error,
43434
+ ...result.affirmations ? { affirmations: result.affirmations } : {},
43414
43435
  ...result.status === "failed" && result.opIndex !== undefined && input.operations[result.opIndex]?.name !== undefined ? { submittedName: input.operations[result.opIndex]?.name } : {},
43415
43436
  ...result.resolvedName !== undefined ? { resolvedName: result.resolvedName } : {},
43416
43437
  ...result.retryable !== undefined ? { retryable: result.retryable } : {},
@@ -43425,7 +43446,7 @@ function completedOperationsFrom(result) {
43425
43446
  // ../../packages/sdk-ts/package.json
43426
43447
  var package_default = {
43427
43448
  name: "@warmhub/sdk-ts",
43428
- version: "0.87.0",
43449
+ version: "0.89.0",
43429
43450
  private: false,
43430
43451
  type: "module",
43431
43452
  description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -45571,6 +45592,7 @@ class WarmHubClient {
45571
45592
  repoName,
45572
45593
  shape: opts?.shape,
45573
45594
  about: opts?.about,
45595
+ affirmedAbout: opts?.affirmedAbout,
45574
45596
  kind: narrowKind(opts?.kind),
45575
45597
  match: opts?.match,
45576
45598
  includeRetracted: opts?.includeRetracted,
@@ -45644,6 +45666,7 @@ class WarmHubClient {
45644
45666
  repoName,
45645
45667
  shape: opts?.shape,
45646
45668
  about: opts?.about,
45669
+ affirmedAbout: opts?.affirmedAbout,
45647
45670
  kind: narrowKind(opts?.kind),
45648
45671
  match: opts?.match,
45649
45672
  includeRetracted: opts?.includeRetracted,
@@ -49968,6 +49991,9 @@ function pinnedWref(c, wref, version2) {
49968
49991
  const base = wref.replace(/@v\d+$/, "");
49969
49992
  return `${c.cyan}${escapeTerminalTextForDisplay(base)}@v${version2}${c.reset}`;
49970
49993
  }
49994
+ function formatAffirmedWrefs(c, wrefs) {
49995
+ return wrefs.map((wref) => pinnedWref(c, wref)).join(`${c.dim},${c.reset} `);
49996
+ }
49971
49997
  function kindLabel(c, kind) {
49972
49998
  return `${c.dim}${kind}${c.reset}`;
49973
49999
  }
@@ -50201,6 +50227,9 @@ function renderAbout(out, c, result) {
50201
50227
  const a = item;
50202
50228
  const wref = a.wref ?? a.name;
50203
50229
  out(` ${pinnedWref(c, wref, a.version)} ${kindLabel(c, a.kind ?? "assertion")}`);
50230
+ if (Array.isArray(a.affirmedWrefs) && a.affirmedWrefs.length > 0) {
50231
+ out(` ${c.dim}affirms:${c.reset} ${formatAffirmedWrefs(c, a.affirmedWrefs.map(String))}`);
50232
+ }
50204
50233
  if (a.data && typeof a.data === "object") {
50205
50234
  out(` ${c.dim}data:${c.reset}`);
50206
50235
  const lines = JSON.stringify(a.data, null, 2).split(`
@@ -50284,6 +50313,10 @@ var createFlags = {
50284
50313
  shape: flag.string({ description: "Shape for assertion (required)" }),
50285
50314
  data: flag.string({ description: "Data payload (JSON)" }),
50286
50315
  about: flag.string({ description: "Target wref" }),
50316
+ affirm: flag.string({
50317
+ multiple: true,
50318
+ description: "Pinned target version the claim is affirmed for (repeatable): Shape/name@vN"
50319
+ }),
50287
50320
  message: flag.string({ short: "m", description: "Commit message" }),
50288
50321
  committer: flag.string({
50289
50322
  description: "Committer wref (shape or shaped thing; e.g. Agent/bot-1)"
@@ -50291,6 +50324,27 @@ var createFlags = {
50291
50324
  };
50292
50325
  var reviseFlags = {
50293
50326
  data: flag.string({ description: "Data payload (JSON)" }),
50327
+ affirm: flag.string({
50328
+ multiple: true,
50329
+ description: "Complete affirmation set for the changed claim (repeatable); omitted clears it"
50330
+ }),
50331
+ message: flag.string({ short: "m", description: "Commit message" }),
50332
+ committer: flag.string({
50333
+ description: "Committer wref (shape or shaped thing; e.g. Agent/bot-1)"
50334
+ })
50335
+ };
50336
+ var reaffirmFlags = {
50337
+ add: flag.string({
50338
+ multiple: true,
50339
+ description: "Pinned target wref to affirm (repeatable): Shape/name@vN"
50340
+ }),
50341
+ remove: flag.string({
50342
+ multiple: true,
50343
+ description: "Pinned target wref to stop affirming (repeatable)"
50344
+ }),
50345
+ "expected-version": flag.number({
50346
+ description: "only reaffirm if the assertion is still at this version (optimistic concurrency)"
50347
+ }),
50294
50348
  message: flag.string({ short: "m", description: "Commit message" }),
50295
50349
  committer: flag.string({
50296
50350
  description: "Committer wref (shape or shaped thing; e.g. Agent/bot-1)"
@@ -50322,7 +50376,8 @@ var handleRevise = async (ctx, { flags, args }) => {
50322
50376
  operation: "revise",
50323
50377
  kind: "assertion",
50324
50378
  name,
50325
- data
50379
+ data,
50380
+ ...flags.affirm && flags.affirm.length > 0 ? { affirmedTargets: flags.affirm } : {}
50326
50381
  }
50327
50382
  ], { committer: flags.committer });
50328
50383
  const result = requireSingleOpSuccess(commitResult);
@@ -50356,6 +50411,47 @@ var handleRetract = async (ctx, { flags, args }) => {
50356
50411
  ctx.out(`${ctx.colors.red}-${ctx.colors.reset} ${displayName(ctx.colors, result.name)}`);
50357
50412
  });
50358
50413
  };
50414
+ var handleReaffirm = async (ctx, { flags, args }) => {
50415
+ const name = args[0];
50416
+ const expectedVersion = parsePositiveIntFlag(flags["expected-version"], "--expected-version", "wh assertion reaffirm Belief/cave-safe --add Location/cave@v3 --expected-version 2");
50417
+ if (!name) {
50418
+ usageError("Usage: wh assertion reaffirm <wref> [--add <wref@vN>]... [--remove <wref@vN>]... [--expected-version <n>]", "wh assertion reaffirm Belief/cave-safe --add Location/cave@v3");
50419
+ }
50420
+ const add = flags.add ?? [];
50421
+ const remove = flags.remove ?? [];
50422
+ if (add.length + remove.length === 0) {
50423
+ usageError("Reaffirm requires at least one --add or --remove target", "wh assertion reaffirm Belief/cave-safe --add Location/cave@v3 --expected-version 2");
50424
+ }
50425
+ const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
50426
+ const commitResult = await ctx.client.commit.apply(org, repo, flags.message ?? `reaffirm ${name}`, [
50427
+ {
50428
+ operation: "reaffirm",
50429
+ kind: "assertion",
50430
+ name,
50431
+ ...expectedVersion !== undefined ? { expectedVersion } : {},
50432
+ ...add.length > 0 ? { add } : {},
50433
+ ...remove.length > 0 ? { remove } : {}
50434
+ }
50435
+ ], { committer: flags.committer });
50436
+ const result = requireSingleOpSuccess(commitResult);
50437
+ writeOutput(ctx, commitResult, () => {
50438
+ const c = ctx.colors;
50439
+ renderSingleOpSuccess(ctx.out, c, ctx.chars, result, {
50440
+ marker: "±",
50441
+ color: c.cyan,
50442
+ committer: flags.committer
50443
+ });
50444
+ const delta = result.affirmations;
50445
+ if (delta) {
50446
+ for (const wref of delta.added)
50447
+ ctx.out(` ${c.green}+${c.reset} ${wref}`);
50448
+ for (const wref of delta.removed)
50449
+ ctx.out(` ${c.red}-${c.reset} ${wref}`);
50450
+ for (const wref of delta.ignored)
50451
+ ctx.out(` ${c.dim}= ${wref} (no change)${c.reset}`);
50452
+ }
50453
+ });
50454
+ };
50359
50455
  var handleCreate = async (ctx, { flags, args }) => {
50360
50456
  const { org, repo } = parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
50361
50457
  const shape = flags.shape;
@@ -50370,13 +50466,15 @@ var handleCreate = async (ctx, { flags, args }) => {
50370
50466
  }
50371
50467
  const about = parseAbout(aboutRaw);
50372
50468
  const localName = `${shape}/${name}`;
50469
+ const affirmedTargets = flags.affirm ?? [];
50373
50470
  const operations = [
50374
50471
  {
50375
50472
  operation: "add",
50376
50473
  kind: "assertion",
50377
50474
  name: localName,
50378
50475
  about,
50379
- data
50476
+ data,
50477
+ ...affirmedTargets.length > 0 ? { affirmedTargets } : {}
50380
50478
  }
50381
50479
  ];
50382
50480
  const commitResult = await ctx.client.commit.apply(org, repo, message ?? `assert ${shape}`, operations, { committer });
@@ -50891,6 +50989,9 @@ function renderHead(out, c, chars, result, org, repo, shape, kind) {
50891
50989
  if (item.kind === "assertion" && item.aboutWref) {
50892
50990
  out(` ${c.dim}about:${c.reset} ${pinnedWref(c, item.aboutWref)}`);
50893
50991
  }
50992
+ if (item.affirmedWrefs?.length) {
50993
+ out(` ${c.dim}affirms:${c.reset} ${formatAffirmedWrefs(c, item.affirmedWrefs)}`);
50994
+ }
50894
50995
  const fields = shapeName && (item.kind === "thing" || item.kind === "collection") && item.data ? collectionFields(shapeName, item.data) : null;
50895
50996
  if (fields) {
50896
50997
  const allWrefs = fields.flatMap((f) => f.wrefs);
@@ -50923,6 +51024,9 @@ function renderThing(out, c, result) {
50923
51024
  if (aboutWref) {
50924
51025
  out(` ${c.dim}about:${c.reset} ${escapeTerminalTextForDisplay(String(aboutWref))}`);
50925
51026
  }
51027
+ if (result.affirmedWrefs?.length) {
51028
+ out(` ${c.dim}affirms:${c.reset} ${formatAffirmedWrefs(c, result.affirmedWrefs)}`);
51029
+ }
50926
51030
  const meta3 = result.metadata;
50927
51031
  if (meta3?.durableId || meta3?.createdOn || meta3?.revisedOn) {
50928
51032
  const now = Date.now();
@@ -51057,6 +51161,8 @@ function renderHistory(out, c, result) {
51057
51161
  } else if (ver.operation === "retract") {
51058
51162
  const reason = ver.retractReason ? ` ${c.dim}'${escapeTerminalTextForDisplay(ver.retractReason.length > 80 ? `${ver.retractReason.slice(0, 77)}...` : ver.retractReason)}'${c.reset}` : "";
51059
51163
  op = `${c.red}retract${c.reset}${reason}`;
51164
+ } else if (ver.operation === "reaffirm") {
51165
+ op = `${c.cyan}reaffirm${c.reset}`;
51060
51166
  } else {
51061
51167
  op = `${c.yellow}revise${c.reset}`;
51062
51168
  }
@@ -51067,6 +51173,10 @@ function renderHistory(out, c, result) {
51067
51173
  const createdOn = ver.metadata?.createdOn;
51068
51174
  const thingCreatedStr = createdOn ? ` ${c.dim}born:${formatTime(createdOn, now)}${c.reset}` : "";
51069
51175
  out(` ${wrefStr} ${op} ${c.dim}${time3}${c.reset}${by}${thingCreatedStr}`);
51176
+ const affirmed = ver.affirmedWrefs;
51177
+ if (Array.isArray(affirmed) && affirmed.length > 0) {
51178
+ out(` ${c.dim}affirms:${c.reset} ${formatAffirmedWrefs(c, affirmed.map(String))}`);
51179
+ }
51070
51180
  }
51071
51181
  }
51072
51182
  function renderRefs(out, c, result, wref, direction) {
@@ -51592,6 +51702,9 @@ var queryFlags = {
51592
51702
  shape: flag.string({ description: "Filter by shape" }),
51593
51703
  kind: flag.string({ description: "Filter by kind" }),
51594
51704
  about: flag.string({ description: "Filter by about wref" }),
51705
+ "affirmed-about": flag.string({
51706
+ description: "Only active assertions whose current version affirms exactly this pinned target version: Shape/name@vN"
51707
+ }),
51595
51708
  limit: flag.number({
51596
51709
  description: "Max results per page (default: 50, max: 500)"
51597
51710
  }),
@@ -51626,6 +51739,7 @@ var handleQuery = async (ctx, { flags }) => {
51626
51739
  const { org, repo } = parseOrgRepo(getRepoRef(ctx), ctx.config);
51627
51740
  const shape = flags.shape;
51628
51741
  const about = flags.about;
51742
+ const affirmedAbout = flags["affirmed-about"];
51629
51743
  const kind = validateKind(flags.kind);
51630
51744
  const limit = flags.limit;
51631
51745
  const cursor = flags.cursor;
@@ -51648,6 +51762,9 @@ var handleQuery = async (ctx, { flags }) => {
51648
51762
  if (ctx.liveMode && sinceRepoSeq !== undefined) {
51649
51763
  usageError("--since-repo-seq cannot be used with --live.", "wh thing query --since-repo-seq 42 --all --format json");
51650
51764
  }
51765
+ if (affirmedAbout && match) {
51766
+ usageError("--affirmed-about is PG-served per exact pinned version; it cannot be combined with --match.", "wh thing query --affirmed-about Location/cave@v3");
51767
+ }
51651
51768
  if (count) {
51652
51769
  if (cursor || all || limit || ctx.liveMode || role) {
51653
51770
  usageError("Usage: wh thing query --count [--shape SHAPE] [--about WREF] [--kind KIND] [--match PATTERN] [--since-repo-seq N]", "wh thing query --kind assertion --about Player/alice --count --since-repo-seq 42");
@@ -51657,6 +51774,7 @@ var handleQuery = async (ctx, { flags }) => {
51657
51774
  kind,
51658
51775
  match,
51659
51776
  about,
51777
+ affirmedAbout,
51660
51778
  includeRetracted,
51661
51779
  resolveCollections,
51662
51780
  componentRef,
@@ -51680,6 +51798,7 @@ var handleQuery = async (ctx, { flags }) => {
51680
51798
  const queryOpts = {
51681
51799
  shape,
51682
51800
  about,
51801
+ affirmedAbout,
51683
51802
  kind,
51684
51803
  match,
51685
51804
  includeRetracted,
@@ -51718,6 +51837,7 @@ var handleQuery = async (ctx, { flags }) => {
51718
51837
  const result = all ? await fetchAllQueryPages(ctx, org, repo, {
51719
51838
  shape,
51720
51839
  about,
51840
+ affirmedAbout,
51721
51841
  kind,
51722
51842
  match,
51723
51843
  includeRetracted,
@@ -51736,6 +51856,7 @@ var handleQuery = async (ctx, { flags }) => {
51736
51856
  } : undefined) : await ctx.client.thing.query(org, repo, {
51737
51857
  shape,
51738
51858
  about,
51859
+ affirmedAbout,
51739
51860
  kind,
51740
51861
  match,
51741
51862
  includeRetracted,
@@ -51767,6 +51888,7 @@ async function fetchAllQueryPages(ctx, org, repo, opts, onPage) {
51767
51888
  fetchPage: (cursor) => ctx.client.thing.query(org, repo, {
51768
51889
  shape: opts.shape,
51769
51890
  about: opts.about,
51891
+ affirmedAbout: opts.affirmedAbout,
51770
51892
  kind: opts.kind,
51771
51893
  match: opts.match,
51772
51894
  includeRetracted: opts.includeRetracted,
@@ -53007,6 +53129,17 @@ var ASSERTION_DOMAIN = defineDomain({
53007
53129
  ],
53008
53130
  handler: handleRevise
53009
53131
  },
53132
+ reaffirm: {
53133
+ prime: true,
53134
+ summary: "Edit which pinned target versions an assertion's claim is affirmed for (claim data unchanged)",
53135
+ args: "<wref>",
53136
+ flags: reaffirmFlags,
53137
+ examples: [
53138
+ "wh assertion reaffirm Belief/cave-safe --add Location/cave@v3",
53139
+ "wh assertion reaffirm Belief/cave-safe --add Location/cave@v4 --remove Location/cave@v1 --expected-version 3"
53140
+ ],
53141
+ handler: handleReaffirm
53142
+ },
53010
53143
  retract: {
53011
53144
  prime: true,
53012
53145
  summary: "Retract an assertion",
@@ -54740,7 +54873,7 @@ function renderPrettyReceipt(ctx, receipt, committer) {
54740
54873
  const record2 = operation;
54741
54874
  const operationKind = String(record2.operation ?? "operation");
54742
54875
  const failed = isFailedOpStatus(record2.status);
54743
- const marker = failed ? "!" : operationKind === "add" ? "+" : operationKind === "revise" ? "~" : "-";
54876
+ const marker = failed ? "!" : operationKind === "add" ? "+" : operationKind === "revise" ? "~" : operationKind === "reaffirm" ? "±" : "-";
54744
54877
  const error51 = typeof record2.error === "object" && record2.error !== null ? record2.error : undefined;
54745
54878
  const errorSummary = failed ? ` ${error51?.message ?? error51?.code ?? "failed"}` : "";
54746
54879
  ctx.out(` ${marker} ${displayName(c, String(record2.name ?? record2.resolvedName ?? "(unnamed)"))}${errorSummary}`);
@@ -54842,6 +54975,10 @@ var createFlags3 = {
54842
54975
  description: "Target shape or shaped thing for assertions. Repeatable; one per --add, or a single value broadcast to all.",
54843
54976
  multiple: true
54844
54977
  }),
54978
+ affirm: flag.string({
54979
+ description: "Pinned target version the assertion claim is affirmed for (repeatable): Shape/name@vN. Requires a single assertion --add or --revise.",
54980
+ multiple: true
54981
+ }),
54845
54982
  reason: flag.string({
54846
54983
  description: "Reason for retraction. Repeatable; one per --retract, or a single value broadcast to all.",
54847
54984
  multiple: true
@@ -55042,18 +55179,21 @@ var handleTemplate = async (ctx, { flags, args }) => {
55042
55179
  }
55043
55180
  const data = buildTemplateData(fields);
55044
55181
  const nameSuffix = count > 1 ? (i) => `my-${shapeName.toLowerCase()}-${i + 1}` : () => `my-${shapeName.toLowerCase()}`;
55182
+ const affirmedTargetsPlaceholder = templateKind === "assertion" ? { affirmedTargets: [] } : {};
55045
55183
  for (let i = 0;i < count; i++) {
55046
55184
  const op = operationType === "add" ? {
55047
55185
  operation: "add",
55048
55186
  kind: templateKind,
55049
55187
  name: `${shapeName}/${nameSuffix(i)}`,
55050
55188
  ...aboutPlaceholder ? { about: aboutPlaceholder } : {},
55051
- data
55189
+ data,
55190
+ ...affirmedTargetsPlaceholder
55052
55191
  } : {
55053
55192
  operation: "revise",
55054
55193
  kind: templateKind,
55055
55194
  name: `${shapeName}/FILL_IN`,
55056
- data
55195
+ data,
55196
+ ...affirmedTargetsPlaceholder
55057
55197
  };
55058
55198
  operations.push(op);
55059
55199
  }
@@ -55078,7 +55218,7 @@ var handleTemplate = async (ctx, { flags, args }) => {
55078
55218
  // ../../packages/warmhub-cli/src/domains/commit-submit-ops.ts
55079
55219
  var SHORT_FORM_MAX_ADDS = 20;
55080
55220
  function buildAddOperations(input) {
55081
- const { addNames, dataJsons, shapes, abouts, kinds } = input;
55221
+ const { addNames, dataJsons, shapes, abouts, affirms, kinds } = input;
55082
55222
  if (addNames.length > SHORT_FORM_MAX_ADDS) {
55083
55223
  throw new CliError(2 /* UserInput */, "USER_INPUT", `Short-form --add is capped at ${SHORT_FORM_MAX_ADDS} operations per write (got ${addNames.length}).`, undefined, "Use --file <path.json> or --ops '<json>' for bulk writes.");
55084
55224
  }
@@ -55096,6 +55236,9 @@ function buildAddOperations(input) {
55096
55236
  assertCardinality("--shape", shapes, { allowBroadcast: true });
55097
55237
  assertCardinality("--about", abouts, { allowBroadcast: true });
55098
55238
  assertCardinality("--kind", kinds, { allowBroadcast: true });
55239
+ if (affirms.length > 0 && addNames.length !== 1) {
55240
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `--affirm requires exactly one --add (got ${addNames.length}); the repeated values form that assertion's affirmation set.`, undefined, 'Use --file <path.json> with per-op "affirmedTargets" for multi-add writes.');
55241
+ }
55099
55242
  const pick2 = (values, i, { allowBroadcast }) => {
55100
55243
  if (values.length === 0)
55101
55244
  return;
@@ -55116,7 +55259,17 @@ function buildAddOperations(input) {
55116
55259
  }
55117
55260
  const localName = shape ? `${shape}/${addName}` : addName;
55118
55261
  const kind = kindFlag ?? (about ? "assertion" : "thing");
55119
- return { operation: "add", kind, name: localName, data, about };
55262
+ if (affirms.length > 0 && kind !== "assertion") {
55263
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `--affirm applies only to assertion adds, but --add "${addName}" resolved kind '${kind}'.`, undefined, `wh commit submit --add ${addName} --about Target/FILL_IN --data '{...}' --affirm Target/FILL_IN@v1`);
55264
+ }
55265
+ return {
55266
+ operation: "add",
55267
+ kind,
55268
+ name: localName,
55269
+ data,
55270
+ about,
55271
+ ...affirms.length > 0 ? { affirmedTargets: affirms } : {}
55272
+ };
55120
55273
  });
55121
55274
  }
55122
55275
  function buildRetractOperations(input) {
@@ -55171,6 +55324,8 @@ function synthesizeCommitMessage(operations) {
55171
55324
  if (operations.length > 1)
55172
55325
  return `batch: ${operations.length} operations`;
55173
55326
  const op = operations[0];
55327
+ if (!op)
55328
+ return;
55174
55329
  const name = op.name ?? "";
55175
55330
  if (op.operation === "revise") {
55176
55331
  return name ? `revise ${name}` : "revise";
@@ -55180,6 +55335,9 @@ function synthesizeCommitMessage(operations) {
55180
55335
  return `retract shape ${name}`;
55181
55336
  return name ? `retract ${name}` : "retract";
55182
55337
  }
55338
+ if (op.operation === "reaffirm") {
55339
+ return name ? `reaffirm ${name}` : "reaffirm";
55340
+ }
55183
55341
  const add = op;
55184
55342
  if (add.kind === "collection") {
55185
55343
  const type = add.type ?? "collection";
@@ -55203,8 +55361,8 @@ var ALLOWED_FLAGS = {
55203
55361
  "--stream": new Set,
55204
55362
  "--ops": new Set,
55205
55363
  "--file": new Set,
55206
- "--add": new Set(["data", "shape", "about", "kind"]),
55207
- "--revise": new Set(["data", "kind"]),
55364
+ "--add": new Set(["data", "shape", "about", "affirm", "kind"]),
55365
+ "--revise": new Set(["data", "affirm", "kind"]),
55208
55366
  "--retract": new Set(["reason", "kind"]),
55209
55367
  "--type": new Set(["name", "members"])
55210
55368
  };
@@ -55704,6 +55862,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
55704
55862
  const dataJsons = flags.data ?? [];
55705
55863
  const shapes = flags.shape ?? [];
55706
55864
  const abouts = flags.about ?? [];
55865
+ const affirms = flags.affirm ?? [];
55707
55866
  const reasons = flags.reason ?? [];
55708
55867
  const kinds = flags.kind ?? [];
55709
55868
  const expectedVersionExample = retractNames.length > 0 ? "wh commit submit --retract Player/alice --expected-version 3" : "wh commit submit --revise Player/alice --data '{...}' --expected-version 3";
@@ -55751,6 +55910,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
55751
55910
  data: dataJsons.length > 0,
55752
55911
  shape: shapes.length > 0,
55753
55912
  about: abouts.length > 0,
55913
+ affirm: affirms.length > 0,
55754
55914
  reason: reasons.length > 0,
55755
55915
  kind: operationKinds.length > 0,
55756
55916
  name: flags.name !== undefined,
@@ -55828,6 +55988,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
55828
55988
  dataJsons,
55829
55989
  shapes,
55830
55990
  abouts,
55991
+ affirms,
55831
55992
  kinds: operationKinds
55832
55993
  });
55833
55994
  } else if (operationSource === "--retract") {
@@ -55849,12 +56010,16 @@ var handleSubmit = async (ctx, { flags, args }) => {
55849
56010
  const data = rawData !== undefined ? parseJsonObject(rawData, "--data") : undefined;
55850
56011
  const kindFlag = operationKinds[0];
55851
56012
  const kind = kindFlag ?? "thing";
56013
+ if (affirms.length > 0 && kind !== "assertion") {
56014
+ throw new CliError(2 /* UserInput */, "USER_INPUT", `--affirm applies only to assertion revises, but --revise resolved kind '${kind}'.`, undefined, `wh commit submit --revise ${reviseName} --kind assertion --data '{...}' --affirm Location/cave@v3`);
56015
+ }
55852
56016
  operations = [
55853
56017
  {
55854
56018
  operation: "revise",
55855
56019
  kind,
55856
56020
  name: reviseName,
55857
56021
  data,
56022
+ ...affirms.length > 0 ? { affirmedTargets: affirms } : {},
55858
56023
  ...expectedVersion !== undefined ? { expectedVersion } : {},
55859
56024
  ...leaseIdFlag ? { leaseId: leaseIdFlag } : {}
55860
56025
  }
@@ -58922,6 +59087,9 @@ var createFlags5 = {
58922
59087
  coverage: flag.string({
58923
59088
  description: "inline coverage JSON ({include, exclude?})"
58924
59089
  }),
59090
+ view: flag.string({
59091
+ description: "View backing coverage instead (View/NAME or View/NAME@vN)"
59092
+ }),
58925
59093
  op: flag.string({
58926
59094
  description: "operation to grant (repeatable)",
58927
59095
  multiple: true
@@ -58937,31 +59105,51 @@ var revokeFlags2 = {
58937
59105
  function repo(ctx) {
58938
59106
  return parseOrgRepo(getRepoRef(ctx), ctx.config);
58939
59107
  }
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/**"]}'`);
59108
+ var CREATE_USAGE = "Usage: wh grant create <member EMAIL | pat NAME | component ORG/NAME> --key KEY --op OP [--op OP] (--coverage JSON | --view View/NAME[@vN])";
59109
+ var CREATE_EXAMPLE = `wh grant create component acme/indexer --key provision --op things:read --coverage '{"include":["Lesson/**"]}'`;
59110
+ function parseRecipient(kind, name) {
59111
+ switch (kind) {
59112
+ case "member":
59113
+ return { kind: "member", email: name };
59114
+ case "pat":
59115
+ return { kind: "pat", name };
59116
+ case "component":
59117
+ return {
59118
+ kind: "component",
59119
+ ...resolveRegisteredComponentRef(name, CREATE_USAGE, CREATE_EXAMPLE)
59120
+ };
59121
+ default:
59122
+ usageError("Grant recipient kind must be member, pat, or component.", CREATE_EXAMPLE);
58944
59123
  }
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/**"]}'`);
59124
+ }
59125
+ function isPatternList(value) {
59126
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string" && entry.length > 0);
59127
+ }
59128
+ function parseCoverage(raw) {
59129
+ const candidate = parseJsonObject(raw, "--coverage");
59130
+ if (!isPatternList(candidate.include) || candidate.include.length === 0) {
59131
+ usageError("--coverage must be an object with a non-empty include array of patterns ({include, exclude?}).", CREATE_EXAMPLE);
58947
59132
  }
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/**"]}'`);
59133
+ if (candidate.exclude !== undefined && !isPatternList(candidate.exclude)) {
59134
+ usageError("--coverage exclude must be an array of patterns when present.", CREATE_EXAMPLE);
58950
59135
  }
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/**"]}'`);
59136
+ return candidate;
59137
+ }
59138
+ var handleCreate4 = async (ctx, { args, flags }) => {
59139
+ const [recipientKind, recipientName] = args;
59140
+ if (!recipientKind || !recipientName || !flags.key || !flags.op?.length) {
59141
+ usageError(CREATE_USAGE, CREATE_EXAMPLE);
59142
+ }
59143
+ if (flags.coverage && flags.view) {
59144
+ usageError("Grant create takes --coverage or --view, not both.", CREATE_EXAMPLE);
58956
59145
  }
59146
+ const recipient = parseRecipient(recipientKind, recipientName);
58957
59147
  const { org, repo: repoName } = repo(ctx);
59148
+ const source = flags.coverage ? { coverage: parseCoverage(flags.coverage) } : flags.view ? { viewRef: flags.view } : usageError("Grant create requires --coverage or --view.", CREATE_EXAMPLE);
58958
59149
  const result = await ctx.client.grant.create(org, repoName, {
58959
59150
  idempotencyKey: flags.key,
58960
- grantee: {
58961
- principalId,
58962
- principalKind
58963
- },
58964
- coverage,
59151
+ recipient,
59152
+ ...source,
58965
59153
  ops: flags.op
58966
59154
  });
58967
59155
  writeOutput(ctx, result, () => ctx.out(JSON.stringify(result, null, 2)));
@@ -58977,7 +59165,7 @@ var handleGet = async (ctx, { args }) => {
58977
59165
  };
58978
59166
  var handleList4 = async (ctx, { flags }) => {
58979
59167
  const { org, repo: repoName } = repo(ctx);
58980
- const limit = Math.min(flags.limit ?? 50, 100);
59168
+ const limit = Math.min(parsePositiveIntFlag(flags.limit, "--limit", "wh grant list --limit 25") ?? 50, 100);
58981
59169
  const result = await ctx.client.grant.list(org, repoName, {
58982
59170
  limit,
58983
59171
  cursor: flags.cursor
@@ -59003,7 +59191,7 @@ var GRANT_DOMAIN = defineDomain({
59003
59191
  create: {
59004
59192
  prime: true,
59005
59193
  summary: "Create or replay an issuer-scoped Grant request",
59006
- args: "<member|pat|component> <principal-id>",
59194
+ args: "<member|pat|component> <email|token-name|org/name>",
59007
59195
  flags: createFlags5,
59008
59196
  handler: handleCreate4
59009
59197
  },
@@ -61063,7 +61251,7 @@ var CHECKPOINT_ID_EXAMPLE = "0198f6d5-78aa-7000-8000-000000000001";
61063
61251
  var CHECKPOINT_ACCESS_EXAMPLE = "wh repo checkpoint access acme/widgets --latest --archive";
61064
61252
  var CHECKPOINT_DOWNLOAD_EXAMPLE = "wh repo checkpoint download acme/widgets --latest --archive --output checkpoint.zip";
61065
61253
  var CHECKPOINT_READ_NOTE = "Requires unrestricted repo:read plus repo:checkpoint-read.";
61066
- var CHECKPOINT_MANAGEMENT_NOTE = "Requires unrestricted repo:read, repo:checkpoint-read, and repo:admin.";
61254
+ var CHECKPOINT_MANAGEMENT_NOTE = "Requires unrestricted repo:read, repo:checkpoint-read, and repo:checkpoint-generate (or repo:admin for compatibility).";
61067
61255
  var generateFlags = {
61068
61256
  "at-least-repo-seq": checkpointFlags["at-least-repo-seq"],
61069
61257
  wait: checkpointFlags.wait
@@ -66200,7 +66388,7 @@ function resolveLogLevel(flagLevel, env) {
66200
66388
  // package.json
66201
66389
  var package_default3 = {
66202
66390
  name: "@warmhub/cli",
66203
- version: "0.89.0",
66391
+ version: "0.91.0",
66204
66392
  private: false,
66205
66393
  type: "module",
66206
66394
  description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -66819,5 +67007,5 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
66819
67007
  version: package_default3.version
66820
67008
  }) : interceptedExitCode;
66821
67009
 
66822
- //# debugId=0D9B1F5B8E62352264756E2164756E21
66823
- //# warmhub-cli-build-info {"cliVersion":"0.89.0","sdkVersion":"0.87.0"}
67010
+ //# debugId=B83F4BF04D38984164756E2164756E21
67011
+ //# warmhub-cli-build-info {"cliVersion":"0.91.0","sdkVersion":"0.89.0"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warmhub/cli",
3
- "version": "0.89.0",
3
+ "version": "0.91.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",