@hasna/skills 0.10.54 → 0.10.55
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/bin/index.js +40 -5
- package/bin/mcp.js +1 -1
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.js +24 -2
- package/dist/lib/session-reconciliation.d.ts +23 -0
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +24 -2
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -36888,7 +36888,7 @@ var package_default;
|
|
|
36888
36888
|
var init_package = __esm(() => {
|
|
36889
36889
|
package_default = {
|
|
36890
36890
|
name: "@hasna/skills",
|
|
36891
|
-
version: "0.10.
|
|
36891
|
+
version: "0.10.55",
|
|
36892
36892
|
description: "Skills library for AI coding agents",
|
|
36893
36893
|
type: "module",
|
|
36894
36894
|
bin: {
|
|
@@ -86070,8 +86070,12 @@ function assertPlanWindow(issuedAt, expiresAt, now3) {
|
|
|
86070
86070
|
throw new SkillSelectionError("SESSION_PLAN_EXPIRED", "The reviewed session reconciliation plan is not currently valid; inspect the receipt and prepare a new plan.");
|
|
86071
86071
|
}
|
|
86072
86072
|
}
|
|
86073
|
+
function selectionMetadata(selection) {
|
|
86074
|
+
return { slug: selection.slug, version: selection.version, bundleDigest: selection.bundleDigest };
|
|
86075
|
+
}
|
|
86073
86076
|
function inspectSkillSession(sessionId, options = {}) {
|
|
86074
86077
|
const snapshot2 = readSkillSessionSnapshot(sessionId, options), { receipt } = snapshot2;
|
|
86078
|
+
const loaded = new Set(receipt.loaded);
|
|
86075
86079
|
return {
|
|
86076
86080
|
sessionId,
|
|
86077
86081
|
path: snapshot2.path,
|
|
@@ -86083,7 +86087,8 @@ function inspectSkillSession(sessionId, options = {}) {
|
|
|
86083
86087
|
profileId: receipt.profile.profileId,
|
|
86084
86088
|
profileRevision: receipt.profile.profileRevision,
|
|
86085
86089
|
selectionCount: receipt.profile.selections.length,
|
|
86086
|
-
loadedCount: receipt.loaded.length
|
|
86090
|
+
loadedCount: receipt.loaded.length,
|
|
86091
|
+
selections: receipt.profile.selections.map((selection) => ({ ...selectionMetadata(selection), loaded: loaded.has(selectionKey(selection)) }))
|
|
86087
86092
|
};
|
|
86088
86093
|
}
|
|
86089
86094
|
function renewalDeadlineSignal(error61) {
|
|
@@ -86305,6 +86310,21 @@ async function reconcileSkillSession(input2, options = {}) {
|
|
|
86305
86310
|
}
|
|
86306
86311
|
const targetKeys = new Set(target.selections.map(selectionKey));
|
|
86307
86312
|
const loaded = old.loaded.filter((key) => targetKeys.has(key));
|
|
86313
|
+
const previouslyLoaded = new Set(old.loaded);
|
|
86314
|
+
const targetBySlug = new Map(target.selections.map((selection) => [selection.slug, selection]));
|
|
86315
|
+
const previousSlugs = new Set(old.profile.selections.map((selection) => selection.slug));
|
|
86316
|
+
const selectionDelta = old.profile.selections.map((previous) => {
|
|
86317
|
+
const current = targetBySlug.get(previous.slug);
|
|
86318
|
+
const wasLoaded = previouslyLoaded.has(selectionKey(previous));
|
|
86319
|
+
const reason2 = !current ? "selection-removed" : selectionKey(previous) === selectionKey(current) ? "same-bundle" : "bundle-changed";
|
|
86320
|
+
return {
|
|
86321
|
+
selection: selectionMetadata(previous),
|
|
86322
|
+
loaded: wasLoaded,
|
|
86323
|
+
outcome: !wasLoaded ? "unloaded" : reason2 === "same-bundle" ? "retained" : "retired",
|
|
86324
|
+
reason: reason2,
|
|
86325
|
+
...reason2 === "bundle-changed" ? { replacement: selectionMetadata(current) } : {}
|
|
86326
|
+
};
|
|
86327
|
+
});
|
|
86308
86328
|
const replacementGeneration = nextSkillSessionGeneration(snapshot2.generation);
|
|
86309
86329
|
const plan = {
|
|
86310
86330
|
schemaVersion: 1,
|
|
@@ -86317,6 +86337,8 @@ async function reconcileSkillSession(input2, options = {}) {
|
|
|
86317
86337
|
replacementGeneration,
|
|
86318
86338
|
retainedLoadedCount: loaded.length,
|
|
86319
86339
|
retiredLoadedCount: old.loaded.length - loaded.length,
|
|
86340
|
+
selectionDelta,
|
|
86341
|
+
addedSelections: target.selections.filter((selection) => !previousSlugs.has(selection.slug)).map(selectionMetadata),
|
|
86320
86342
|
scope: "Only this receipt; existing child sessions, project locks, shared profiles, hooks and running processes are unchanged."
|
|
86321
86343
|
};
|
|
86322
86344
|
const planDigest = digest3(plan);
|
|
@@ -86356,6 +86378,9 @@ __export(exports_context, {
|
|
|
86356
86378
|
contextResolverOptions: () => contextResolverOptions
|
|
86357
86379
|
});
|
|
86358
86380
|
import { readSync as readSync12 } from "fs";
|
|
86381
|
+
function sessionSelectionLabel(selection) {
|
|
86382
|
+
return `${selection.slug}@${selection.version} ${selection.bundleDigest}`;
|
|
86383
|
+
}
|
|
86359
86384
|
function selectedProfileId(explicit) {
|
|
86360
86385
|
return explicit ?? process.env.HASNA_SKILLS_SELECTION_PROFILE ?? readManagedSkillPolicy()?.profileId ?? "default";
|
|
86361
86386
|
}
|
|
@@ -86373,8 +86398,12 @@ function registerContextCommands(parent) {
|
|
|
86373
86398
|
sessions.command("show <id>").option("--json", "Return metadata as JSON", false).description("Inspect one session receipt without displaying payloads or changing its pin").action(async (id, options) => {
|
|
86374
86399
|
try {
|
|
86375
86400
|
const result2 = inspectSkillSession(id);
|
|
86376
|
-
await writeCliOutput(options.json ? JSON.stringify(result2) :
|
|
86377
|
-
|
|
86401
|
+
await writeCliOutput(options.json ? JSON.stringify(result2) : [
|
|
86402
|
+
`${JSON.stringify(id)}: ${result2.profileId} at ${result2.profileRevision}`,
|
|
86403
|
+
`Receipt SHA256: ${result2.receiptSha256}`,
|
|
86404
|
+
...result2.selections.map((selection) => `${selection.loaded ? "Loaded" : "Unloaded"}: ${sessionSelectionLabel(selection)}`)
|
|
86405
|
+
].join(`
|
|
86406
|
+
`));
|
|
86378
86407
|
} catch (error61) {
|
|
86379
86408
|
reportContextError(error61, options.json);
|
|
86380
86409
|
}
|
|
@@ -86401,7 +86430,13 @@ Review digest: ${result2.reviewDigest}`);
|
|
|
86401
86430
|
try {
|
|
86402
86431
|
const result2 = await reconcileSkillSession({ ...options, sessionId: id });
|
|
86403
86432
|
await writeCliOutput(options.json ? JSON.stringify(result2) : result2.applied ? `Reconciled ${JSON.stringify(id)} to ${result2.plan.target.profileId} at ${result2.plan.target.profileRevision}.
|
|
86404
|
-
Preserved original receipt: ${result2.archivePath}` :
|
|
86433
|
+
Preserved original receipt: ${result2.archivePath}` : [
|
|
86434
|
+
`Planned one session reconciliation: ${result2.plan.retainedLoadedCount} loaded retained, ${result2.plan.retiredLoadedCount} loaded retired.`,
|
|
86435
|
+
...result2.plan.selectionDelta.map((row) => `${row.outcome} (${row.reason}): ${sessionSelectionLabel(row.selection)}${row.replacement ? ` -> ${sessionSelectionLabel(row.replacement)}` : ""}`),
|
|
86436
|
+
...result2.plan.addedSelections.map((selection) => `Added selection (unloaded): ${sessionSelectionLabel(selection)}`),
|
|
86437
|
+
`Review --json output, then use --apply --plan-digest ${result2.planDigest} --plan-issued-at ${result2.plan.issuedAt} --plan-expires-at ${result2.plan.expiresAt}.`
|
|
86438
|
+
].join(`
|
|
86439
|
+
`));
|
|
86405
86440
|
} catch (error61) {
|
|
86406
86441
|
reportContextError(error61, options.json);
|
|
86407
86442
|
}
|
package/bin/mcp.js
CHANGED
|
@@ -20019,7 +20019,7 @@ var package_default;
|
|
|
20019
20019
|
var init_package = __esm(() => {
|
|
20020
20020
|
package_default = {
|
|
20021
20021
|
name: "@hasna/skills",
|
|
20022
|
-
version: "0.10.
|
|
20022
|
+
version: "0.10.55",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
package/bin/migrate.js
CHANGED
package/bin/server.js
CHANGED
|
@@ -24140,7 +24140,7 @@ restoreLaunchCwd();
|
|
|
24140
24140
|
// package.json
|
|
24141
24141
|
var package_default = {
|
|
24142
24142
|
name: "@hasna/skills",
|
|
24143
|
-
version: "0.10.
|
|
24143
|
+
version: "0.10.55",
|
|
24144
24144
|
description: "Skills library for AI coding agents",
|
|
24145
24145
|
type: "module",
|
|
24146
24146
|
bin: {
|
package/bin/worker.js
CHANGED
|
@@ -24143,7 +24143,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
24143
24143
|
// package.json
|
|
24144
24144
|
var package_default = {
|
|
24145
24145
|
name: "@hasna/skills",
|
|
24146
|
-
version: "0.10.
|
|
24146
|
+
version: "0.10.55",
|
|
24147
24147
|
description: "Skills library for AI coding agents",
|
|
24148
24148
|
type: "module",
|
|
24149
24149
|
bin: {
|
package/dist/index.js
CHANGED
|
@@ -11833,7 +11833,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
|
|
|
11833
11833
|
// package.json
|
|
11834
11834
|
var package_default = {
|
|
11835
11835
|
name: "@hasna/skills",
|
|
11836
|
-
version: "0.10.
|
|
11836
|
+
version: "0.10.55",
|
|
11837
11837
|
description: "Skills library for AI coding agents",
|
|
11838
11838
|
type: "module",
|
|
11839
11839
|
bin: {
|
|
@@ -48150,8 +48150,12 @@ function assertPlanWindow(issuedAt, expiresAt, now) {
|
|
|
48150
48150
|
throw new SkillSelectionError("SESSION_PLAN_EXPIRED", "The reviewed session reconciliation plan is not currently valid; inspect the receipt and prepare a new plan.");
|
|
48151
48151
|
}
|
|
48152
48152
|
}
|
|
48153
|
+
function selectionMetadata(selection) {
|
|
48154
|
+
return { slug: selection.slug, version: selection.version, bundleDigest: selection.bundleDigest };
|
|
48155
|
+
}
|
|
48153
48156
|
function inspectSkillSession(sessionId, options = {}) {
|
|
48154
48157
|
const snapshot2 = readSkillSessionSnapshot(sessionId, options), { receipt } = snapshot2;
|
|
48158
|
+
const loaded = new Set(receipt.loaded);
|
|
48155
48159
|
return {
|
|
48156
48160
|
sessionId,
|
|
48157
48161
|
path: snapshot2.path,
|
|
@@ -48163,7 +48167,8 @@ function inspectSkillSession(sessionId, options = {}) {
|
|
|
48163
48167
|
profileId: receipt.profile.profileId,
|
|
48164
48168
|
profileRevision: receipt.profile.profileRevision,
|
|
48165
48169
|
selectionCount: receipt.profile.selections.length,
|
|
48166
|
-
loadedCount: receipt.loaded.length
|
|
48170
|
+
loadedCount: receipt.loaded.length,
|
|
48171
|
+
selections: receipt.profile.selections.map((selection) => ({ ...selectionMetadata(selection), loaded: loaded.has(selectionKey(selection)) }))
|
|
48167
48172
|
};
|
|
48168
48173
|
}
|
|
48169
48174
|
var SESSION_RENEWAL_REFUSAL_TTL_MS = 5 * 60 * 1000;
|
|
@@ -48198,6 +48203,21 @@ async function reconcileSkillSession(input2, options = {}) {
|
|
|
48198
48203
|
}
|
|
48199
48204
|
const targetKeys = new Set(target.selections.map(selectionKey));
|
|
48200
48205
|
const loaded = old.loaded.filter((key) => targetKeys.has(key));
|
|
48206
|
+
const previouslyLoaded = new Set(old.loaded);
|
|
48207
|
+
const targetBySlug = new Map(target.selections.map((selection) => [selection.slug, selection]));
|
|
48208
|
+
const previousSlugs = new Set(old.profile.selections.map((selection) => selection.slug));
|
|
48209
|
+
const selectionDelta = old.profile.selections.map((previous) => {
|
|
48210
|
+
const current = targetBySlug.get(previous.slug);
|
|
48211
|
+
const wasLoaded = previouslyLoaded.has(selectionKey(previous));
|
|
48212
|
+
const reason2 = !current ? "selection-removed" : selectionKey(previous) === selectionKey(current) ? "same-bundle" : "bundle-changed";
|
|
48213
|
+
return {
|
|
48214
|
+
selection: selectionMetadata(previous),
|
|
48215
|
+
loaded: wasLoaded,
|
|
48216
|
+
outcome: !wasLoaded ? "unloaded" : reason2 === "same-bundle" ? "retained" : "retired",
|
|
48217
|
+
reason: reason2,
|
|
48218
|
+
...reason2 === "bundle-changed" ? { replacement: selectionMetadata(current) } : {}
|
|
48219
|
+
};
|
|
48220
|
+
});
|
|
48201
48221
|
const replacementGeneration = nextSkillSessionGeneration(snapshot2.generation);
|
|
48202
48222
|
const plan = {
|
|
48203
48223
|
schemaVersion: 1,
|
|
@@ -48210,6 +48230,8 @@ async function reconcileSkillSession(input2, options = {}) {
|
|
|
48210
48230
|
replacementGeneration,
|
|
48211
48231
|
retainedLoadedCount: loaded.length,
|
|
48212
48232
|
retiredLoadedCount: old.loaded.length - loaded.length,
|
|
48233
|
+
selectionDelta,
|
|
48234
|
+
addedSelections: target.selections.filter((selection) => !previousSlugs.has(selection.slug)).map(selectionMetadata),
|
|
48213
48235
|
scope: "Only this receipt; existing child sessions, project locks, shared profiles, hooks and running processes are unchanged."
|
|
48214
48236
|
};
|
|
48215
48237
|
const planDigest = digest3(plan);
|
|
@@ -16,6 +16,19 @@ export interface SessionReconciliationOptions extends SelectionCacheOptions {
|
|
|
16
16
|
client?: ProfileClient;
|
|
17
17
|
}
|
|
18
18
|
export declare const SESSION_RECONCILIATION_PLAN_TTL_MS: number;
|
|
19
|
+
/** Exact bundle identity only; never spread receipt, policy or payload fields. */
|
|
20
|
+
export interface SessionSelectionMetadata {
|
|
21
|
+
slug: string;
|
|
22
|
+
version: string;
|
|
23
|
+
bundleDigest: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SessionSelectionDelta {
|
|
26
|
+
selection: SessionSelectionMetadata;
|
|
27
|
+
loaded: boolean;
|
|
28
|
+
outcome: "retained" | "retired" | "unloaded";
|
|
29
|
+
reason: "same-bundle" | "selection-removed" | "bundle-changed";
|
|
30
|
+
replacement?: SessionSelectionMetadata;
|
|
31
|
+
}
|
|
19
32
|
/** Metadata only: inspection never displays skill payloads or resolves credentials. */
|
|
20
33
|
export declare function inspectSkillSession(sessionId: string, options?: SelectionCacheOptions): {
|
|
21
34
|
sessionId: string;
|
|
@@ -29,6 +42,12 @@ export declare function inspectSkillSession(sessionId: string, options?: Selecti
|
|
|
29
42
|
profileRevision: string;
|
|
30
43
|
selectionCount: number;
|
|
31
44
|
loadedCount: number;
|
|
45
|
+
selections: {
|
|
46
|
+
loaded: boolean;
|
|
47
|
+
slug: string;
|
|
48
|
+
version: string;
|
|
49
|
+
bundleDigest: string;
|
|
50
|
+
}[];
|
|
32
51
|
};
|
|
33
52
|
/** Fits inside the managed context child's 6.5-second ceiling, including CLI work. */
|
|
34
53
|
export declare const SESSION_RENEWAL_TIMEOUT_MS = 4000;
|
|
@@ -75,6 +94,8 @@ export declare function reconcileSkillSession(input: SessionReconciliationInput,
|
|
|
75
94
|
replacementGeneration: number;
|
|
76
95
|
retainedLoadedCount: number;
|
|
77
96
|
retiredLoadedCount: number;
|
|
97
|
+
selectionDelta: SessionSelectionDelta[];
|
|
98
|
+
addedSelections: SessionSelectionMetadata[];
|
|
78
99
|
scope: string;
|
|
79
100
|
};
|
|
80
101
|
planDigest: string;
|
|
@@ -112,6 +133,8 @@ export declare function reconcileSkillSession(input: SessionReconciliationInput,
|
|
|
112
133
|
replacementGeneration: number;
|
|
113
134
|
retainedLoadedCount: number;
|
|
114
135
|
retiredLoadedCount: number;
|
|
136
|
+
selectionDelta: SessionSelectionDelta[];
|
|
137
|
+
addedSelections: SessionSelectionMetadata[];
|
|
115
138
|
scope: string;
|
|
116
139
|
};
|
|
117
140
|
planDigest: string;
|
package/dist/sdk/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export { CloudExecutionClient, type CloudExecution, type CloudEligibility } from
|
|
|
19
19
|
export { readExecutionGrantPolicy, saveExecutionGrantPolicy, resolveExecutionGrant } from "../lib/execution-grant-client.js";
|
|
20
20
|
export type { ExecutionGrant, ExecutionGrantPolicy, ExecutionGrantRequest, ResolvedExecutionGrant } from "../lib/execution-grants.js";
|
|
21
21
|
export { HttpProfileClient, createProfileClient, type ProfileClient, type AuthenticatedProfilePrincipal, type AuthenticatedProfileRole } from "../lib/profile-client.js";
|
|
22
|
-
export { inspectSkillSession, reconcileSkillSession, type SessionReconciliationInput, type SessionReconciliationOptions } from "../lib/session-reconciliation.js";
|
|
22
|
+
export { inspectSkillSession, reconcileSkillSession, type SessionSelectionMetadata, type SessionSelectionDelta, type SessionReconciliationInput, type SessionReconciliationOptions } from "../lib/session-reconciliation.js";
|
|
23
23
|
export { resolveSelectedRun, executeSelectedLocal, prepareSelectedSecretBindings, type ResolvedSelectedRun, type SelectedLocalRunOptions } from "../lib/selected-run.js";
|
|
24
24
|
export { readSelectedSecretBindings, type SelectedSecretBindings, type SelectedSecretsClient } from "../lib/execution-secrets.js";
|
|
25
25
|
export type { SkillSelection, SkillProfile, ResolvedSkillSelection, ResolvedSkillProfile, StationSkillStateInput, StationSkillState } from "../types/skill-selection.js";
|
package/dist/sdk/index.js
CHANGED
|
@@ -32373,7 +32373,7 @@ var init_event_sink = __esm(() => {
|
|
|
32373
32373
|
// package.json
|
|
32374
32374
|
var package_default = {
|
|
32375
32375
|
name: "@hasna/skills",
|
|
32376
|
-
version: "0.10.
|
|
32376
|
+
version: "0.10.55",
|
|
32377
32377
|
description: "Skills library for AI coding agents",
|
|
32378
32378
|
type: "module",
|
|
32379
32379
|
bin: {
|
|
@@ -37490,8 +37490,12 @@ function assertPlanWindow(issuedAt, expiresAt, now) {
|
|
|
37490
37490
|
throw new SkillSelectionError("SESSION_PLAN_EXPIRED", "The reviewed session reconciliation plan is not currently valid; inspect the receipt and prepare a new plan.");
|
|
37491
37491
|
}
|
|
37492
37492
|
}
|
|
37493
|
+
function selectionMetadata(selection2) {
|
|
37494
|
+
return { slug: selection2.slug, version: selection2.version, bundleDigest: selection2.bundleDigest };
|
|
37495
|
+
}
|
|
37493
37496
|
function inspectSkillSession(sessionId, options = {}) {
|
|
37494
37497
|
const snapshot = readSkillSessionSnapshot(sessionId, options), { receipt } = snapshot;
|
|
37498
|
+
const loaded = new Set(receipt.loaded);
|
|
37495
37499
|
return {
|
|
37496
37500
|
sessionId,
|
|
37497
37501
|
path: snapshot.path,
|
|
@@ -37503,7 +37507,8 @@ function inspectSkillSession(sessionId, options = {}) {
|
|
|
37503
37507
|
profileId: receipt.profile.profileId,
|
|
37504
37508
|
profileRevision: receipt.profile.profileRevision,
|
|
37505
37509
|
selectionCount: receipt.profile.selections.length,
|
|
37506
|
-
loadedCount: receipt.loaded.length
|
|
37510
|
+
loadedCount: receipt.loaded.length,
|
|
37511
|
+
selections: receipt.profile.selections.map((selection2) => ({ ...selectionMetadata(selection2), loaded: loaded.has(selectionKey(selection2)) }))
|
|
37507
37512
|
};
|
|
37508
37513
|
}
|
|
37509
37514
|
var SESSION_RENEWAL_REFUSAL_TTL_MS = 5 * 60 * 1000;
|
|
@@ -37538,6 +37543,21 @@ async function reconcileSkillSession(input, options = {}) {
|
|
|
37538
37543
|
}
|
|
37539
37544
|
const targetKeys = new Set(target.selections.map(selectionKey));
|
|
37540
37545
|
const loaded = old.loaded.filter((key) => targetKeys.has(key));
|
|
37546
|
+
const previouslyLoaded = new Set(old.loaded);
|
|
37547
|
+
const targetBySlug = new Map(target.selections.map((selection2) => [selection2.slug, selection2]));
|
|
37548
|
+
const previousSlugs = new Set(old.profile.selections.map((selection2) => selection2.slug));
|
|
37549
|
+
const selectionDelta = old.profile.selections.map((previous) => {
|
|
37550
|
+
const current = targetBySlug.get(previous.slug);
|
|
37551
|
+
const wasLoaded = previouslyLoaded.has(selectionKey(previous));
|
|
37552
|
+
const reason = !current ? "selection-removed" : selectionKey(previous) === selectionKey(current) ? "same-bundle" : "bundle-changed";
|
|
37553
|
+
return {
|
|
37554
|
+
selection: selectionMetadata(previous),
|
|
37555
|
+
loaded: wasLoaded,
|
|
37556
|
+
outcome: !wasLoaded ? "unloaded" : reason === "same-bundle" ? "retained" : "retired",
|
|
37557
|
+
reason,
|
|
37558
|
+
...reason === "bundle-changed" ? { replacement: selectionMetadata(current) } : {}
|
|
37559
|
+
};
|
|
37560
|
+
});
|
|
37541
37561
|
const replacementGeneration = nextSkillSessionGeneration(snapshot.generation);
|
|
37542
37562
|
const plan = {
|
|
37543
37563
|
schemaVersion: 1,
|
|
@@ -37550,6 +37570,8 @@ async function reconcileSkillSession(input, options = {}) {
|
|
|
37550
37570
|
replacementGeneration,
|
|
37551
37571
|
retainedLoadedCount: loaded.length,
|
|
37552
37572
|
retiredLoadedCount: old.loaded.length - loaded.length,
|
|
37573
|
+
selectionDelta,
|
|
37574
|
+
addedSelections: target.selections.filter((selection2) => !previousSlugs.has(selection2.slug)).map(selectionMetadata),
|
|
37553
37575
|
scope: "Only this receipt; existing child sessions, project locks, shared profiles, hooks and running processes are unchanged."
|
|
37554
37576
|
};
|
|
37555
37577
|
const planDigest = digest(plan);
|