@iamu-dev/iamu 0.8.0-beta.6 → 0.8.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js CHANGED
@@ -6685,6 +6685,9 @@ var init_wire_compat = __esm({
6685
6685
  });
6686
6686
 
6687
6687
  // ../../packages/local-store/dist/sync/server-meta.js
6688
+ function cloudDistinguishesHumanEdits(capabilities) {
6689
+ return Boolean(capabilities?.includes(SYNC_TOKEN_CAPABILITY));
6690
+ }
6688
6691
  function cloudSupportsGuidance(capabilities) {
6689
6692
  return Boolean(capabilities?.includes(GUIDANCE_CAPABILITY) || capabilities?.includes(DESIGNER_FINDINGS_CAPABILITY));
6690
6693
  }
@@ -6753,7 +6756,7 @@ function shapeForServer(pending, capabilities) {
6753
6756
  }
6754
6757
  return { pending: out2, heldDesigner };
6755
6758
  }
6756
- var DESIGNER_FINDINGS_CAPABILITY, GUIDANCE_CAPABILITY, WALKTHROUGH_DELETE_CAPABILITY, FINDING_PROVENANCE_CAPABILITY, BUNDLE_FINDING_HASH_CAPABILITY, RUN_BLOCKED_CAPABILITY;
6759
+ var DESIGNER_FINDINGS_CAPABILITY, GUIDANCE_CAPABILITY, WALKTHROUGH_DELETE_CAPABILITY, FINDING_PROVENANCE_CAPABILITY, BUNDLE_FINDING_HASH_CAPABILITY, RUN_BLOCKED_CAPABILITY, SYNC_TOKEN_CAPABILITY;
6757
6760
  var init_server_meta = __esm({
6758
6761
  "../../packages/local-store/dist/sync/server-meta.js"() {
6759
6762
  "use strict";
@@ -6765,6 +6768,7 @@ var init_server_meta = __esm({
6765
6768
  FINDING_PROVENANCE_CAPABILITY = "finding-provenance";
6766
6769
  BUNDLE_FINDING_HASH_CAPABILITY = "bundle-finding-hash";
6767
6770
  RUN_BLOCKED_CAPABILITY = "run-blocked";
6771
+ SYNC_TOKEN_CAPABILITY = "sync-token";
6768
6772
  }
6769
6773
  });
6770
6774
 
@@ -14281,6 +14285,18 @@ async function pushOneBatch(target, batch, byType, label, opts = {}) {
14281
14285
  out2.errors.push(failure.message);
14282
14286
  return out2;
14283
14287
  }
14288
+ function cloudTokenOrigin(hash, humanTokens) {
14289
+ if (hash.startsWith("cloud-sync-"))
14290
+ return "projection";
14291
+ if (hash.startsWith("cloud-"))
14292
+ return humanTokens ? "person" : "unknown";
14293
+ if (hash.startsWith("cloud:"))
14294
+ return "unknown";
14295
+ return null;
14296
+ }
14297
+ function isCloudToken(hash) {
14298
+ return cloudTokenOrigin(hash, false) !== null;
14299
+ }
14284
14300
  async function ownEarlierWrites(projectRoot, batch, conflicts) {
14285
14301
  if (conflicts.length === 0)
14286
14302
  return [];
@@ -14294,7 +14310,7 @@ async function ownEarlierWrites(projectRoot, batch, conflicts) {
14294
14310
  const entity = byId.get(c.entity_id);
14295
14311
  if (!entity || c.base_hash || bases[c.entity_id])
14296
14312
  continue;
14297
- if (!c.cloud_hash || c.cloud_hash.startsWith("cloud:"))
14313
+ if (!c.cloud_hash || isCloudToken(c.cloud_hash))
14298
14314
  continue;
14299
14315
  if (!sent[c.entity_id]?.includes(c.cloud_hash))
14300
14316
  continue;
@@ -14303,45 +14319,54 @@ async function ownEarlierWrites(projectRoot, batch, conflicts) {
14303
14319
  }
14304
14320
  return out2;
14305
14321
  }
14306
- function findingRun(frontmatter) {
14322
+ function findingRuns(frontmatter) {
14323
+ const out2 = /* @__PURE__ */ new Set();
14307
14324
  if (typeof frontmatter.run === "string" && frontmatter.run) {
14308
- return frontmatter.run;
14325
+ out2.add(frontmatter.run);
14309
14326
  }
14310
14327
  const seen = frontmatter.seen_in;
14311
- if (typeof seen !== "string")
14312
- return null;
14313
- const i = seen.indexOf(":");
14314
- return i >= 0 ? seen.slice(i + 1) : seen;
14328
+ if (typeof seen === "string") {
14329
+ const m = /^(?:ux|designer):(.+)$/.exec(seen);
14330
+ if (m?.[1])
14331
+ out2.add(m[1]);
14332
+ }
14333
+ return out2;
14315
14334
  }
14316
- async function rowsFromOwnBundles(projectRoot, batch, conflicts, adopt) {
14317
- if (!adopt || adopt.runs.size === 0 || conflicts.length === 0)
14335
+ async function rowsToAdopt(projectRoot, batch, conflicts, adopt) {
14336
+ if (!adopt || conflicts.length === 0)
14318
14337
  return [];
14319
14338
  const bases = await readBaseHashes(projectRoot);
14320
14339
  const byId = new Map(batch.map((e) => [e.id, e]));
14321
14340
  const out2 = [];
14322
14341
  for (const c of conflicts) {
14323
14342
  const entity = byId.get(c.entity_id);
14324
- if (!entity || entity.type !== "finding")
14325
- continue;
14326
- if (!c.cloud_hash?.startsWith("cloud:"))
14343
+ if (!entity || entity.type !== "finding" || !c.cloud_hash)
14327
14344
  continue;
14328
- const run = findingRun(entity.frontmatter);
14329
- if (!run || !adopt.runs.has(run))
14345
+ const origin = cloudTokenOrigin(c.cloud_hash, adopt.humanTokens);
14346
+ if (origin === null || origin === "person")
14330
14347
  continue;
14331
- const at = c.cloud_updated_at ? Date.parse(c.cloud_updated_at) : Number.NaN;
14332
- const slack = adopt.serverClock ? ADOPT_CLOCK_SLACK_MS : 0;
14333
- if (Number.isNaN(at) || at < adopt.since - slack)
14334
- continue;
14335
- if (adopt.identity && c.cloud_changed_by !== adopt.identity)
14348
+ if (origin === "unknown" && !stampedByThisPass(c, entity, adopt)) {
14336
14349
  continue;
14350
+ }
14337
14351
  await recordCloudBase(projectRoot, c.entity_id, c.cloud_hash);
14338
- out2.push({
14352
+ out2.push(origin === "projection" ? { entity, restamped: false, kind: "projection" } : {
14339
14353
  entity,
14340
- restamped: Boolean(c.base_hash || bases[c.entity_id])
14354
+ restamped: Boolean(c.base_hash || bases[c.entity_id]),
14355
+ kind: "bundle"
14341
14356
  });
14342
14357
  }
14343
14358
  return out2;
14344
14359
  }
14360
+ function stampedByThisPass(c, entity, adopt) {
14361
+ const runs = findingRuns(entity.frontmatter);
14362
+ if (![...runs].some((r) => adopt.runs.has(r)))
14363
+ return false;
14364
+ const at = c.cloud_updated_at ? Date.parse(c.cloud_updated_at) : Number.NaN;
14365
+ const slack = adopt.serverClock ? ADOPT_CLOCK_SLACK_MS : 0;
14366
+ if (Number.isNaN(at) || at < adopt.since - slack)
14367
+ return false;
14368
+ return !adopt.identity || c.cloud_changed_by === adopt.identity;
14369
+ }
14345
14370
  async function pushBatches(target, batches, byType, opts = {}) {
14346
14371
  let pushed = 0;
14347
14372
  let enqueued = 0;
@@ -14377,7 +14402,7 @@ async function pushBatches(target, batches, byType, opts = {}) {
14377
14402
  const own = await ownEarlierWrites(target.projectRoot, batch, unresolved);
14378
14403
  const ownIds = new Set(own.map((e) => e.id));
14379
14404
  const basesBefore = opts.adopt ? await readCloudBase(target.projectRoot) : {};
14380
- const fromBundles = await rowsFromOwnBundles(target.projectRoot, batch, unresolved.filter((c) => !ownIds.has(c.entity_id)), opts.adopt);
14405
+ const fromBundles = await rowsToAdopt(target.projectRoot, batch, unresolved.filter((c) => !ownIds.has(c.entity_id)), opts.adopt);
14381
14406
  const resend = [...own, ...fromBundles.map((a) => a.entity)];
14382
14407
  if (resend.length > 0) {
14383
14408
  const resendIds = new Set(resend.map((e) => e.id));
@@ -14391,6 +14416,7 @@ async function pushBatches(target, batches, byType, opts = {}) {
14391
14416
  if (landed2.has(a.entity.id)) {
14392
14417
  adopted.push({
14393
14418
  slug: a.entity.slug,
14419
+ kind: a.kind,
14394
14420
  restamped: a.restamped,
14395
14421
  serverClock: opts.adopt?.serverClock ?? false
14396
14422
  });
@@ -15118,6 +15144,7 @@ async function runSync(projectRoot, deps) {
15118
15144
  runs: /* @__PURE__ */ new Set([...drainedRuns, ...runs]),
15119
15145
  since: startedAt + (serverClockOffsetMs ?? 0),
15120
15146
  serverClock: serverClockOffsetMs !== null,
15147
+ humanTokens: cloudDistinguishesHumanEdits(capabilities),
15121
15148
  identity: deps.identity ?? null
15122
15149
  });
15123
15150
  const scanned = await scanPending(projectRoot);
@@ -15187,6 +15214,10 @@ async function runSync(projectRoot, deps) {
15187
15214
  progress.errors.push(...deletion.errors);
15188
15215
  notices.push(...deletion.notices);
15189
15216
  for (const a of progress.adopted) {
15217
+ if (a.kind === "projection") {
15218
+ notices.push(`${a.slug}: kept the local version over the cloud's projected triage (automated, from a run's outcome)`);
15219
+ continue;
15220
+ }
15190
15221
  const what = a.restamped ? "overwrote the cloud row re-stamped during this sync (its version token came from this sync's own bundle of the finding's run)" : "overwrote the cloud row stamped during this sync (its version token came from this sync's own bundle)";
15191
15222
  const clock = a.serverClock ? "" : "; the server sent no clock, so only rows stamped after this sync began by this machine's clock counted";
15192
15223
  notices.push(`${a.slug}: ${what}${clock}`);
@@ -25077,8 +25108,8 @@ import { dirname as dirname3, join as join5, relative, resolve as resolve2 } fro
25077
25108
  import { fileURLToPath as fileURLToPath2 } from "url";
25078
25109
  import chalk6 from "chalk";
25079
25110
  function getVersion() {
25080
- if ("0.8.0-beta.6") {
25081
- return "0.8.0-beta.6";
25111
+ if ("0.8.0-beta.7") {
25112
+ return "0.8.0-beta.7";
25082
25113
  }
25083
25114
  try {
25084
25115
  const thisDir = dirname3(fileURLToPath2(import.meta.url));
@@ -1 +1 @@
1
- f5e575f9a571d24c34c77773c0feb71a627d2be39209a2124310486e49cd2bdf
1
+ 59403743808ddbd9b8b8b6dd935e183ee7c9040c9405d2f1deabed46c09ea324
package/dist/index.js CHANGED
@@ -6684,6 +6684,9 @@ var init_wire_compat = __esm({
6684
6684
  });
6685
6685
 
6686
6686
  // ../../packages/local-store/dist/sync/server-meta.js
6687
+ function cloudDistinguishesHumanEdits(capabilities) {
6688
+ return Boolean(capabilities?.includes(SYNC_TOKEN_CAPABILITY));
6689
+ }
6687
6690
  function cloudSupportsGuidance(capabilities) {
6688
6691
  return Boolean(capabilities?.includes(GUIDANCE_CAPABILITY) || capabilities?.includes(DESIGNER_FINDINGS_CAPABILITY));
6689
6692
  }
@@ -6752,7 +6755,7 @@ function shapeForServer(pending, capabilities) {
6752
6755
  }
6753
6756
  return { pending: out2, heldDesigner };
6754
6757
  }
6755
- var DESIGNER_FINDINGS_CAPABILITY, GUIDANCE_CAPABILITY, WALKTHROUGH_DELETE_CAPABILITY, FINDING_PROVENANCE_CAPABILITY, BUNDLE_FINDING_HASH_CAPABILITY, RUN_BLOCKED_CAPABILITY;
6758
+ var DESIGNER_FINDINGS_CAPABILITY, GUIDANCE_CAPABILITY, WALKTHROUGH_DELETE_CAPABILITY, FINDING_PROVENANCE_CAPABILITY, BUNDLE_FINDING_HASH_CAPABILITY, RUN_BLOCKED_CAPABILITY, SYNC_TOKEN_CAPABILITY;
6756
6759
  var init_server_meta = __esm({
6757
6760
  "../../packages/local-store/dist/sync/server-meta.js"() {
6758
6761
  "use strict";
@@ -6764,6 +6767,7 @@ var init_server_meta = __esm({
6764
6767
  FINDING_PROVENANCE_CAPABILITY = "finding-provenance";
6765
6768
  BUNDLE_FINDING_HASH_CAPABILITY = "bundle-finding-hash";
6766
6769
  RUN_BLOCKED_CAPABILITY = "run-blocked";
6770
+ SYNC_TOKEN_CAPABILITY = "sync-token";
6767
6771
  }
6768
6772
  });
6769
6773
 
@@ -14280,6 +14284,18 @@ async function pushOneBatch(target, batch, byType, label, opts = {}) {
14280
14284
  out2.errors.push(failure.message);
14281
14285
  return out2;
14282
14286
  }
14287
+ function cloudTokenOrigin(hash, humanTokens) {
14288
+ if (hash.startsWith("cloud-sync-"))
14289
+ return "projection";
14290
+ if (hash.startsWith("cloud-"))
14291
+ return humanTokens ? "person" : "unknown";
14292
+ if (hash.startsWith("cloud:"))
14293
+ return "unknown";
14294
+ return null;
14295
+ }
14296
+ function isCloudToken(hash) {
14297
+ return cloudTokenOrigin(hash, false) !== null;
14298
+ }
14283
14299
  async function ownEarlierWrites(projectRoot, batch, conflicts) {
14284
14300
  if (conflicts.length === 0)
14285
14301
  return [];
@@ -14293,7 +14309,7 @@ async function ownEarlierWrites(projectRoot, batch, conflicts) {
14293
14309
  const entity = byId.get(c.entity_id);
14294
14310
  if (!entity || c.base_hash || bases[c.entity_id])
14295
14311
  continue;
14296
- if (!c.cloud_hash || c.cloud_hash.startsWith("cloud:"))
14312
+ if (!c.cloud_hash || isCloudToken(c.cloud_hash))
14297
14313
  continue;
14298
14314
  if (!sent[c.entity_id]?.includes(c.cloud_hash))
14299
14315
  continue;
@@ -14302,45 +14318,54 @@ async function ownEarlierWrites(projectRoot, batch, conflicts) {
14302
14318
  }
14303
14319
  return out2;
14304
14320
  }
14305
- function findingRun(frontmatter) {
14321
+ function findingRuns(frontmatter) {
14322
+ const out2 = /* @__PURE__ */ new Set();
14306
14323
  if (typeof frontmatter.run === "string" && frontmatter.run) {
14307
- return frontmatter.run;
14324
+ out2.add(frontmatter.run);
14308
14325
  }
14309
14326
  const seen = frontmatter.seen_in;
14310
- if (typeof seen !== "string")
14311
- return null;
14312
- const i = seen.indexOf(":");
14313
- return i >= 0 ? seen.slice(i + 1) : seen;
14327
+ if (typeof seen === "string") {
14328
+ const m = /^(?:ux|designer):(.+)$/.exec(seen);
14329
+ if (m?.[1])
14330
+ out2.add(m[1]);
14331
+ }
14332
+ return out2;
14314
14333
  }
14315
- async function rowsFromOwnBundles(projectRoot, batch, conflicts, adopt) {
14316
- if (!adopt || adopt.runs.size === 0 || conflicts.length === 0)
14334
+ async function rowsToAdopt(projectRoot, batch, conflicts, adopt) {
14335
+ if (!adopt || conflicts.length === 0)
14317
14336
  return [];
14318
14337
  const bases = await readBaseHashes(projectRoot);
14319
14338
  const byId = new Map(batch.map((e) => [e.id, e]));
14320
14339
  const out2 = [];
14321
14340
  for (const c of conflicts) {
14322
14341
  const entity = byId.get(c.entity_id);
14323
- if (!entity || entity.type !== "finding")
14324
- continue;
14325
- if (!c.cloud_hash?.startsWith("cloud:"))
14342
+ if (!entity || entity.type !== "finding" || !c.cloud_hash)
14326
14343
  continue;
14327
- const run = findingRun(entity.frontmatter);
14328
- if (!run || !adopt.runs.has(run))
14344
+ const origin = cloudTokenOrigin(c.cloud_hash, adopt.humanTokens);
14345
+ if (origin === null || origin === "person")
14329
14346
  continue;
14330
- const at = c.cloud_updated_at ? Date.parse(c.cloud_updated_at) : Number.NaN;
14331
- const slack = adopt.serverClock ? ADOPT_CLOCK_SLACK_MS : 0;
14332
- if (Number.isNaN(at) || at < adopt.since - slack)
14333
- continue;
14334
- if (adopt.identity && c.cloud_changed_by !== adopt.identity)
14347
+ if (origin === "unknown" && !stampedByThisPass(c, entity, adopt)) {
14335
14348
  continue;
14349
+ }
14336
14350
  await recordCloudBase(projectRoot, c.entity_id, c.cloud_hash);
14337
- out2.push({
14351
+ out2.push(origin === "projection" ? { entity, restamped: false, kind: "projection" } : {
14338
14352
  entity,
14339
- restamped: Boolean(c.base_hash || bases[c.entity_id])
14353
+ restamped: Boolean(c.base_hash || bases[c.entity_id]),
14354
+ kind: "bundle"
14340
14355
  });
14341
14356
  }
14342
14357
  return out2;
14343
14358
  }
14359
+ function stampedByThisPass(c, entity, adopt) {
14360
+ const runs = findingRuns(entity.frontmatter);
14361
+ if (![...runs].some((r) => adopt.runs.has(r)))
14362
+ return false;
14363
+ const at = c.cloud_updated_at ? Date.parse(c.cloud_updated_at) : Number.NaN;
14364
+ const slack = adopt.serverClock ? ADOPT_CLOCK_SLACK_MS : 0;
14365
+ if (Number.isNaN(at) || at < adopt.since - slack)
14366
+ return false;
14367
+ return !adopt.identity || c.cloud_changed_by === adopt.identity;
14368
+ }
14344
14369
  async function pushBatches(target, batches, byType, opts = {}) {
14345
14370
  let pushed = 0;
14346
14371
  let enqueued = 0;
@@ -14376,7 +14401,7 @@ async function pushBatches(target, batches, byType, opts = {}) {
14376
14401
  const own = await ownEarlierWrites(target.projectRoot, batch, unresolved);
14377
14402
  const ownIds = new Set(own.map((e) => e.id));
14378
14403
  const basesBefore = opts.adopt ? await readCloudBase(target.projectRoot) : {};
14379
- const fromBundles = await rowsFromOwnBundles(target.projectRoot, batch, unresolved.filter((c) => !ownIds.has(c.entity_id)), opts.adopt);
14404
+ const fromBundles = await rowsToAdopt(target.projectRoot, batch, unresolved.filter((c) => !ownIds.has(c.entity_id)), opts.adopt);
14380
14405
  const resend = [...own, ...fromBundles.map((a) => a.entity)];
14381
14406
  if (resend.length > 0) {
14382
14407
  const resendIds = new Set(resend.map((e) => e.id));
@@ -14390,6 +14415,7 @@ async function pushBatches(target, batches, byType, opts = {}) {
14390
14415
  if (landed2.has(a.entity.id)) {
14391
14416
  adopted.push({
14392
14417
  slug: a.entity.slug,
14418
+ kind: a.kind,
14393
14419
  restamped: a.restamped,
14394
14420
  serverClock: opts.adopt?.serverClock ?? false
14395
14421
  });
@@ -15117,6 +15143,7 @@ async function runSync(projectRoot, deps) {
15117
15143
  runs: /* @__PURE__ */ new Set([...drainedRuns, ...runs]),
15118
15144
  since: startedAt + (serverClockOffsetMs ?? 0),
15119
15145
  serverClock: serverClockOffsetMs !== null,
15146
+ humanTokens: cloudDistinguishesHumanEdits(capabilities),
15120
15147
  identity: deps.identity ?? null
15121
15148
  });
15122
15149
  const scanned = await scanPending(projectRoot);
@@ -15186,6 +15213,10 @@ async function runSync(projectRoot, deps) {
15186
15213
  progress.errors.push(...deletion.errors);
15187
15214
  notices.push(...deletion.notices);
15188
15215
  for (const a of progress.adopted) {
15216
+ if (a.kind === "projection") {
15217
+ notices.push(`${a.slug}: kept the local version over the cloud's projected triage (automated, from a run's outcome)`);
15218
+ continue;
15219
+ }
15189
15220
  const what = a.restamped ? "overwrote the cloud row re-stamped during this sync (its version token came from this sync's own bundle of the finding's run)" : "overwrote the cloud row stamped during this sync (its version token came from this sync's own bundle)";
15190
15221
  const clock = a.serverClock ? "" : "; the server sent no clock, so only rows stamped after this sync began by this machine's clock counted";
15191
15222
  notices.push(`${a.slug}: ${what}${clock}`);
@@ -25076,8 +25107,8 @@ import { dirname as dirname3, join as join5, relative, resolve as resolve2 } fro
25076
25107
  import { fileURLToPath as fileURLToPath2 } from "url";
25077
25108
  import chalk6 from "chalk";
25078
25109
  function getVersion() {
25079
- if ("0.8.0-beta.6") {
25080
- return "0.8.0-beta.6";
25110
+ if ("0.8.0-beta.7") {
25111
+ return "0.8.0-beta.7";
25081
25112
  }
25082
25113
  try {
25083
25114
  const thisDir = dirname3(fileURLToPath2(import.meta.url));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iamu-dev/iamu",
3
- "version": "0.8.0-beta.6",
3
+ "version": "0.8.0-beta.7",
4
4
  "type": "module",
5
5
  "description": "Test your product as realistic personas — scenario-driven development CLI",
6
6
  "license": "MIT",