@skrr-ai/cli 0.1.32 → 0.1.34

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 (114) hide show
  1. package/bin/run.js +2 -2
  2. package/dist/base-command.js +5 -0
  3. package/dist/commands/agents/list.d.ts +2 -1
  4. package/dist/commands/agents/list.js +2 -1
  5. package/dist/commands/agents/show.js +2 -1
  6. package/dist/commands/balance/statement.js +8 -4
  7. package/dist/commands/browser/install.js +6 -2
  8. package/dist/commands/browser/uninstall.js +6 -2
  9. package/dist/commands/code/acp.js +2 -1
  10. package/dist/commands/code/doctor.d.ts +1 -1
  11. package/dist/commands/code/doctor.js +6 -5
  12. package/dist/commands/code/handover.d.ts +2 -2
  13. package/dist/commands/code/handover.js +2 -2
  14. package/dist/commands/code/index.d.ts +2 -2
  15. package/dist/commands/code/index.js +18 -17
  16. package/dist/commands/code/install.d.ts +3 -3
  17. package/dist/commands/code/install.js +18 -11
  18. package/dist/commands/code/migrate.js +3 -2
  19. package/dist/commands/code/oversky-agent.d.ts +5 -4
  20. package/dist/commands/code/oversky-agent.js +24 -22
  21. package/dist/commands/code/run.js +2 -1
  22. package/dist/commands/harnesses/list.d.ts +9 -1
  23. package/dist/commands/harnesses/list.js +28 -7
  24. package/dist/commands/harnesses/show.js +7 -2
  25. package/dist/commands/instructions/install.js +16 -6
  26. package/dist/commands/learning/delete.d.ts +9 -0
  27. package/dist/commands/learning/delete.js +40 -0
  28. package/dist/commands/learning/export.d.ts +9 -0
  29. package/dist/commands/learning/export.js +56 -0
  30. package/dist/commands/learning/reset.d.ts +9 -0
  31. package/dist/commands/learning/reset.js +36 -0
  32. package/dist/commands/learning/set.d.ts +10 -0
  33. package/dist/commands/learning/set.js +52 -0
  34. package/dist/commands/learning/status.d.ts +8 -0
  35. package/dist/commands/learning/status.js +35 -0
  36. package/dist/commands/logout.js +10 -5
  37. package/dist/commands/machines/dedicated/attach.js +2 -1
  38. package/dist/commands/tasks/runs.js +3 -1
  39. package/dist/commands/workspaces/use.js +2 -1
  40. package/dist/lib/adaptive-learning.d.ts +37 -0
  41. package/dist/lib/adaptive-learning.js +39 -0
  42. package/dist/lib/auth-core-init.d.ts +23 -0
  43. package/dist/lib/auth-core-init.js +61 -0
  44. package/dist/lib/code-handover.d.ts +1 -1
  45. package/dist/lib/code-handover.js +3 -2
  46. package/dist/lib/config.d.ts +30 -4
  47. package/dist/lib/config.js +2 -1
  48. package/dist/lib/daemon-installer.d.ts +1 -1
  49. package/dist/lib/daemon-target.js +2 -2
  50. package/dist/lib/dedicated-machines.d.ts +2 -2
  51. package/dist/lib/dedicated-machines.js +11 -4
  52. package/dist/lib/exec-runtime-binary.d.ts +2 -2
  53. package/dist/lib/exec-runtime-binary.js +2 -2
  54. package/dist/lib/{sky-code-agent.d.ts → first-party-harness-agent.d.ts} +20 -19
  55. package/dist/lib/{sky-code-agent.js → first-party-harness-agent.js} +85 -47
  56. package/dist/lib/{sky-code-broker.d.ts → first-party-harness-broker.d.ts} +6 -6
  57. package/dist/lib/{sky-code-broker.js → first-party-harness-broker.js} +23 -23
  58. package/dist/lib/{sky-code-doctor.d.ts → first-party-harness-doctor.d.ts} +12 -2
  59. package/dist/lib/{sky-code-doctor.js → first-party-harness-doctor.js} +181 -94
  60. package/dist/lib/{sky-code-managed.d.ts → first-party-harness-managed.d.ts} +55 -30
  61. package/dist/lib/{sky-code-managed.js → first-party-harness-managed.js} +92 -35
  62. package/dist/lib/{sky-code.d.ts → first-party-harness.d.ts} +107 -36
  63. package/dist/lib/{sky-code.js → first-party-harness.js} +172 -73
  64. package/dist/lib/harness-provider-input.d.ts +35 -0
  65. package/dist/lib/harness-provider-input.js +57 -0
  66. package/dist/lib/harness-tiers.d.ts +8 -2
  67. package/dist/lib/harness-tiers.js +11 -6
  68. package/dist/lib/task-instruction-offer.js +10 -4
  69. package/dist/lib/worklogs.js +2 -2
  70. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/configRoot.d.ts +2 -2
  71. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/configRoot.js +2 -2
  72. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.d.ts +248 -0
  73. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.js +361 -0
  74. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.d.ts +147 -0
  75. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.js +180 -0
  76. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessHome.d.ts +111 -0
  77. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessHome.js +314 -0
  78. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.d.ts +11 -5
  79. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.js +14 -7
  80. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +3 -1
  81. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +51 -14
  82. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseManifest.js +1 -1
  83. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +4 -4
  84. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +4 -4
  85. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/configRoot.d.ts +2 -2
  86. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/configRoot.js +2 -2
  87. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.d.ts +248 -0
  88. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.js +332 -0
  89. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.d.ts +147 -0
  90. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.js +170 -0
  91. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessHome.d.ts +111 -0
  92. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessHome.js +303 -0
  93. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.d.ts +11 -5
  94. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.js +14 -7
  95. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +3 -1
  96. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +12 -2
  97. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseManifest.js +1 -1
  98. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +4 -4
  99. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +4 -4
  100. package/dist/node_modules/@skrr-ai/auth-core/package.json +11 -1
  101. package/dist/node_modules/@skrr-ai/data-provider/index.js +4816 -4782
  102. package/dist/node_modules/@skrr-ai/inference-broker/dist/cjs/index.d.ts +1 -1
  103. package/dist/node_modules/@skrr-ai/inference-broker/dist/cjs/index.js +1 -1
  104. package/dist/node_modules/@skrr-ai/inference-broker/dist/cjs/managed-inference-broker.js +1 -1
  105. package/dist/node_modules/@skrr-ai/inference-broker/dist/esm/index.d.ts +1 -1
  106. package/dist/node_modules/@skrr-ai/inference-broker/dist/esm/index.js +1 -1
  107. package/dist/node_modules/@skrr-ai/inference-broker/dist/esm/managed-inference-broker.js +1 -1
  108. package/dist/node_modules/@skrr-ai/inference-broker/package.json +1 -1
  109. package/oclif.manifest.json +34286 -33962
  110. package/package.json +5 -2
  111. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/skyCodeChannels.d.ts +0 -96
  112. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/skyCodeChannels.js +0 -115
  113. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/skyCodeChannels.d.ts +0 -96
  114. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/skyCodeChannels.js +0 -107
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../base-command");
5
+ const api_fetch_1 = require("../../lib/api-fetch");
6
+ const adaptive_learning_1 = require("../../lib/adaptive-learning");
7
+ class LearningStatus extends base_command_1.BaseCommand {
8
+ static description = 'Show adaptive-learning consent, state, and serving fallback';
9
+ static flags = { json: core_1.Flags.boolean({ description: 'Output JSON' }) };
10
+ async run() {
11
+ this.requireAuth();
12
+ const { flags } = await this.parse(LearningStatus);
13
+ let consent;
14
+ let state;
15
+ try {
16
+ [consent, state] = await Promise.all([
17
+ (0, api_fetch_1.apiFetch)('/api/user/adaptive-learning/preferences', {
18
+ credential: this.resolvedCredential,
19
+ }),
20
+ (0, api_fetch_1.apiFetch)('/api/user/adaptive-learning/state', {
21
+ credential: this.resolvedCredential,
22
+ }),
23
+ ]);
24
+ }
25
+ catch (err) {
26
+ this.handleApiError(err);
27
+ }
28
+ if (flags.json) {
29
+ this.log(JSON.stringify({ consent, state }, null, 2));
30
+ return;
31
+ }
32
+ this.log((0, adaptive_learning_1.formatLearningStatus)(consent, state));
33
+ }
34
+ }
35
+ exports.default = LearningStatus;
@@ -37,6 +37,7 @@ exports.shouldSkipLocalLogout = shouldSkipLocalLogout;
37
37
  const core_1 = require("@oclif/core");
38
38
  const base_command_1 = require("../base-command");
39
39
  const config_1 = require("../lib/config");
40
+ const first_party_harness_managed_1 = require("../lib/first-party-harness-managed");
40
41
  const auth_storage_1 = require("../lib/auth-storage");
41
42
  const refresh_1 = require("../lib/refresh");
42
43
  const api_fetch_1 = require("../lib/api-fetch");
@@ -212,10 +213,13 @@ class Logout extends base_command_1.BaseCommand {
212
213
  //
213
214
  // This rebuilds the object rather than deleting keys, which is what strips
214
215
  // the tokens — so every field worth keeping has to be named here, and one
215
- // that is not named is dropped SILENTLY. `skyCodeAgentId` was in exactly
216
- // that position: `skrr code` told users to set it, and the next `skrr logout`
217
- // erased it with no message. It is preserved for the same reason `baseURL`
218
- // and `cliId` are — this machine's settings outlive one session.
216
+ // that is not named is dropped SILENTLY. The `skrr code` agent setting was in
217
+ // exactly that position: `skrr code` told users to set it, and the next
218
+ // `skrr logout` erased it with no message. It is preserved for the same reason
219
+ // `baseURL` and `cliId` are — this machine's settings outlive one session.
220
+ //
221
+ // Read under every key it has had and written back under the neutral one, so a
222
+ // logout on a machine an older CLI configured also finishes that key's move.
219
223
  //
220
224
  // It is re-resolved through the NEXT caller's own roster, so an id they
221
225
  // cannot reach is refused by name rather than silently attributed. That is
@@ -225,10 +229,11 @@ class Logout extends base_command_1.BaseCommand {
225
229
  // would bill it. `skrr code skrr-agent --show` reports the resolved agent
226
230
  // and where it came from, which is the intended way to notice.
227
231
  const cfg = (0, config_1.loadConfig)();
232
+ const agentSetting = (0, first_party_harness_managed_1.readAgentSetting)(cfg);
228
233
  (0, config_1.saveConfig)({
229
234
  baseURL: cfg.baseURL,
230
235
  ...(cfg.cliId ? { cliId: cfg.cliId } : {}),
231
- ...(cfg.skyCodeAgentId ? { skyCodeAgentId: cfg.skyCodeAgentId } : {}),
236
+ ...(agentSetting.value ? { [first_party_harness_managed_1.AGENT_CONFIG_KEY]: agentSetting.value } : {}),
232
237
  ...(cfg.credentials ? { credentials: cfg.credentials } : {}),
233
238
  migrated: { ...(cfg.migrated ?? {}), authOutOfConfig: true },
234
239
  });
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const core_1 = require("@oclif/core");
7
+ const auth_core_1 = require("@skrr-ai/auth-core");
7
8
  const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
8
9
  const dedicated_machines_1 = require("../../../lib/dedicated-machines");
9
10
  const harnesses_1 = require("../../../lib/harnesses");
@@ -40,7 +41,7 @@ class DedicatedMachinesAttach extends dedicated_lease_command_1.DedicatedLeaseCo
40
41
  description: 'Agent to attach. Inside an agent session it defaults to that agent (OVERSKY_SESSION_AGENT_ID).',
41
42
  }),
42
43
  engine: core_1.Flags.string({
43
- description: 'Which engine row to attach when the machine registered several (claude, codex, sky-code). Required only when it is ambiguous.',
44
+ description: `Which engine row to attach when the machine registered several (claude, codex, ${auth_core_1.FIRST_PARTY_HARNESS.provider}, oversky). Required only when it is ambiguous.`,
44
45
  }),
45
46
  'rebind-tasks': core_1.Flags.boolean({
46
47
  description: 'Publish the updated agent release and move dormant assigned task pins to it. Running and finished tasks are never changed.',
@@ -5,6 +5,7 @@ exports.runNeedsFailureReason = runNeedsFailureReason;
5
5
  exports.failureFromRun = failureFromRun;
6
6
  exports.renderRunFailures = renderRunFailures;
7
7
  const core_1 = require("@oclif/core");
8
+ const auth_core_1 = require("@skrr-ai/auth-core");
8
9
  const data_provider_1 = require("@skrr-ai/data-provider");
9
10
  const base_command_1 = require("../../base-command");
10
11
  const format_1 = require("../../lib/format");
@@ -34,7 +35,8 @@ function formatRunExecutor(run) {
34
35
  }
35
36
  const env = run.executionEnvironment;
36
37
  if (typeof env === 'string' && env.trim() !== '') {
37
- return env;
38
+ // Canonical: a run recorded before or after a harness rename prints one name.
39
+ return String((0, auth_core_1.canonicalExecutionEnvironment)(env));
38
40
  }
39
41
  return '-';
40
42
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
+ const auth_core_1 = require("@skrr-ai/auth-core");
4
5
  const base_command_1 = require("../../base-command");
5
6
  const config_1 = require("../../lib/config");
6
7
  const workspaces_1 = require("../../lib/workspaces");
@@ -87,7 +88,7 @@ class WorkspacesUse extends base_command_1.BaseCommand {
87
88
  return;
88
89
  }
89
90
  this.log(`Now working in ${selected.name ?? selected.id} (${selected.id}).`);
90
- this.log('New agents and `skrr code` sessions resolve here. --workspace still wins per command.');
91
+ this.log(`New agents and \`${auth_core_1.FIRST_PARTY_HARNESS.command}\` sessions resolve here. --workspace still wins per command.`);
91
92
  }
92
93
  }
93
94
  exports.default = WorkspacesUse;
@@ -0,0 +1,37 @@
1
+ export interface AdaptiveLearningConsent {
2
+ personalizationAllowed: boolean;
3
+ sharedTrainingAllowed: boolean;
4
+ policyVersion: string;
5
+ source: 'explicit' | 'default_off' | 'workspace_policy' | string;
6
+ stateGeneration: number;
7
+ decidedAt: string | null;
8
+ }
9
+ export interface LearnedPreference {
10
+ key: string;
11
+ value: unknown;
12
+ confidence: number;
13
+ source: 'explicit' | 'inferred' | 'aggregate' | string;
14
+ evidenceCategory: string;
15
+ evidenceCount: number;
16
+ }
17
+ export interface AdaptiveLearningState {
18
+ id: string;
19
+ policyNamespace: string;
20
+ scopeKey: string;
21
+ stateVersion: number;
22
+ modelVersion: string;
23
+ featureViewVersion: string;
24
+ posteriorVersion: string;
25
+ sampleCount: number;
26
+ preferences?: LearnedPreference[];
27
+ }
28
+ export interface AdaptiveLearningStateResponse {
29
+ items: AdaptiveLearningState[];
30
+ count: number;
31
+ }
32
+ export declare function consentPatch(input: {
33
+ personalization?: 'on' | 'off';
34
+ sharedTraining?: 'on' | 'off';
35
+ }): Record<string, boolean>;
36
+ export declare function servingSummary(consent: AdaptiveLearningConsent, state: AdaptiveLearningStateResponse): string;
37
+ export declare function formatLearningStatus(consent: AdaptiveLearningConsent, state: AdaptiveLearningStateResponse): string;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.consentPatch = consentPatch;
4
+ exports.servingSummary = servingSummary;
5
+ exports.formatLearningStatus = formatLearningStatus;
6
+ function consentPatch(input) {
7
+ const patch = {};
8
+ if (input.personalization !== undefined) {
9
+ patch.personalizationAllowed = input.personalization === 'on';
10
+ }
11
+ if (input.sharedTraining !== undefined) {
12
+ patch.sharedTrainingAllowed = input.sharedTraining === 'on';
13
+ }
14
+ return patch;
15
+ }
16
+ function servingSummary(consent, state) {
17
+ if (!consent.personalizationAllowed)
18
+ return 'deterministic baseline (personalization off)';
19
+ if (!state.items.length)
20
+ return 'deterministic baseline (cold start)';
21
+ return 'One Voice authoritative; learned policy is shadow-only';
22
+ }
23
+ function formatLearningStatus(consent, state) {
24
+ const lines = [
25
+ `Personalization: ${consent.personalizationAllowed ? 'on' : 'off'}`,
26
+ `Shared model training: ${consent.sharedTrainingAllowed ? 'on' : 'off'}`,
27
+ `Serving: ${servingSummary(consent, state)}`,
28
+ `Consent: ${consent.source} · ${consent.policyVersion} · generation ${consent.stateGeneration}`,
29
+ `Learned states: ${state.count}`,
30
+ ];
31
+ for (const row of state.items) {
32
+ const recommendation = row.preferences?.find((item) => item.key === 'recommended_action');
33
+ lines.push(`- ${row.policyNamespace} / ${row.scopeKey}: v${row.stateVersion}, samples=${row.sampleCount}` +
34
+ (recommendation
35
+ ? `, recommended=${String(recommendation.value)} (${recommendation.source})`
36
+ : ''));
37
+ }
38
+ return lines.join('\n');
39
+ }
@@ -1,4 +1,26 @@
1
1
  import { type AuthBundle } from './auth-storage';
2
+ type DedicatedGenerationPreparationOptions = {
3
+ machineUuid?: string;
4
+ configDir?: string;
5
+ clearStoredAuth?: () => void;
6
+ clearCredentialEnvelope?: () => Promise<void>;
7
+ clearDeviceIdentity?: () => Promise<void>;
8
+ };
9
+ /**
10
+ * A Dedicated Runtime's workspace survives replacement but `/etc/machine-id`
11
+ * intentionally does not. Linux's fallback KEK is derived from that id, so a
12
+ * CLI credential persisted by the prior instance is unreadable on the next
13
+ * one. The guest never needs that stale authority: its root-owned loopback
14
+ * handoff descriptor mints a fresh CLI credential from the current daemon.
15
+ *
16
+ * Clear only the workload CLI's machine-bound auth artifacts once per runtime
17
+ * generation, before auth-core tries to decrypt them. A cross-process lock is
18
+ * required because terminals and agent tools can launch several `skrr`
19
+ * processes as soon as the guest becomes ready; without it they can clear a
20
+ * sibling's just-enrolled credential. The marker contains identity, not a
21
+ * secret, and stays in the persistent workspace beside the auth files.
22
+ */
23
+ export declare function prepareDedicatedRuntimeAuthGeneration(options?: DedicatedGenerationPreparationOptions): Promise<boolean>;
2
24
  export declare function ensureAuthCoreConfigured(): void;
3
25
  export declare class CliCredentialInitializationError extends Error {
4
26
  readonly code = "CREDENTIAL_INITIALIZATION_UNAVAILABLE";
@@ -42,3 +64,4 @@ export declare function waitForCliCredentialEnvelope(): Promise<void>;
42
64
  /** @internal Test seam — reset the module-level one-shot initialization. */
43
65
  export declare function __resetPrefetchCliAuthForTest(): void;
44
66
  export declare function shouldUseAccessTokenForEnrollment(bundle: Pick<AuthBundle, 'token' | 'expiresAt'> | null | undefined, nowMs?: number, minTtlMs?: number): boolean;
67
+ export {};
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CliCredentialInitializationError = void 0;
7
+ exports.prepareDedicatedRuntimeAuthGeneration = prepareDedicatedRuntimeAuthGeneration;
7
8
  exports.ensureAuthCoreConfigured = ensureAuthCoreConfigured;
8
9
  exports.prefetchCliAuth = prefetchCliAuth;
9
10
  exports.waitForCliCredentialEnvelope = waitForCliCredentialEnvelope;
@@ -33,8 +34,10 @@ exports.shouldUseAccessTokenForEnrollment = shouldUseAccessTokenForEnrollment;
33
34
  * - Fire-and-forget enrollment when an access token is already
34
35
  * present — short-circuits silently on a fresh install before login.
35
36
  */
37
+ const node_fs_1 = __importDefault(require("node:fs"));
36
38
  const node_os_1 = __importDefault(require("node:os"));
37
39
  const node_path_1 = __importDefault(require("node:path"));
40
+ const proper_lockfile_1 = __importDefault(require("proper-lockfile"));
38
41
  const auth_core_1 = require("@skrr-ai/auth-core");
39
42
  const cred_envelope_1 = require("./cred-envelope");
40
43
  const device_identity_1 = require("./device-identity");
@@ -64,6 +67,64 @@ const cliLogger = {
64
67
  * so cross-binary file paths align byte-for-byte.
65
68
  */
66
69
  const DEFAULT_PROFILE = 'default';
70
+ const DEDICATED_AUTH_GENERATION_MARKER = 'dedicated-runtime-auth-generation';
71
+ /**
72
+ * A Dedicated Runtime's workspace survives replacement but `/etc/machine-id`
73
+ * intentionally does not. Linux's fallback KEK is derived from that id, so a
74
+ * CLI credential persisted by the prior instance is unreadable on the next
75
+ * one. The guest never needs that stale authority: its root-owned loopback
76
+ * handoff descriptor mints a fresh CLI credential from the current daemon.
77
+ *
78
+ * Clear only the workload CLI's machine-bound auth artifacts once per runtime
79
+ * generation, before auth-core tries to decrypt them. A cross-process lock is
80
+ * required because terminals and agent tools can launch several `skrr`
81
+ * processes as soon as the guest becomes ready; without it they can clear a
82
+ * sibling's just-enrolled credential. The marker contains identity, not a
83
+ * secret, and stays in the persistent workspace beside the auth files.
84
+ */
85
+ async function prepareDedicatedRuntimeAuthGeneration(options = {}) {
86
+ const machineUuid = String(options.machineUuid ?? process.env.SKRR_MACHINE_UUID ?? '').trim();
87
+ if (!machineUuid.startsWith('dedicated-runtime:'))
88
+ return false;
89
+ const configDir = options.configDir ?? node_path_1.default.join(node_os_1.default.homedir(), '.skrr');
90
+ node_fs_1.default.mkdirSync(configDir, { recursive: true, mode: 0o700 });
91
+ const markerPath = node_path_1.default.join(configDir, DEDICATED_AUTH_GENERATION_MARKER);
92
+ const release = await proper_lockfile_1.default.lock(configDir, {
93
+ lockfilePath: `${markerPath}.lock`,
94
+ realpath: false,
95
+ retries: { retries: 20, minTimeout: 25, maxTimeout: 250 },
96
+ });
97
+ try {
98
+ let recorded = '';
99
+ try {
100
+ recorded = node_fs_1.default.readFileSync(markerPath, 'utf8').trim();
101
+ }
102
+ catch (error) {
103
+ if (error.code !== 'ENOENT')
104
+ throw error;
105
+ }
106
+ if (recorded === machineUuid)
107
+ return false;
108
+ (options.clearStoredAuth ?? auth_storage_1.clearAllBackends)();
109
+ await (options.clearDeviceIdentity ??
110
+ (() => (0, device_identity_1.resetDeviceIdentity)({
111
+ profile: DEFAULT_PROFILE,
112
+ clearOnDisk: true,
113
+ })))();
114
+ await (options.clearCredentialEnvelope ??
115
+ (() => (0, cred_envelope_1.resetCredEnvelope)({
116
+ profile: DEFAULT_PROFILE,
117
+ clearOnDisk: true,
118
+ })))();
119
+ const temporary = `${markerPath}.tmp.${process.pid}.${Date.now()}`;
120
+ node_fs_1.default.writeFileSync(temporary, `${machineUuid}\n`, { mode: 0o600 });
121
+ node_fs_1.default.renameSync(temporary, markerPath);
122
+ return true;
123
+ }
124
+ finally {
125
+ await release();
126
+ }
127
+ }
67
128
  /**
68
129
  * Soft cap so a stuck KEK probe (corrupt keychain, hung native binding)
69
130
  * does not wedge commands on a fresh/plaintext install. Persisted encrypted
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Exported and pure so the parts that decide whether a handover is SAFE are
5
5
  * unit-testable without an oclif runtime, a git checkout, or a live API — the
6
- * convention `buildEngineArgs` follows in `lib/sky-code.ts`. The command itself
6
+ * convention `buildEngineArgs` follows in `lib/first-party-harness.ts`. The command itself
7
7
  * only collects facts and prints.
8
8
  */
9
9
  /** `owner/name` from any GitHub remote URL shape. */
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Exported and pure so the parts that decide whether a handover is SAFE are
6
6
  * unit-testable without an oclif runtime, a git checkout, or a live API — the
7
- * convention `buildEngineArgs` follows in `lib/sky-code.ts`. The command itself
7
+ * convention `buildEngineArgs` follows in `lib/first-party-harness.ts`. The command itself
8
8
  * only collects facts and prints.
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -13,6 +13,7 @@ exports.evaluateHandoverSafety = evaluateHandoverSafety;
13
13
  exports.formatUnsafeHandover = formatUnsafeHandover;
14
14
  exports.composeHandoverPrompt = composeHandoverPrompt;
15
15
  exports.matchAgent = matchAgent;
16
+ const auth_core_1 = require("@skrr-ai/auth-core");
16
17
  /** `owner/name` from any GitHub remote URL shape. */
17
18
  function parseGitHubRepo(remoteUrl) {
18
19
  if (!remoteUrl || !remoteUrl.trim()) {
@@ -69,7 +70,7 @@ function composeHandoverPrompt(input) {
69
70
  input.brief.trim(),
70
71
  '',
71
72
  '---',
72
- `Handed over from a local skrr Code session in ${input.repoFullName} on ${input.branch}${at}.`,
73
+ `Handed over from a local ${auth_core_1.FIRST_PARTY_HARNESS.displayName} session in ${input.repoFullName} on ${input.branch}${at}.`,
73
74
  input.recentCommits ? `Recent commits:\n${input.recentCommits}` : null,
74
75
  input.localWorkNotCarried
75
76
  ? 'NOTE: local uncommitted or unpushed work was NOT carried over — you are working from the pushed state of this branch.'
@@ -33,16 +33,22 @@ export interface CliConfig {
33
33
  * OSK-3892 — the agent a locally-hosted `skrr code` session is attributed to.
34
34
  *
35
35
  * `skrr code` is the local arm of an AGENT's harness: the cloud dispatches to
36
- * sky-code as an agent, and a human running it here runs the same harness. So a
37
- * managed session needs an agent, and this is where a user records the one they
38
- * normally work as instead of typing `--oversky-agent` every time.
36
+ * the first-party harness as an agent, and a human running it here runs the same
37
+ * harness. So a managed session needs an agent, and this is where a user records
38
+ * the one they normally work as instead of typing `--skrr-agent` every time.
39
39
  *
40
40
  * Deliberately NOT a fallback for anything else. It is read only by the managed
41
41
  * acquisition in `skrr code`; every other command keeps its own agent resolution
42
42
  * (`agent-resolver.ts`), whose precedence is different and whose callers are
43
43
  * often inside a daemon session that already binds one.
44
+ *
45
+ * The key is brand-neutral. Earlier CLIs wrote the same setting under a key
46
+ * named after the product; those are still read, through
47
+ * `readAgentSetting` in `first-party-harness-managed.ts`, which is the only
48
+ * reader — never read this field directly, or an older machine's setting is
49
+ * silently ignored.
44
50
  */
45
- skyCodeAgentId?: string;
51
+ firstPartyHarnessAgentId?: string;
46
52
  /**
47
53
  * The workspace this machine works in, chosen once with `skrr workspaces use`.
48
54
  *
@@ -167,6 +173,26 @@ export declare function isEnvAuthOverride(): boolean;
167
173
  * resolver and every existing install read it.
168
174
  */
169
175
  export declare function configRoot(env?: NodeJS.ProcessEnv): string;
176
+ /**
177
+ * The PRE-RENAME config root — the generation between `.sky` and `.skrr`.
178
+ *
179
+ * This was missing from the fallback chain, which went straight from `.skrr` to
180
+ * `.sky` and skipped the directory that every current install actually has.
181
+ * The effect is not a missing preference: with no config found, `loadConfig`
182
+ * returns DEFAULT_CONFIG, whose baseURL is the DEV deployment — so a CLI that
183
+ * had been pointed at production silently starts addressing dev, and its
184
+ * `workspaceId` is gone. Nothing errors; commands just answer about a different
185
+ * backend.
186
+ *
187
+ * This read "the production apex", and said the drift ran the other way. It did
188
+ * not: DEFAULT_CONFIG has been dev since it was written, forty lines further up.
189
+ * The direction matters here more than most stale comments, because it is the
190
+ * difference between a lost session and one that silently addresses production.
191
+ *
192
+ * Note the filename differs by generation: `.sky` used `config.json`, `.oversky`
193
+ * and `.skrr` use `cli-config.json`.
194
+ */
195
+ export declare function priorConfigDir(): string;
170
196
  /**
171
197
  * Read the config file. Returns defaults if missing. Throws on corrupt JSON.
172
198
  * Performs a one-shot legacy → new copy when only the legacy file exists, so
@@ -39,6 +39,7 @@ exports.describeDeployment = describeDeployment;
39
39
  exports.canonicalizeKnownBaseURL = canonicalizeKnownBaseURL;
40
40
  exports.isEnvAuthOverride = isEnvAuthOverride;
41
41
  exports.configRoot = configRoot;
42
+ exports.priorConfigDir = priorConfigDir;
42
43
  exports.loadConfig = loadConfig;
43
44
  exports.saveConfig = saveConfig;
44
45
  exports.getConfigPath = getConfigPath;
@@ -280,7 +281,7 @@ function newConfigDir() {
280
281
  *
281
282
  * Everything else follows the profile, because everything else IS the
282
283
  * deployment: `baseURL`, who you are there (`userId`, `email`), and what you
283
- * chose there (`workspaceId`, `skyCodeAgentId`).
284
+ * chose there (`workspaceId`, `firstPartyHarnessAgentId`).
284
285
  */
285
286
  const MACHINE_SCOPED_KEYS = ['cliId', 'credentials', 'migrated'];
286
287
  /**
@@ -22,7 +22,7 @@ export interface DaemonInstallOptions {
22
22
  fetchImpl?: typeof fetch;
23
23
  /**
24
24
  * Trust anchors. Defaults to the pinned production set; tests substitute a
25
- * generated keypair, exactly as the sky-code installer does. Passing an EMPTY
25
+ * generated keypair, exactly as the first-party harness installer does. Passing an EMPTY
26
26
  * set does not disable verification here — every non-`ok` verdict is a
27
27
  * refusal, so an unconfigured trust root turns installs off rather than
28
28
  * turning checking off.
@@ -49,11 +49,11 @@ exports.listActiveDaemons = listActiveDaemons;
49
49
  const api_fetch_1 = require("./api-fetch");
50
50
  const daemonBroker_1 = require("./daemonBroker");
51
51
  const daemon_ref_1 = require("./daemon-ref");
52
- const sky_code_1 = require("./sky-code");
52
+ const first_party_harness_1 = require("./first-party-harness");
53
53
  function localMachine(options = {}) {
54
54
  const env = options.env ?? process.env;
55
55
  const getuid = 'getuid' in options ? options.getuid : process.getuid?.bind(process);
56
- if (!(0, sky_code_1.isDedicatedRuntimeWorkload)(env, getuid))
56
+ if (!(0, first_party_harness_1.isDedicatedRuntimeWorkload)(env, getuid))
57
57
  return { dedicatedRuntime: false, daemonId: null };
58
58
  return { dedicatedRuntime: true, daemonId: publishedDaemonId(options) };
59
59
  }
@@ -418,8 +418,8 @@ export declare function dedicatedDeletionLines(lease: DedicatedLease, now?: Date
418
418
  * A lease payload names no daemon (provider and daemon ids are deliberately
419
419
  * absent), so the join goes the other way: each row a guest daemon registers
420
420
  * carries `metadata.machineLeaseId` and `metadata.machineProduct`. One daemon
421
- * writes one row PER ENGINE it announces (claude, codex, sky-code, or `oversky`
422
- * when it announces none), all sharing the daemon id.
421
+ * writes one row PER ENGINE it announces (claude, codex, the first-party harness,
422
+ * or `oversky` when it announces none), all sharing the daemon id.
423
423
  */
424
424
  export declare function dedicatedLeaseHarnesses(lease: Pick<DedicatedLease, 'id'>, harnesses: readonly Harness[]): Harness[];
425
425
  /**
@@ -36,6 +36,7 @@ exports.dedicatedCatalogFromProducts = dedicatedCatalogFromProducts;
36
36
  exports.dedicatedRuntimeApiErrorCode = dedicatedRuntimeApiErrorCode;
37
37
  exports.dedicatedRuntimeApiErrorDetails = dedicatedRuntimeApiErrorDetails;
38
38
  exports.formatDedicatedRuntimeApiError = formatDedicatedRuntimeApiError;
39
+ const auth_core_1 = require("@skrr-ai/auth-core");
39
40
  const api_fetch_1 = require("./api-fetch");
40
41
  const edge_error_page_1 = require("./edge-error-page");
41
42
  const harnesses_1 = require("./harnesses");
@@ -622,8 +623,8 @@ function dedicatedDeletionLines(lease, now = new Date()) {
622
623
  * A lease payload names no daemon (provider and daemon ids are deliberately
623
624
  * absent), so the join goes the other way: each row a guest daemon registers
624
625
  * carries `metadata.machineLeaseId` and `metadata.machineProduct`. One daemon
625
- * writes one row PER ENGINE it announces (claude, codex, sky-code, or `oversky`
626
- * when it announces none), all sharing the daemon id.
626
+ * writes one row PER ENGINE it announces (claude, codex, the first-party harness,
627
+ * or `oversky` when it announces none), all sharing the daemon id.
627
628
  */
628
629
  function dedicatedLeaseHarnesses(lease, harnesses) {
629
630
  const seenAt = (harness) => Date.parse(harness.lastSeenAt || '') || 0;
@@ -689,7 +690,9 @@ function selectDedicatedAttachHarness(lease, harnesses, engine) {
689
690
  }
690
691
  const providers = [...new Set(rows.map((row) => row.provider))];
691
692
  if (engine) {
692
- const match = rows.find((row) => row.provider === engine);
693
+ // Any accepted spelling of an engine names it: a user who typed the first-party
694
+ // harness's older name means the row stored under its canonical one.
695
+ const match = rows.find((row) => (0, auth_core_1.isSameHarnessProvider)(row.provider, engine));
693
696
  if (!match) {
694
697
  return {
695
698
  error: `${lease.id} has no "${engine}" engine. Registered: ${providers.join(', ')}.`,
@@ -890,7 +893,11 @@ function formatDedicatedRuntimeApiError(err) {
890
893
  }
891
894
  try {
892
895
  const parsed = JSON.parse(err.body);
893
- const sentence = parsed.message || parsed.error || parsed.code;
896
+ // This formatter is reached only by `machines dedicated *`. Older API
897
+ // replicas and product-neutral action errors may still carry the Hosted
898
+ // Machine noun even though the caller named a Dedicated Runtime. Do not
899
+ // repeat that contradictory product name while a mixed deployment rolls.
900
+ const sentence = (parsed.message || parsed.error || parsed.code)?.replace(/(?:skrr )?Hosted Machine/g, 'Dedicated Runtime');
894
901
  return sentence ? `${sentence}${describeRefusalReasons(err)}` : null;
895
902
  }
896
903
  catch {
@@ -57,8 +57,8 @@ export declare function normalizeRuntimeGlobalArgs(args: readonly string[]): str
57
57
  *
58
58
  * An install instruction is only worth what it installs. Renaming these
59
59
  * before the tap and repository move produces a message that reads correct
60
- * and fails when followed — the same defect as the "install it with
61
- * `sky code install`" hint, which named a command that never existed.
60
+ * and fails when followed — the same defect as the old hint that told users to
61
+ * run `code install` under the previous CLI name, a command that never existed.
62
62
  *
63
63
  * They move when the Homebrew tap is published (that work is tracked
64
64
  * separately) and when the repository is renamed — not before, and not as
@@ -187,8 +187,8 @@ function isExecutable(p) {
187
187
  *
188
188
  * An install instruction is only worth what it installs. Renaming these
189
189
  * before the tap and repository move produces a message that reads correct
190
- * and fails when followed — the same defect as the "install it with
191
- * `sky code install`" hint, which named a command that never existed.
190
+ * and fails when followed — the same defect as the old hint that told users to
191
+ * run `code install` under the previous CLI name, a command that never existed.
192
192
  *
193
193
  * They move when the Homebrew tap is published (that work is tracked
194
194
  * separately) and when the repository is renamed — not before, and not as