@skrr-ai/cli 0.1.94 → 0.1.95

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 (120) hide show
  1. package/README.md +153 -165
  2. package/bin/run.js +32 -0
  3. package/bin/update-npm-runner.cjs +33 -0
  4. package/bin/update-session.cjs +194 -0
  5. package/bin/update-worker.cjs +208 -0
  6. package/dist/base-command.js +0 -15
  7. package/dist/commands/code/doctor.d.ts +1 -0
  8. package/dist/commands/code/doctor.js +6 -0
  9. package/dist/commands/code/index.js +4 -0
  10. package/dist/commands/code/install.d.ts +5 -62
  11. package/dist/commands/code/install.js +86 -279
  12. package/dist/commands/code/rollback.d.ts +8 -0
  13. package/dist/commands/code/rollback.js +20 -0
  14. package/dist/commands/code/update.d.ts +8 -37
  15. package/dist/commands/code/update.js +134 -213
  16. package/dist/commands/daemon/install.js +4 -0
  17. package/dist/commands/generate-recovery-code.d.ts +13 -1
  18. package/dist/commands/generate-recovery-code.js +146 -13
  19. package/dist/commands/instructions/guide.d.ts +20 -0
  20. package/dist/commands/instructions/guide.js +84 -0
  21. package/dist/commands/instructions/install.js +57 -33
  22. package/dist/commands/instructions/setup.d.ts +14 -0
  23. package/dist/commands/instructions/setup.js +72 -0
  24. package/dist/commands/integrations/execute.js +1 -1
  25. package/dist/commands/login.d.ts +5 -6
  26. package/dist/commands/login.js +27 -11
  27. package/dist/commands/logout.js +7 -7
  28. package/dist/commands/security/overview.d.ts +11 -0
  29. package/dist/commands/security/overview.js +158 -0
  30. package/dist/commands/spaces/claim.d.ts +12 -0
  31. package/dist/commands/spaces/claim.js +42 -0
  32. package/dist/commands/spaces/ownership.d.ts +12 -0
  33. package/dist/commands/spaces/ownership.js +46 -0
  34. package/dist/commands/tasks/cancel-cascade.js +1 -1
  35. package/dist/commands/tasks/create-tree.d.ts +5 -1
  36. package/dist/commands/tasks/create-tree.js +35 -7
  37. package/dist/commands/tasks/interrupt.js +2 -2
  38. package/dist/commands/tasks/pause-schedule.js +1 -1
  39. package/dist/commands/token/list.d.ts +3 -5
  40. package/dist/commands/token/list.js +99 -57
  41. package/dist/commands/update.d.ts +14 -0
  42. package/dist/commands/update.js +61 -0
  43. package/dist/generated/managed-instruction-guides.json +9 -0
  44. package/dist/hooks/init.d.ts +5 -0
  45. package/dist/hooks/init.js +27 -0
  46. package/dist/lib/commitments.d.ts +0 -8
  47. package/dist/lib/commitments.js +0 -52
  48. package/dist/lib/daemon-installer.d.ts +2 -0
  49. package/dist/lib/daemon-installer.js +100 -24
  50. package/dist/lib/first-party-harness-doctor.js +31 -1
  51. package/dist/lib/first-party-harness-remote-install.d.ts +71 -0
  52. package/dist/lib/first-party-harness-remote-install.js +310 -0
  53. package/dist/lib/first-party-harness-remote-update.d.ts +46 -0
  54. package/dist/lib/first-party-harness-remote-update.js +242 -0
  55. package/dist/lib/first-party-harness-startup-update.d.ts +26 -0
  56. package/dist/lib/first-party-harness-startup-update.js +166 -0
  57. package/dist/lib/first-party-harness-update.d.ts +46 -0
  58. package/dist/lib/first-party-harness-update.js +289 -0
  59. package/dist/lib/first-party-harness.js +7 -4
  60. package/dist/lib/managed-instruction-local.d.ts +12 -0
  61. package/dist/lib/managed-instruction-local.js +58 -0
  62. package/dist/lib/managed-instruction-setup.d.ts +35 -0
  63. package/dist/lib/managed-instruction-setup.js +306 -0
  64. package/dist/lib/memory-sync.d.ts +1 -0
  65. package/dist/lib/memory-sync.js +279 -68
  66. package/dist/lib/platform-update-local.d.ts +2 -0
  67. package/dist/lib/platform-update-local.js +113 -0
  68. package/dist/lib/platform-update.d.ts +39 -0
  69. package/dist/lib/platform-update.js +84 -0
  70. package/dist/lib/profile-machine-identity-guard.d.ts +2 -0
  71. package/dist/lib/profile-machine-identity-guard.js +13 -0
  72. package/dist/lib/prompt.d.ts +1 -0
  73. package/dist/lib/prompt.js +4 -3
  74. package/dist/lib/task-batch.d.ts +9 -0
  75. package/dist/lib/task-batch.js +94 -17
  76. package/dist/lib/task-instruction-offer.d.ts +1 -4
  77. package/dist/lib/task-instruction-offer.js +3 -129
  78. package/dist/lib/update-check.d.ts +61 -53
  79. package/dist/lib/update-check.js +453 -314
  80. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.d.ts +3 -4
  81. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.js +3 -4
  82. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessReleaseKeys.d.ts +82 -0
  83. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessReleaseKeys.js +105 -0
  84. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessUpdater.d.ts +110 -0
  85. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessUpdater.js +945 -0
  86. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessPermissionControls.d.ts +32 -0
  87. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessPermissionControls.js +62 -0
  88. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +2 -0
  89. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +4 -1
  90. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +35 -5
  91. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releasePolicy.d.ts +63 -0
  92. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releasePolicy.js +169 -0
  93. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseVersions.d.ts +2 -0
  94. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseVersions.js +44 -0
  95. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.d.ts +3 -4
  96. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.js +3 -4
  97. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessReleaseKeys.d.ts +82 -0
  98. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessReleaseKeys.js +102 -0
  99. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessUpdater.d.ts +110 -0
  100. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessUpdater.js +923 -0
  101. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessPermissionControls.d.ts +32 -0
  102. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessPermissionControls.js +59 -0
  103. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +2 -0
  104. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -0
  105. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +35 -5
  106. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releasePolicy.d.ts +63 -0
  107. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releasePolicy.js +163 -0
  108. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseVersions.d.ts +2 -0
  109. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseVersions.js +41 -0
  110. package/dist/node_modules/@skrr-ai/auth-core/package.json +31 -1
  111. package/dist/node_modules/@skrr-ai/data-provider/index.js +6584 -6567
  112. package/docs/v1/README.md +28 -0
  113. package/docs/v1/api.md +55 -0
  114. package/docs/v1/changelog.md +16 -0
  115. package/docs/v1/check-examples.mjs +178 -0
  116. package/docs/v1/examples/api-readonly.mjs +144 -0
  117. package/docs/v1/operations.md +87 -0
  118. package/docs/v1/quickstart.md +71 -0
  119. package/oclif.manifest.json +46007 -45462
  120. package/package.json +13 -11
@@ -0,0 +1,306 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shouldSkipInstructionPrompt = shouldSkipInstructionPrompt;
4
+ exports.instructionProviderLabel = instructionProviderLabel;
5
+ exports.runManagedInstructionSetup = runManagedInstructionSetup;
6
+ exports.maybeOfferManagedInstructionSetup = maybeOfferManagedInstructionSetup;
7
+ const node_crypto_1 = require("node:crypto");
8
+ const auth_core_1 = require("@skrr-ai/auth-core");
9
+ const data_provider_1 = require("@skrr-ai/data-provider");
10
+ const harness_provider_input_1 = require("./harness-provider-input");
11
+ const managed_instruction_local_1 = require("./managed-instruction-local");
12
+ const prompt_1 = require("./prompt");
13
+ const TEMPLATE_KEY = 'oversky-task-management';
14
+ function shouldSkipInstructionPrompt() {
15
+ return Boolean(!process.stdin.isTTY ||
16
+ !process.stdout.isTTY ||
17
+ process.env.CI ||
18
+ process.env.OVERSKY_HEADLESS ||
19
+ process.env.OVERSKY_SESSION_TASK_ID ||
20
+ process.env.OVERSKY_SESSION_AGENT_ID ||
21
+ process.env.OVERSKY_AGENT_ID ||
22
+ process.env.OVERSKY_DISABLE_INSTRUCTION_OFFER === '1');
23
+ }
24
+ function instructionProviderLabel(provider) {
25
+ if (provider === 'claude')
26
+ return 'Claude Code';
27
+ if (provider === 'codex')
28
+ return 'Codex';
29
+ return auth_core_1.FIRST_PARTY_HARNESS.displayName;
30
+ }
31
+ function detectedProviders(daemon) {
32
+ let capabilities = [];
33
+ if (Array.isArray(daemon.capabilities))
34
+ capabilities = daemon.capabilities.map(String);
35
+ else if (typeof daemon.capabilities === 'string') {
36
+ try {
37
+ const parsed = JSON.parse(daemon.capabilities);
38
+ if (Array.isArray(parsed))
39
+ capabilities = parsed.map(String);
40
+ }
41
+ catch {
42
+ capabilities = daemon.capabilities.split(',').map((entry) => entry.trim());
43
+ }
44
+ }
45
+ const providers = [];
46
+ if (capabilities.includes('claude_session'))
47
+ providers.push('claude');
48
+ if (capabilities.includes('codex_session'))
49
+ providers.push('codex');
50
+ if (capabilities.some(auth_core_1.isFirstPartyHarnessCapability))
51
+ providers.push(auth_core_1.FIRST_PARTY_HARNESS.provider);
52
+ return providers;
53
+ }
54
+ function eligibleProviders(offer, detected) {
55
+ // Preserve suppression on older servers without provider-scoped decisions.
56
+ const providerOffers = offer.providerOffers;
57
+ if (providerOffers) {
58
+ return detected.filter((provider) => providerOffers.some((entry) => entry.provider === provider && entry.eligible));
59
+ }
60
+ return offer.eligible ? detected : [];
61
+ }
62
+ function printStatus(offer, options) {
63
+ for (const target of offer.targets ?? []) {
64
+ if (target.desiredState !== 'installed')
65
+ continue;
66
+ if (options.trigger !== 'manual' && target.status !== 'error')
67
+ continue;
68
+ const policy = target.trackingMode === 'pinned' ? 'fixed version' : 'automatic updates';
69
+ options.log(`${instructionProviderLabel(target.provider)}: ${target.status}, ${policy}${target.appliedPath ? ` — ${target.appliedPath}` : ''}.`);
70
+ if (target.status === 'error') {
71
+ options.log(` ${target.lastError || 'The daemon could not apply this instruction.'} Check \`skrr instructions status\`.`);
72
+ }
73
+ else if (options.trigger === 'manual' && target.status !== 'synced') {
74
+ options.log(' Awaiting daemon confirmation; `skrr instructions status` shows the applied file and version.');
75
+ }
76
+ }
77
+ if (offer.bundleId && options.trigger === 'manual') {
78
+ options.log(`\`skrr instructions show ${offer.bundleId}\` shows saved versions and pending template updates.`);
79
+ }
80
+ }
81
+ /** Read-only preflight precedes every consent and every write to the API. */
82
+ async function runManagedInstructionSetup(options) {
83
+ const result = {
84
+ status: 'skipped',
85
+ targets: [],
86
+ installed: [],
87
+ decisions: [],
88
+ };
89
+ const interactive = !shouldSkipInstructionPrompt() && !options.json;
90
+ if (options.trigger !== 'manual' && !interactive)
91
+ return result;
92
+ if (!interactive && !options.yes && !options.review) {
93
+ throw new Error('Instruction setup needs a terminal, or --yes --provider <provider> --update-policy <latest|pinned>. Use --review --json to inspect without installing.');
94
+ }
95
+ if (options.yes && (!options.providers?.length || !options.trackingMode)) {
96
+ throw new Error('--yes requires explicit --provider and --update-policy; no installation was authorized.');
97
+ }
98
+ const daemonId = options.daemonId ??
99
+ (await (0, managed_instruction_local_1.resolveLocalInstructionDaemon)({
100
+ waitMs: options.waitForLocalReady ? 20_000 : 0,
101
+ log: options.log,
102
+ }));
103
+ if (!daemonId) {
104
+ result.status = 'unavailable';
105
+ result.message =
106
+ 'Could not verify a signed-in local daemon for this account, server, and profile. Run `skrr daemon status`, then `skrr instructions setup`; use --daemon <id> to choose a machine explicitly.';
107
+ if (options.trigger === 'manual')
108
+ options.log(result.message);
109
+ return result;
110
+ }
111
+ result.daemonId = daemonId;
112
+ const [daemons, response] = await Promise.all([
113
+ data_provider_1.dataService.getDaemons(),
114
+ data_provider_1.dataService.getManagedInstructionOffer(TEMPLATE_KEY),
115
+ ]);
116
+ const daemon = daemons.active.find((entry) => entry.daemonId === daemonId);
117
+ const offer = response.offers.find((entry) => entry.daemonId === daemonId);
118
+ if (!daemon || !offer) {
119
+ result.status = 'unavailable';
120
+ result.message =
121
+ 'The selected daemon is not connected or does not support instruction setup. Check `skrr daemon status` or `skrr list-daemons` and retry.';
122
+ if (options.trigger === 'manual')
123
+ options.log(result.message);
124
+ return result;
125
+ }
126
+ result.targets = offer.targets ?? [];
127
+ if (!options.json) {
128
+ printStatus(offer, options);
129
+ if (options.trigger === 'manual' &&
130
+ response.preset.pendingTemplateVersionId &&
131
+ response.preset.bundleId) {
132
+ options.log(`Built-in template v${response.preset.pendingTemplateVersion} is available for your customized instruction. Review with \`skrr instructions diff ${response.preset.bundleId} --from ${response.preset.contentVersion} --to ${response.preset.pendingTemplateVersionId}\`.`);
133
+ options.log(`After reviewing, \`skrr instructions activate ${response.preset.bundleId} --version ${response.preset.pendingTemplateVersionId}\` updates all targets tracking the current version; fixed versions stay pinned.`);
134
+ }
135
+ if (options.trigger === 'manual')
136
+ for (const target of result.targets) {
137
+ if (target.trackingMode === 'pinned' &&
138
+ target.desiredState === 'installed' &&
139
+ target.appliedVersionNumber &&
140
+ target.appliedVersionNumber < response.preset.contentVersion) {
141
+ options.log(`${instructionProviderLabel(target.provider)} stays on fixed v${target.appliedVersionNumber}; v${response.preset.contentVersion} is current. Review with \`skrr instructions setup --provider ${target.provider} --review\`, then rerun with --update-policy pinned to adopt it.`);
142
+ }
143
+ }
144
+ }
145
+ const detected = detectedProviders(daemon);
146
+ const providers = options.providers?.length
147
+ ? (0, harness_provider_input_1.canonicalHarnessInputs)(options.providers)
148
+ : options.review
149
+ ? detected
150
+ : eligibleProviders(offer, detected);
151
+ if (!providers.length) {
152
+ result.status = 'unchanged';
153
+ if (options.trigger === 'manual' && !options.json) {
154
+ options.log('No new providers need setup. To change a previous decision or update policy, pass --provider <provider>.');
155
+ }
156
+ return result;
157
+ }
158
+ if (providers.some((provider) => !detected.includes(provider))) {
159
+ throw new Error('The selected machine has not detected every requested provider. Install the coding agent first and retry; no instruction targets were created.');
160
+ }
161
+ const prepared = await data_provider_1.dataService.prepareManagedInstructionOffer(TEMPLATE_KEY, {
162
+ daemonId,
163
+ providers,
164
+ });
165
+ result.prepared = prepared;
166
+ if (prepared.daemonId !== daemonId)
167
+ throw new Error('Instruction preflight returned another machine; no installation was authorized.');
168
+ if (prepared.readiness !== 'ready') {
169
+ result.status = 'unavailable';
170
+ result.message =
171
+ prepared.message ||
172
+ 'The daemon cannot preflight these files yet. Update or reconnect it and run `skrr instructions setup`.';
173
+ if (!options.json)
174
+ options.log(result.message);
175
+ return result;
176
+ }
177
+ const preflight = new Map(prepared.providers.map((entry) => [entry.provider, entry]));
178
+ const previews = new Map(prepared.previews.map((entry) => [entry.provider, entry]));
179
+ for (const provider of providers) {
180
+ const placement = preflight.get(provider);
181
+ const preview = previews.get(provider);
182
+ if (!placement?.instructionPath ||
183
+ !preview ||
184
+ (0, node_crypto_1.createHash)('sha256').update(preview.body).digest('hex') !== preview.hash) {
185
+ throw new Error(`The daemon did not return a verified path and exact preview for ${instructionProviderLabel(provider)}; no installation was authorized.`);
186
+ }
187
+ }
188
+ if (!options.json) {
189
+ options.log('');
190
+ options.log(`Managed instructions on ${daemon.deviceName || daemonId} (${daemonId})`);
191
+ options.log('Global scope: these removable blocks apply to future coding-agent sessions across all projects. skrr maintains its block and preserves your other file content.');
192
+ for (const provider of providers) {
193
+ const placement = preflight.get(provider);
194
+ options.log(`${instructionProviderLabel(provider)}: ${placement.instructionPath} (${placement.loadingStatus})`);
195
+ options.log(` Reviewed content SHA-256: ${previews.get(provider).hash}`);
196
+ for (const issue of placement.issues)
197
+ options.log(` ${issue.severity}: ${issue.message}`);
198
+ }
199
+ }
200
+ if (options.review) {
201
+ result.status = 'reviewed';
202
+ if (!options.json)
203
+ for (const provider of providers)
204
+ printPreview(provider, previews.get(provider), options.log);
205
+ return result;
206
+ }
207
+ // Validate all automated placements before creating any target.
208
+ if (options.yes)
209
+ for (const provider of providers) {
210
+ const placement = preflight.get(provider);
211
+ if (!placement.canInstall || placement.loadingStatus === 'shadowed') {
212
+ throw new Error(`Cannot install ${instructionProviderLabel(provider)}: ${placement.issues.map((issue) => issue.message).join(' ') || placement.loadingStatus}. Resolve this and retry; no targets were created.`);
213
+ }
214
+ }
215
+ const install = [];
216
+ for (const provider of providers) {
217
+ const placement = preflight.get(provider);
218
+ if (!placement.canInstall || placement.loadingStatus === 'shadowed')
219
+ continue;
220
+ let answer = options.yes ? 'y' : '';
221
+ const alreadyAccepted = offer.providerOffers?.some((entry) => entry.provider === provider && entry.selected) ||
222
+ offer.targets?.some((target) => target.provider === provider);
223
+ if (!options.yes) {
224
+ options.log(alreadyAccepted
225
+ ? 'y: update installation policy, v: exact preview, n/Enter: keep the current decision'
226
+ : 'y: install, v: exact preview, n/Enter: not now, d: do not ask for this provider');
227
+ answer = (await (0, prompt_1.prompt)(`Set up ${instructionProviderLabel(provider)}? ${alreadyAccepted ? '[y/N/v]' : '[y/N/v/d]'} `)).toLowerCase();
228
+ while (answer === 'v' || answer === 'view') {
229
+ printPreview(provider, previews.get(provider), options.log);
230
+ answer = (await (0, prompt_1.prompt)(`Set up ${instructionProviderLabel(provider)}? ${alreadyAccepted ? '[y/N]' : '[y/N/d]'} `)).toLowerCase();
231
+ }
232
+ }
233
+ const action = answer === 'y' || answer === 'yes'
234
+ ? 'install'
235
+ : alreadyAccepted
236
+ ? 'keep'
237
+ : answer === 'd' || answer === 'decline'
238
+ ? 'decline'
239
+ : 'snooze';
240
+ result.decisions.push({ provider, action });
241
+ if (action === 'install')
242
+ install.push(provider);
243
+ }
244
+ let trackingMode = options.trackingMode;
245
+ if (install.length && !trackingMode) {
246
+ options.log('Automatic updates follow the current saved instruction. Fixed version keeps today’s content; dynamic account identity can still refresh.');
247
+ const answer = (await (0, prompt_1.prompt)('Update policy: automatic [a] or fixed current version [p]? [a/p] ')).toLowerCase();
248
+ if (answer && !['a', 'auto', 'automatic', 'p', 'pin', 'pinned'].includes(answer)) {
249
+ throw new Error('Unknown update policy; no installation was authorized. Run `skrr instructions setup` again.');
250
+ }
251
+ trackingMode = ['p', 'pin', 'pinned'].includes(answer) ? 'pinned' : 'latest';
252
+ }
253
+ if (install.length) {
254
+ const accepted = await data_provider_1.dataService.acceptManagedInstructionOffer(TEMPLATE_KEY, {
255
+ daemonId,
256
+ providers: install,
257
+ trackingMode,
258
+ expectedHash: prepared.preset.hash,
259
+ expectedContentVersion: prepared.preset.contentVersion,
260
+ expectedRenderedHashes: Object.fromEntries(install.map((provider) => [provider, previews.get(provider).hash])),
261
+ });
262
+ result.installed = accepted.targets;
263
+ if (!options.json) {
264
+ options.log(`Installation queued for ${install.map(instructionProviderLabel).join(', ')} (${trackingMode === 'latest' ? 'automatic updates' : 'fixed current version'}).`);
265
+ options.log('`skrr instructions status` confirms the applied path and version. Edits inside the managed block are maintained by skrr; use `skrr instructions update` to customize the saved instruction.');
266
+ }
267
+ }
268
+ for (const action of ['snooze', 'decline']) {
269
+ const declined = result.decisions
270
+ .filter((entry) => entry.action === action)
271
+ .map((entry) => entry.provider);
272
+ if (!declined.length)
273
+ continue;
274
+ await data_provider_1.dataService.respondManagedInstructionOffer(TEMPLATE_KEY, {
275
+ daemonId,
276
+ providers: declined,
277
+ action,
278
+ });
279
+ if (!options.json)
280
+ options.log(`${declined.map(instructionProviderLabel).join(', ')}: ${action === 'snooze' ? 'not now; reminders paused for 14 days' : 'will not ask again'}. Revisit with \`skrr instructions setup --provider ${declined[0]}\`.`);
281
+ }
282
+ result.status = result.decisions.some((entry) => entry.action !== 'keep')
283
+ ? 'decided'
284
+ : 'unchanged';
285
+ return result;
286
+ }
287
+ function printPreview(provider, preview, log) {
288
+ log(`Exact ${instructionProviderLabel(provider)} managed instruction (SHA-256 ${preview.hash}):`);
289
+ log('---');
290
+ log(preview.body);
291
+ log('---');
292
+ }
293
+ /** Optional onboarding must not change the successful login/task exit status. */
294
+ async function maybeOfferManagedInstructionSetup(options) {
295
+ if (shouldSkipInstructionPrompt())
296
+ return;
297
+ try {
298
+ const result = await runManagedInstructionSetup(options);
299
+ if (options.trigger === 'login' && result.status === 'unavailable' && result.message)
300
+ options.log(result.message);
301
+ }
302
+ catch (error) {
303
+ const message = error instanceof Error ? error.message : String(error);
304
+ options.log(`Managed instruction setup could not finish: ${message}. Run \`skrr instructions setup\` when ready.`);
305
+ }
306
+ }
@@ -1,6 +1,7 @@
1
1
  export declare const MEMORY_SYNC_MANIFEST = ".memory-sync";
2
2
  export declare const MEMORY_SYNC_BASIS = ".memory-sync-basis";
3
3
  export declare const MEMORY_SYNC_CONFLICTS = ".memory-conflicts";
4
+ export declare const MEMORY_SYNC_QUARANTINE = ".memory-quarantine";
4
5
  export declare const MEMORY_SYNC_TOMBSTONES = ".memory-tombstones";
5
6
  export interface RemoteMemoryEntry {
6
7
  memoryId: string;