@volter/world-core 3.0.57 → 3.0.59

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.
@@ -407,6 +407,8 @@ export type ScreenDecl = {
407
407
  export type PerformHookArgs = {
408
408
  execute: import('./remote-execute.js').RemoteExecute;
409
409
  group: import('./actions.js').TwinAction[];
410
+ /** Recorded local effects before root reference translation, for local blob ownership. */
411
+ localGroup: import('./actions.js').TwinAction[];
410
412
  input: Record<string, unknown>;
411
413
  ctx: import('./head.js').PerformContext;
412
414
  send: (input: Record<string, unknown>) => Promise<import('./head.js').PushOutcome>;
@@ -468,7 +468,7 @@ function performOf(units) {
468
468
  if (!hook || !unit)
469
469
  return derived(execute, group, ctx, input);
470
470
  return hook({
471
- execute, group, input, ctx,
471
+ execute, group, localGroup: ctx.localGroup ?? group, input, ctx,
472
472
  send: (changed) => derived(execute, group, ctx, changed),
473
473
  resolve: (type, localId) => ctx.resolve(type, localId),
474
474
  basePath: unit.surface.basePath ?? '',
@@ -29,6 +29,7 @@ export type PerformContext = {
29
29
  service?: string;
30
30
  root?: string;
31
31
  credential?: string;
32
+ localGroup?: TwinAction[];
32
33
  };
33
34
  /** One request's entries (a group: they share its `correlationId`), performed as the one call that made them. */
34
35
  export type PerformAction = (execute: RemoteExecute, group: TwinAction[], ctx: PerformContext) => Promise<PushOutcome>;
package/dist/src/head.js CHANGED
@@ -401,7 +401,7 @@ async function performNow(opts) {
401
401
  const aliases = aliasesFrom(parentEntries(service, root));
402
402
  const resolved = group.map((action) => { const fields = resolveReferences(service, action.subject.type, action.fields ?? {}, aliases); return fields === action.fields ? action : { ...action, fields }; });
403
403
  try {
404
- const outcome = await adapters.perform(execute, resolved, performContext(service, root, bound.sealed ? rootCredentialFingerprint(bound.sealed) : undefined));
404
+ const outcome = await adapters.perform(execute, resolved, { ...performContext(service, root, bound.sealed ? rootCredentialFingerprint(bound.sealed) : undefined), localGroup: group });
405
405
  // the vendor's answer, when the adapter returned one as fields, is what the primary entry's landed copy holds
406
406
  const answered = outcome.data !== null && typeof outcome.data === 'object' && !Array.isArray(outcome.data) ? outcome.data : {};
407
407
  const primary = resolved.find((a) => a.id === outcome.actionId) ?? resolved[0];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/world-core",
3
- "version": "3.0.57",
3
+ "version": "3.0.59",
4
4
  "description": "The kernel of Volter World: one log per twin, branches as pointers, checkpoints, the fold that keeps a twin current, the head that performs a write against the vendor, references, and the git plane. A twin package builds on it; the runtime serves it.",
5
5
  "keywords": [
6
6
  "twin",
@@ -305,6 +305,8 @@ export type ScreenDecl = {
305
305
  export type PerformHookArgs = {
306
306
  execute: import('./remote-execute.ts').RemoteExecute;
307
307
  group: import('./actions.ts').TwinAction[];
308
+ /** Recorded local effects before root reference translation, for local blob ownership. */
309
+ localGroup: import('./actions.ts').TwinAction[];
308
310
  input: Record<string, unknown>;
309
311
  ctx: import('./head.ts').PerformContext;
310
312
  send: (input: Record<string, unknown>) => Promise<import('./head.ts').PushOutcome>;
@@ -396,7 +396,7 @@ function performOf(units: Unit[]): PerformAction {
396
396
  const hook = unit && typeof input.operationId === 'string' ? unit.manifest.performs?.[input.operationId] : undefined;
397
397
  if (!hook || !unit) return derived(execute, group, ctx, input);
398
398
  return hook({
399
- execute, group, input, ctx,
399
+ execute, group, localGroup: ctx.localGroup ?? group, input, ctx,
400
400
  send: (changed) => derived(execute, group, ctx, changed),
401
401
  resolve: (type, localId) => ctx.resolve(type, localId),
402
402
  basePath: unit.surface.basePath ?? '',
package/src/head.ts CHANGED
@@ -39,7 +39,7 @@ export type PushOutcome = {
39
39
  * vault's transit hmac at a pinned key version,
40
40
  * never the secret and no offline oracle for it), so a pack keys its budget ledger per real credential:
41
41
  * every World and branch performing with one vendor key then shares that key's one allowance. */
42
- export type PerformContext = { resolve: (type: string, localId: string) => string; service?: string; root?: string; credential?: string };
42
+ export type PerformContext = { resolve: (type: string, localId: string) => string; service?: string; root?: string; credential?: string; localGroup?: TwinAction[] };
43
43
  /** One request's entries (a group: they share its `correlationId`), performed as the one call that made them. */
44
44
  export type PerformAction = (execute: RemoteExecute, group: TwinAction[], ctx: PerformContext) => Promise<PushOutcome>;
45
45
  export function performContext(service: string, root?: string, credential?: string): PerformContext {
@@ -406,7 +406,7 @@ async function performNow(opts: Parameters<typeof performEntries>[0]): Promise<D
406
406
  const aliases = aliasesFrom(parentEntries(service, root));
407
407
  const resolved = group.map((action) => { const fields = resolveReferences(service, action.subject.type, action.fields ?? {}, aliases); return fields === action.fields ? action : { ...action, fields }; });
408
408
  try {
409
- const outcome = await adapters.perform(execute, resolved, performContext(service, root, bound.sealed ? rootCredentialFingerprint(bound.sealed) : undefined));
409
+ const outcome = await adapters.perform(execute, resolved, { ...performContext(service, root, bound.sealed ? rootCredentialFingerprint(bound.sealed) : undefined), localGroup: group });
410
410
  // the vendor's answer, when the adapter returned one as fields, is what the primary entry's landed copy holds
411
411
  const answered = outcome.data !== null && typeof outcome.data === 'object' && !Array.isArray(outcome.data) ? (outcome.data as Record<string, unknown>) : {};
412
412
  const primary = resolved.find((a) => a.id === outcome.actionId) ?? resolved[0]!;