sneakoscope 8.1.2 → 8.2.0
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/README.md +96 -58
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/bin/fast-inline.js +5 -51
- package/dist/cli/command-manifest-lite.js +2 -1
- package/dist/cli/command-registry.js +2 -1
- package/dist/cli/global-mode-router.js +1 -1
- package/dist/cli/install-helpers-codex-lb-config.js +112 -914
- package/dist/cli/install-helpers-codex-lb-shared.js +3 -44
- package/dist/cli/install-helpers-install-support.js +4 -20
- package/dist/cli/install-helpers.js +36 -2716
- package/dist/cli/router.js +9 -9
- package/dist/commands/bridge-command-output.js +111 -0
- package/dist/commands/bridge.js +320 -0
- package/dist/commands/codex-app.js +39 -123
- package/dist/commands/doctor-helpers.js +380 -0
- package/dist/commands/doctor-profile.js +3 -0
- package/dist/commands/doctor.js +114 -873
- package/dist/commands/mad-sks.js +0 -4
- package/dist/config/skills-manifest.json +1 -1
- package/dist/core/agents/agent-effort-policy.js +11 -21
- package/dist/core/agents/agent-recursion-guard.js +26 -0
- package/dist/core/agents/agent-runner-codex-exec.js +7 -9
- package/dist/core/architecture-hardening/contracts/contracts.js +225 -161
- package/dist/core/architecture-hardening/state/state-service.js +49 -13
- package/dist/core/auto-review.js +15 -9
- package/dist/core/codex/codex-config-guard.js +8 -0
- package/dist/core/codex-adapter.js +8 -10
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +7 -29
- package/dist/core/codex-app/codex-app-launcher.js +10 -12
- package/dist/core/codex-app/codex-app-restart.js +10 -12
- package/dist/core/codex-app/menubar/constants.js +2 -5
- package/dist/core/codex-app/menubar/global-install.js +3 -2
- package/dist/core/codex-app/menubar/installer/result.js +23 -0
- package/dist/core/codex-app/menubar/installer/runtime.js +28 -0
- package/dist/core/codex-app/menubar/installer.js +5 -96
- package/dist/core/codex-app/menubar/migration.js +1 -42
- package/dist/core/codex-app/openrouter-provider.js +0 -78
- package/dist/core/codex-app.js +97 -360
- package/dist/core/codex-control/codex-app-server-runtime-env.js +8 -28
- package/dist/core/codex-control/codex-current-image-path-real-probe.js +2 -3
- package/dist/core/codex-control/codex-current-web-search-probe.js +2 -3
- package/dist/core/codex-control/codex-sdk-adapter.js +5 -48
- package/dist/core/codex-control/codex-task-runner.js +16 -60
- package/dist/core/codex-control/desktop-bridge-launch-guard.js +227 -0
- package/dist/core/codex-exec-output-schema.js +11 -13
- package/dist/core/codex-lb/bridge-contracts.js +2 -0
- package/dist/core/codex-lb/bridge-runtime-validation/capability.js +104 -0
- package/dist/core/codex-lb/bridge-runtime-validation/catalog.js +52 -0
- package/dist/core/codex-lb/bridge-runtime-validation/shared.js +109 -0
- package/dist/core/codex-lb/bridge-runtime-validation/status.js +250 -0
- package/dist/core/codex-lb/bridge-runtime-validation.js +106 -0
- package/dist/core/codex-lb/capability-runner.js +505 -201
- package/dist/core/codex-lb/codex-lb-env.js +179 -12
- package/dist/core/codex-lb/combined-catalog/builder.js +86 -0
- package/dist/core/codex-lb/combined-catalog/contracts.js +5 -0
- package/dist/core/codex-lb/combined-catalog/normalize.js +170 -0
- package/dist/core/codex-lb/combined-catalog/persistence.js +207 -0
- package/dist/core/codex-lb/combined-catalog/shared.js +12 -0
- package/dist/core/codex-lb/combined-catalog/storage.js +171 -0
- package/dist/core/codex-lb/combined-catalog.js +12 -0
- package/dist/core/codex-lb/desktop-bridge/client.js +4 -1
- package/dist/core/codex-lb/desktop-bridge/header-policy.js +48 -63
- package/dist/core/codex-lb/desktop-bridge/http-forward.js +115 -83
- package/dist/core/codex-lb/desktop-bridge/launchd.js +20 -13
- package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +4 -1
- package/dist/core/codex-lb/desktop-bridge/security.js +381 -267
- package/dist/core/codex-lb/desktop-bridge/server.js +148 -19
- package/dist/core/codex-lb/desktop-bridge/state.js +56 -70
- package/dist/core/codex-lb/desktop-bridge/types.js +6 -1
- package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +281 -106
- package/dist/core/codex-lb/desktop-bridge-migration/historical-config.js +245 -0
- package/dist/core/codex-lb/desktop-bridge-migration/historical-toml.js +56 -0
- package/dist/core/codex-lb/desktop-bridge-migration/metadata.js +73 -0
- package/dist/core/codex-lb/desktop-bridge-migration/receipt.js +52 -0
- package/dist/core/codex-lb/desktop-bridge-migration/retired-runtime-cleanup.js +106 -0
- package/dist/core/codex-lb/desktop-bridge-migration/types.js +1 -0
- package/dist/core/codex-lb/desktop-bridge-migration.js +238 -0
- package/dist/core/codex-lb/desktop-controller-v3/catalog.js +257 -0
- package/dist/core/codex-lb/desktop-controller-v3/diagnostics.js +62 -0
- package/dist/core/codex-lb/desktop-controller-v3/lifecycle-commands.js +203 -0
- package/dist/core/codex-lb/desktop-controller-v3/live-probes.js +293 -0
- package/dist/core/codex-lb/desktop-controller-v3/preflight-probes.js +144 -0
- package/dist/core/codex-lb/desktop-controller-v3/provider-commands.js +182 -0
- package/dist/core/codex-lb/desktop-controller-v3/shared.js +279 -0
- package/dist/core/codex-lb/desktop-controller-v3/status.js +269 -0
- package/dist/core/codex-lb/desktop-controller-v3/types.js +1 -0
- package/dist/core/codex-lb/desktop-controller-v3/verification.js +89 -0
- package/dist/core/codex-lb/desktop-controller-v3.js +67 -0
- package/dist/core/codex-lb/desktop-controller.js +2 -1730
- package/dist/core/codex-lb/desktop-service.js +462 -627
- package/dist/core/codex-lb/migration-receipt.js +560 -118
- package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +37 -53
- package/dist/core/codex-lb/probes/bridge-probe.js +125 -64
- package/dist/core/codex-lb/probes/catalog-probe.js +36 -136
- package/dist/core/codex-lb/probes/computer-use-probe.js +63 -39
- package/dist/core/codex-lb/probes/image-generation-probe.js +98 -41
- package/dist/core/codex-lb/probes/probe-evidence.js +32 -33
- package/dist/core/codex-lb/probes/voice-realtime-probe.js +69 -43
- package/dist/core/codex-lb/provider-credentials/configuration.js +127 -0
- package/dist/core/codex-lb/provider-credentials/locks.js +11 -0
- package/dist/core/codex-lb/provider-credentials/private-snapshot.js +28 -0
- package/dist/core/codex-lb/provider-credentials/removal.js +33 -0
- package/dist/core/codex-lb/provider-credentials/resolution.js +59 -0
- package/dist/core/codex-lb/provider-credentials/runtime.js +55 -0
- package/dist/core/codex-lb/provider-credentials/types.js +1 -0
- package/dist/core/codex-lb/provider-credentials/validation-store.js +137 -0
- package/dist/core/codex-lb/provider-credentials.js +5 -0
- package/dist/core/codex-lb/provider-registry.js +323 -0
- package/dist/core/codex-lb/provider-route-policy.js +118 -0
- package/dist/core/codex-lb/request-route-resolver.js +172 -0
- package/dist/core/codex-lb/route-index.js +148 -0
- package/dist/core/codex-lb/trusted-deep-evidence.js +158 -286
- package/dist/core/commands/basic-cli.js +1 -1
- package/dist/core/commands/check-command.js +3 -10
- package/dist/core/commands/gate-result-contract.js +10 -14
- package/dist/core/commands/intent-normalization/normalizer.js +1 -1
- package/dist/core/commands/mad-sks-command.js +2 -6
- package/dist/core/commands/release-command.js +11 -1
- package/dist/core/commands/telegram-command.js +46 -6
- package/dist/core/doctor/doctor-readiness-matrix.js +9 -7
- package/dist/core/doctor/skill-legacy-surface.js +5 -5
- package/dist/core/evidence/v2/evidence-key.js +30 -3
- package/dist/core/feature-fixtures.js +8 -1
- package/dist/core/feature-registry.js +3 -2
- package/dist/core/hooks-runtime/stop-finalization.js +11 -1
- package/dist/core/hooks-runtime/subagent-context.js +15 -1
- package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +1 -1
- package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
- package/dist/core/hooks-runtime.js +73 -87
- package/dist/core/image-ux-review/imagegen-adapter.js +108 -94
- package/dist/core/image-ux-review/real-callout-extractor.js +144 -14
- package/dist/core/imagegen/desktop-bridge-imagegen-target.js +77 -0
- package/dist/core/imagegen/imagegen-capability.js +43 -151
- package/dist/core/init/skills/filesystem.js +89 -0
- package/dist/core/init/skills/inventory.js +97 -0
- package/dist/core/init/skills/manifest.js +151 -0
- package/dist/core/init/skills.js +5 -325
- package/dist/core/init.js +0 -63
- package/dist/core/install/installed-package-smoke.js +1 -1
- package/dist/core/managed-assets/managed-assets-manifest.js +0 -1
- package/dist/core/policy/latest-version-guidance.js +15 -2
- package/dist/core/preflight/parallel-preflight-engine.js +27 -51
- package/dist/core/provider/provider-badge.js +9 -4
- package/dist/core/provider/provider-context.js +57 -107
- package/dist/core/providers/openrouter/openrouter-account.js +3 -1
- package/dist/core/providers/openrouter/openrouter-secret-store.js +91 -22
- package/dist/core/release/desktop-bridge-release-evidence.js +457 -0
- package/dist/core/release/gate-manifest.js +0 -1
- package/dist/core/release/main-push-guard.js +13 -0
- package/dist/core/release/main-push-receipt.js +11 -0
- package/dist/core/release/physical-release-gates.js +664 -61
- package/dist/core/release/publish-preflight.js +3 -3
- package/dist/core/release/release-gate-batch-runner.js +19 -6
- package/dist/core/release/release-gate-dag.js +33 -6
- package/dist/core/release/release-gate-node.js +1 -3
- package/dist/core/release/release-gate-output-contract.js +55 -0
- package/dist/core/release/release-pack-contract.js +1 -1
- package/dist/core/release/release-pack-receipt.js +209 -8
- package/dist/core/release/release-real-contract.js +1 -1
- package/dist/core/release/stage-publish.js +106 -28
- package/dist/core/retention/temp-lease.js +204 -0
- package/dist/core/retention.js +18 -195
- package/dist/core/routes.js +1 -2
- package/dist/core/safety/intent-contract/intent-contract.js +3 -3
- package/dist/core/subagents/naruto-host-credentials.js +6 -1
- package/dist/core/subagents/official-subagent-config.js +27 -9
- package/dist/core/subagents/official-subagent-runner.js +14 -31
- package/dist/core/subagents/wave-lifecycle.js +36 -8
- package/dist/core/subagents/wave-parent-guidance.js +2 -1
- package/dist/core/telegram/doctor.js +2 -2
- package/dist/core/telegram/liveness.js +10 -4
- package/dist/core/triwiki/context-graph/compiler/index.js +18 -18
- package/dist/core/update/update-migration-state/fast-mode-config.js +172 -0
- package/dist/core/update/update-migration-state/session-state-split.js +247 -0
- package/dist/core/update/update-migration-state/simple-stages.js +46 -0
- package/dist/core/update/update-migration-state.js +4 -481
- package/dist/core/version.js +1 -1
- package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +28 -4
- package/dist/native/sks-menubar/Sources/OperationModels.swift +112 -2
- package/dist/native/sks-menubar/Sources/ProviderRouteExplanation.swift +21 -0
- package/dist/native/sks-menubar/Sources/ProvidersBridgeCatalog.swift +140 -0
- package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +107 -470
- package/dist/native/sks-menubar/Sources/ProvidersReliability.swift +27 -197
- package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +335 -269
- package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +233 -437
- package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +16 -7
- package/dist/native/sks-menubar/Sources/SecureProcessEnvelope.swift +39 -9
- package/dist/native/sks-menubar/Sources/TelegramSupport.swift +56 -0
- package/dist/scripts/canonical-test-runner.js +7 -1
- package/dist/scripts/check-runtime-schemas.js +7 -2
- package/dist/scripts/codex-sdk-real-smoke-check.js +3 -1
- package/dist/scripts/desktop-bridge-capabilities-check.js +123 -0
- package/dist/scripts/{codex-lb-desktop-bridge-latency-check.js → desktop-bridge-latency-check.js} +61 -16
- package/dist/scripts/desktop-bridge-real-evidence-check.js +64 -0
- package/dist/scripts/{codex-lb-desktop-bridge-check.js → desktop-bridge-transport-check.js} +92 -155
- package/dist/scripts/desktop-bridge-transport-client.js +116 -0
- package/dist/scripts/desktop-bridge-unification-check.js +276 -0
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +12 -8
- package/dist/scripts/gate-policy-audit-check.js +52 -2
- package/dist/scripts/provider-badge-context-check.js +55 -12
- package/dist/scripts/publish-preflight.js +1 -2
- package/dist/scripts/release-affected-selector-check.js +1 -2
- package/dist/scripts/release-aggressive-resource-governor-check.js +1 -1
- package/dist/scripts/release-cache-glob-hashing-check.js +1 -0
- package/dist/scripts/release-cache-version-neutral-fixture-check.js +1 -0
- package/dist/scripts/release-full-parallelism-blackbox.js +1 -1
- package/dist/scripts/release-gate-batch-runner-check.js +9 -0
- package/dist/scripts/release-gate-dag-runner-check.js +6 -0
- package/dist/scripts/release-gate-dag-runner.js +4 -2
- package/dist/scripts/release-metadata-check.js +16 -3
- package/dist/scripts/release-pack-receipt.js +29 -6
- package/dist/scripts/release-physical-gates-check.js +39 -0
- package/dist/scripts/release-real-check.js +7 -5
- package/package.json +6 -8
- package/release-gates.v2.json +156 -157
- package/runtime-required-scripts.json +11 -11
- package/schemas/codex/desktop-bridge-status-v3.schema.json +286 -0
- package/schemas/codex/desktop-capabilities-v3.schema.json +198 -0
- package/schemas/release/release-gate-node.schema.json +2 -3
- package/dist/cli/codex-lb-setup-warning-output.js +0 -17
- package/dist/cli/install-helpers-codex-lb-chain.js +0 -529
- package/dist/commands/codex-lb.js +0 -1232
- package/dist/core/architecture-hardening/migration/migration.js +0 -111
- package/dist/core/codex-app/auxiliary-oauth-policy.js +0 -36
- package/dist/core/codex-app/catalog-compat/catalog-service.js +0 -104
- package/dist/core/codex-app/child-policy/child-policy.js +0 -35
- package/dist/core/codex-app/desktop-routing-snapshot.js +0 -233
- package/dist/core/codex-app/glm-model-profile.js +0 -1
- package/dist/core/codex-app/glm-profile-installer.js +0 -191
- package/dist/core/codex-app/glm-profile-schema.js +0 -42
- package/dist/core/codex-app/multi-provider-router.js +0 -391
- package/dist/core/codex-app/openrouter-activate.js +0 -405
- package/dist/core/codex-app/openrouter-model-catalog.js +0 -217
- package/dist/core/codex-app/provider-child-policy.js +0 -64
- package/dist/core/codex-app/provider-mode.js +0 -91
- package/dist/core/codex-app/provider-session-policy.js +0 -85
- package/dist/core/codex-app/session-policy/session-pinning.js +0 -68
- package/dist/core/codex-control/codex-lb-launch-recovery.js +0 -319
- package/dist/core/codex-lb/codex-lb-setup.js +0 -293
- package/dist/core/codex-lb/codex-lb-tool-catalog.js +0 -456
- package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +0 -290
- package/dist/core/codex-lb/desktop-center-credentials.js +0 -1083
- package/dist/core/codex-lb/desktop-mode.js +0 -32
- package/dist/core/codex-lb/desktop-real-evidence.js +0 -168
- package/dist/core/codex-lb/legacy-migration.js +0 -576
- package/dist/core/codex-lb/native-openai-transport/transport.js +0 -68
- package/dist/core/codex-lb/provider-routing/provider-router.js +0 -58
- package/dist/core/codex-lb/routing-truth.js +0 -327
- package/dist/core/imagegen/codex-lb-imagegen-target.js +0 -92
- package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +0 -118
- package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +0 -17
- package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +0 -331
- package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +0 -260
- package/dist/scripts/codex-lb-catalog-passthrough-check.js +0 -120
- package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +0 -169
- package/dist/scripts/codex-lb-desktop-capabilities-check.js +0 -287
- package/dist/scripts/codex-lb-desktop-real-evidence-check.js +0 -123
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +0 -114
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +0 -152
- package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +0 -231
|
@@ -9,15 +9,12 @@ import { MANAGED_ASSET_VERSION } from '../managed-assets/managed-assets-manifest
|
|
|
9
9
|
import { enforceRetention } from '../retention.js';
|
|
10
10
|
import { COMMANDS } from '../../cli/command-registry.js';
|
|
11
11
|
import { reconcileLegacyManagedGeneration } from '../init/legacy-generation-convergence.js';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import { runConfigFastModeNormalizeStage } from './update-migration-state/fast-mode-config.js';
|
|
13
|
+
import { runSessionStateSplitStage } from './update-migration-state/session-state-split.js';
|
|
14
|
+
import { runHookTrustRefreshStage, runOtherHarnessCleanupStage } from './update-migration-state/simple-stages.js';
|
|
14
15
|
import { compareSemVer } from './semver.js';
|
|
15
|
-
import { escapeRegExp } from '../text/regex.js';
|
|
16
|
-
import { sessionStateKey } from '../mission.js';
|
|
17
|
-
import { ensureConfinedDirectory, inspectConfinedPath, moveConfinedPath, uniqueConfinedPath } from '../managed-path-safety.js';
|
|
18
16
|
export const UPDATE_MIGRATION_SCHEMA = 'sks.project-migration-receipt.v2';
|
|
19
17
|
export const INSTALLATION_EPOCH_SCHEMA = 'sks.installation-epoch.v1';
|
|
20
|
-
const LEGACY_CURRENT_STATE_MAX_BYTES = 1024 * 1024;
|
|
21
18
|
export function installationEpochPath() {
|
|
22
19
|
return path.join(globalSksRoot(), 'update', 'installation-epoch.json');
|
|
23
20
|
}
|
|
@@ -191,6 +188,7 @@ export async function runUpdateRetentionCleanup(root, source = 'update-migration
|
|
|
191
188
|
const result = await enforceRetention(root, {
|
|
192
189
|
mode: 'update_migration',
|
|
193
190
|
pruneReportLogs: true,
|
|
191
|
+
skipSksTempSweep: true,
|
|
194
192
|
policy: { max_tmp_age_hours: 0 }
|
|
195
193
|
});
|
|
196
194
|
return {
|
|
@@ -262,37 +260,6 @@ const UPDATE_MIGRATION_STAGES = [
|
|
|
262
260
|
run: runReceiptRotationStage
|
|
263
261
|
}
|
|
264
262
|
];
|
|
265
|
-
async function runOtherHarnessCleanupStage(root) {
|
|
266
|
-
const { scanHarnessConflicts } = await import('../harness-conflicts.js');
|
|
267
|
-
const scan = await scanHarnessConflicts(root);
|
|
268
|
-
if (scan.hard_block) {
|
|
269
|
-
return {
|
|
270
|
-
ok: false,
|
|
271
|
-
status: 'failed',
|
|
272
|
-
actions: ['other_harness_conflict_detected'],
|
|
273
|
-
blockers: scan.hard.map((row) => `other_harness_conflict:${row.path}`),
|
|
274
|
-
warnings: [],
|
|
275
|
-
detail: {
|
|
276
|
-
cleaned_count: 0,
|
|
277
|
-
remaining_count: scan.hard.length,
|
|
278
|
-
error_count: 0,
|
|
279
|
-
cleanup_prompt_command: 'sks conflicts cleanup --yes'
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
return {
|
|
284
|
-
ok: true,
|
|
285
|
-
status: 'ok',
|
|
286
|
-
actions: ['other_harness_conflict_check_clean'],
|
|
287
|
-
blockers: [],
|
|
288
|
-
warnings: [],
|
|
289
|
-
detail: {
|
|
290
|
-
cleaned_count: 0,
|
|
291
|
-
remaining_count: 0,
|
|
292
|
-
error_count: 0
|
|
293
|
-
}
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
263
|
async function runCurrentPublicSurfaceReconcileStage(root) {
|
|
297
264
|
const [{ runDoctorCommandAliasCleanup }, { migrateSksProfilesToPerFile }, { cleanupRetiredRemoteBridgeLaunchAgent, quarantineRetiredRemoteBridgeBindings }] = await Promise.all([
|
|
298
265
|
import('../doctor/command-alias-cleanup.js'),
|
|
@@ -402,242 +369,6 @@ async function runUpdateMigrationStages(root, opts = {}) {
|
|
|
402
369
|
}
|
|
403
370
|
return runs;
|
|
404
371
|
}
|
|
405
|
-
async function runSessionStateSplitStage(root) {
|
|
406
|
-
const legacyCurrent = path.join(root, '.sneakoscope', 'current.json');
|
|
407
|
-
const stateCurrent = path.join(root, '.sneakoscope', 'state', 'current.json');
|
|
408
|
-
const sessionsDir = path.join(root, '.sneakoscope', 'state', 'sessions');
|
|
409
|
-
await ensureConfinedDirectory(root, sessionsDir);
|
|
410
|
-
const actions = [];
|
|
411
|
-
const legacyRead = await readBoundedUpdateState(root, legacyCurrent, { requireLegacyShape: true });
|
|
412
|
-
if (legacyRead.blocker) {
|
|
413
|
-
return {
|
|
414
|
-
ok: false,
|
|
415
|
-
status: 'failed',
|
|
416
|
-
actions: ['legacy_current_state_preserved'],
|
|
417
|
-
blockers: [legacyRead.blocker],
|
|
418
|
-
warnings: [],
|
|
419
|
-
detail: { legacy_present: legacyRead.present }
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
const currentRead = await readBoundedUpdateState(root, stateCurrent);
|
|
423
|
-
if (currentRead.blocker) {
|
|
424
|
-
return {
|
|
425
|
-
ok: false,
|
|
426
|
-
status: 'failed',
|
|
427
|
-
actions: ['current_state_preserved'],
|
|
428
|
-
blockers: [currentRead.blocker],
|
|
429
|
-
warnings: [],
|
|
430
|
-
detail: { legacy_present: legacyRead.present }
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
let current = currentRead.value;
|
|
434
|
-
if (!current && legacyRead.value) {
|
|
435
|
-
current = legacyRead.value;
|
|
436
|
-
await writeJsonAtomic(stateCurrent, current);
|
|
437
|
-
const verified = await readBoundedUpdateState(root, stateCurrent);
|
|
438
|
-
if (verified.blocker || !verified.value || updateStateDigest(verified.value) !== legacyRead.sha256) {
|
|
439
|
-
return {
|
|
440
|
-
ok: false,
|
|
441
|
-
status: 'failed',
|
|
442
|
-
actions: ['copy_legacy_current_json_failed_verification'],
|
|
443
|
-
blockers: [verified.blocker || 'legacy_current_state_copy_verification_failed'],
|
|
444
|
-
warnings: [],
|
|
445
|
-
detail: { legacy_present: true }
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
actions.push('copied_legacy_current_json_to_state_current');
|
|
449
|
-
}
|
|
450
|
-
const missionId = typeof current?.mission_id === 'string' ? current.mission_id : typeof current?.mission === 'string' ? current.mission : null;
|
|
451
|
-
const rawSessionKey = typeof current?._session_key === 'string' && current._session_key.trim()
|
|
452
|
-
? current._session_key
|
|
453
|
-
: null;
|
|
454
|
-
const canonicalSessionKey = rawSessionKey ? sessionStateKey(rawSessionKey) : null;
|
|
455
|
-
if (canonicalSessionKey) {
|
|
456
|
-
const sessionPath = path.join(sessionsDir, `${canonicalSessionKey}.json`);
|
|
457
|
-
const sessionRead = await readBoundedUpdateState(root, sessionPath);
|
|
458
|
-
if (sessionRead.blocker) {
|
|
459
|
-
return {
|
|
460
|
-
ok: false,
|
|
461
|
-
status: 'failed',
|
|
462
|
-
actions,
|
|
463
|
-
blockers: [sessionRead.blocker],
|
|
464
|
-
warnings: [],
|
|
465
|
-
detail: { legacy_present: legacyRead.present, mission_id: missionId, session_key: canonicalSessionKey }
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
if (!sessionRead.present) {
|
|
469
|
-
await writeJsonAtomic(sessionPath, {
|
|
470
|
-
...current,
|
|
471
|
-
_session_key: canonicalSessionKey,
|
|
472
|
-
migrated_from: path.relative(root, stateCurrent),
|
|
473
|
-
migrated_at: nowIso()
|
|
474
|
-
});
|
|
475
|
-
const verifiedSession = await readBoundedUpdateState(root, sessionPath);
|
|
476
|
-
if (verifiedSession.blocker
|
|
477
|
-
|| verifiedSession.value?._session_key !== canonicalSessionKey
|
|
478
|
-
|| verifiedSession.value?.mission_id !== current?.mission_id) {
|
|
479
|
-
return {
|
|
480
|
-
ok: false,
|
|
481
|
-
status: 'failed',
|
|
482
|
-
actions,
|
|
483
|
-
blockers: [verifiedSession.blocker || 'legacy_session_state_copy_verification_failed'],
|
|
484
|
-
warnings: [],
|
|
485
|
-
detail: { legacy_present: legacyRead.present, mission_id: missionId, session_key: canonicalSessionKey }
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
actions.push('wrote_state_session_alias');
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
let quarantinePath = null;
|
|
492
|
-
if (legacyRead.present) {
|
|
493
|
-
const quarantineBase = path.join(root, '.sneakoscope', 'quarantine', 'update-legacy-state', `current-${legacyRead.sha256?.slice(0, 12) || 'unknown'}.json`);
|
|
494
|
-
quarantinePath = await uniqueConfinedPath(root, quarantineBase);
|
|
495
|
-
await moveConfinedPath(root, legacyCurrent, quarantinePath);
|
|
496
|
-
const quarantined = await readBoundedUpdateState(root, quarantinePath, { requireLegacyShape: true });
|
|
497
|
-
const legacyAfter = await inspectConfinedPath(root, legacyCurrent);
|
|
498
|
-
if (legacyAfter.exists
|
|
499
|
-
|| quarantined.blocker
|
|
500
|
-
|| !quarantined.value
|
|
501
|
-
|| quarantined.sha256 !== legacyRead.sha256) {
|
|
502
|
-
const sourceAfter = await inspectConfinedPath(root, legacyCurrent);
|
|
503
|
-
if (!sourceAfter.exists && (await inspectConfinedPath(root, quarantinePath)).exists) {
|
|
504
|
-
await moveConfinedPath(root, quarantinePath, legacyCurrent).catch(() => undefined);
|
|
505
|
-
}
|
|
506
|
-
return {
|
|
507
|
-
ok: false,
|
|
508
|
-
status: 'failed',
|
|
509
|
-
actions: [...actions, 'legacy_current_state_quarantine_rolled_back'],
|
|
510
|
-
blockers: [quarantined.blocker || 'legacy_current_state_quarantine_verification_failed'],
|
|
511
|
-
warnings: [],
|
|
512
|
-
detail: { legacy_present: true, mission_id: missionId }
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
actions.push('quarantined_legacy_current_json');
|
|
516
|
-
}
|
|
517
|
-
if (!actions.length)
|
|
518
|
-
actions.push('session_state_current');
|
|
519
|
-
return {
|
|
520
|
-
ok: true,
|
|
521
|
-
status: 'ok',
|
|
522
|
-
actions,
|
|
523
|
-
blockers: [],
|
|
524
|
-
warnings: [],
|
|
525
|
-
detail: {
|
|
526
|
-
legacy_present: legacyRead.present,
|
|
527
|
-
mission_id: missionId,
|
|
528
|
-
session_key: canonicalSessionKey,
|
|
529
|
-
legacy_quarantine_path: quarantinePath ? path.relative(root, quarantinePath) : null
|
|
530
|
-
}
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
async function readBoundedUpdateState(root, file, opts = {}) {
|
|
534
|
-
let inspected;
|
|
535
|
-
try {
|
|
536
|
-
inspected = await inspectConfinedPath(root, file);
|
|
537
|
-
}
|
|
538
|
-
catch (error) {
|
|
539
|
-
return {
|
|
540
|
-
present: true,
|
|
541
|
-
value: null,
|
|
542
|
-
sha256: null,
|
|
543
|
-
blocker: `update_state_path_unsafe:${error?.code || error?.message || String(error)}`
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
if (!inspected.exists)
|
|
547
|
-
return { present: false, value: null, sha256: null, blocker: null };
|
|
548
|
-
if (inspected.leafSymlink) {
|
|
549
|
-
return { present: true, value: null, sha256: null, blocker: 'update_state_symlink_refused' };
|
|
550
|
-
}
|
|
551
|
-
if (!inspected.stat?.isFile()) {
|
|
552
|
-
return { present: true, value: null, sha256: null, blocker: 'update_state_non_regular_refused' };
|
|
553
|
-
}
|
|
554
|
-
if (inspected.stat.size > LEGACY_CURRENT_STATE_MAX_BYTES) {
|
|
555
|
-
return { present: true, value: null, sha256: null, blocker: 'update_state_size_limit_exceeded' };
|
|
556
|
-
}
|
|
557
|
-
let text;
|
|
558
|
-
let handle = null;
|
|
559
|
-
try {
|
|
560
|
-
const noFollow = process.platform === 'win32' ? 0 : fsConstants.O_NOFOLLOW;
|
|
561
|
-
handle = await fsp.open(file, fsConstants.O_RDONLY | noFollow);
|
|
562
|
-
const before = await handle.stat();
|
|
563
|
-
if (!before.isFile()) {
|
|
564
|
-
return { present: true, value: null, sha256: null, blocker: 'update_state_non_regular_refused' };
|
|
565
|
-
}
|
|
566
|
-
if (before.size > LEGACY_CURRENT_STATE_MAX_BYTES) {
|
|
567
|
-
return { present: true, value: null, sha256: null, blocker: 'update_state_size_limit_exceeded' };
|
|
568
|
-
}
|
|
569
|
-
const buffer = Buffer.alloc(LEGACY_CURRENT_STATE_MAX_BYTES + 1);
|
|
570
|
-
const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
|
|
571
|
-
const after = await handle.stat();
|
|
572
|
-
const pathAfter = await inspectConfinedPath(root, file);
|
|
573
|
-
if (bytesRead > LEGACY_CURRENT_STATE_MAX_BYTES
|
|
574
|
-
|| bytesRead !== before.size
|
|
575
|
-
|| after.size !== before.size
|
|
576
|
-
|| after.dev !== before.dev
|
|
577
|
-
|| after.ino !== before.ino
|
|
578
|
-
|| !pathAfter.exists
|
|
579
|
-
|| pathAfter.leafSymlink
|
|
580
|
-
|| pathAfter.stat?.dev !== after.dev
|
|
581
|
-
|| pathAfter.stat?.ino !== after.ino) {
|
|
582
|
-
return { present: true, value: null, sha256: null, blocker: 'update_state_changed_during_safe_read' };
|
|
583
|
-
}
|
|
584
|
-
text = buffer.subarray(0, bytesRead).toString('utf8');
|
|
585
|
-
}
|
|
586
|
-
catch (error) {
|
|
587
|
-
return {
|
|
588
|
-
present: true,
|
|
589
|
-
value: null,
|
|
590
|
-
sha256: null,
|
|
591
|
-
blocker: `update_state_read_failed:${error?.code || error?.message || String(error)}`
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
finally {
|
|
595
|
-
await handle?.close().catch(() => undefined);
|
|
596
|
-
}
|
|
597
|
-
let value;
|
|
598
|
-
try {
|
|
599
|
-
value = JSON.parse(text);
|
|
600
|
-
}
|
|
601
|
-
catch {
|
|
602
|
-
return { present: true, value: null, sha256: null, blocker: 'update_state_json_invalid' };
|
|
603
|
-
}
|
|
604
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
605
|
-
return { present: true, value: null, sha256: null, blocker: 'update_state_object_required' };
|
|
606
|
-
}
|
|
607
|
-
const record = value;
|
|
608
|
-
if (opts.requireLegacyShape && !isRecognizedLegacyCurrentState(record)) {
|
|
609
|
-
return { present: true, value: null, sha256: null, blocker: 'legacy_current_state_ownership_unproven' };
|
|
610
|
-
}
|
|
611
|
-
return {
|
|
612
|
-
present: true,
|
|
613
|
-
value: record,
|
|
614
|
-
sha256: updateStateDigest(record),
|
|
615
|
-
blocker: null
|
|
616
|
-
};
|
|
617
|
-
}
|
|
618
|
-
function isRecognizedLegacyCurrentState(value) {
|
|
619
|
-
const mission = typeof value.mission_id === 'string'
|
|
620
|
-
? value.mission_id.trim()
|
|
621
|
-
: typeof value.mission === 'string'
|
|
622
|
-
? value.mission.trim()
|
|
623
|
-
: '';
|
|
624
|
-
if (/^M-[A-Za-z0-9][A-Za-z0-9._-]{2,127}$/.test(mission))
|
|
625
|
-
return true;
|
|
626
|
-
const mode = typeof value.mode === 'string' ? value.mode.trim() : '';
|
|
627
|
-
const phase = typeof value.phase === 'string' ? value.phase.trim() : '';
|
|
628
|
-
if (mode === 'IDLE' && phase === 'IDLE')
|
|
629
|
-
return true;
|
|
630
|
-
if (!mode || !phase)
|
|
631
|
-
return false;
|
|
632
|
-
const sessionKey = typeof value._session_key === 'string' && value._session_key.trim().length > 0;
|
|
633
|
-
const routeCommand = typeof value.route_command === 'string' && value.route_command.trim().startsWith('$');
|
|
634
|
-
const managedStopGate = ['stop_gate', 'stop_gate_abs_path']
|
|
635
|
-
.some((key) => typeof value[key] === 'string' && String(value[key]).trim().length > 0);
|
|
636
|
-
return sessionKey || routeCommand || managedStopGate;
|
|
637
|
-
}
|
|
638
|
-
function updateStateDigest(value) {
|
|
639
|
-
return sha256(JSON.stringify(value));
|
|
640
|
-
}
|
|
641
372
|
async function runSkillsReconcileStage(root) {
|
|
642
373
|
if (process.env.SKS_TEST_UPDATE_GLOBAL_SKILLS_FAIL === '1') {
|
|
643
374
|
return {
|
|
@@ -754,83 +485,6 @@ async function runMenubarRetargetStage(root) {
|
|
|
754
485
|
}
|
|
755
486
|
};
|
|
756
487
|
}
|
|
757
|
-
async function runConfigFastModeNormalizeStage() {
|
|
758
|
-
const { reconcileRetiredSksConfigText } = await import('../auto-review.js');
|
|
759
|
-
const configPath = path.join(os.homedir(), '.codex', 'config.toml');
|
|
760
|
-
const text = await readText(configPath, null);
|
|
761
|
-
if (typeof text !== 'string')
|
|
762
|
-
return { ok: true, status: 'ok', actions: ['codex_config_absent'], blockers: [], warnings: [] };
|
|
763
|
-
const normalized = normalizeLegacyFastModeConfigForUpdate(text);
|
|
764
|
-
const retired = reconcileRetiredSksConfigText(normalized.text);
|
|
765
|
-
const nextText = ensureTrailingNewline(retired.text);
|
|
766
|
-
const actions = [
|
|
767
|
-
...normalized.actions,
|
|
768
|
-
...(retired.detected_count > 0 ? ['stripped_retired_sks_config_profiles_and_policies'] : [])
|
|
769
|
-
];
|
|
770
|
-
if (nextText === ensureTrailingNewline(text)) {
|
|
771
|
-
return {
|
|
772
|
-
ok: true,
|
|
773
|
-
status: 'ok',
|
|
774
|
-
actions: actions.length ? actions : ['fastmode_config_current'],
|
|
775
|
-
blockers: [],
|
|
776
|
-
warnings: [],
|
|
777
|
-
detail: {
|
|
778
|
-
config_path: configPath,
|
|
779
|
-
default_profile: normalized.defaultProfile,
|
|
780
|
-
retired_config_detected_count: retired.detected_count
|
|
781
|
-
}
|
|
782
|
-
};
|
|
783
|
-
}
|
|
784
|
-
let guardResult = null;
|
|
785
|
-
guardResult = await writeCodexConfigGuarded({
|
|
786
|
-
configPath,
|
|
787
|
-
before: text,
|
|
788
|
-
mutate: () => nextText,
|
|
789
|
-
cause: 'project-update-fastmode-normalize',
|
|
790
|
-
backupTag: 'project-update-fastmode-normalize',
|
|
791
|
-
preserveFastUiKeys: true
|
|
792
|
-
});
|
|
793
|
-
if (!guardResult.ok) {
|
|
794
|
-
return {
|
|
795
|
-
ok: false,
|
|
796
|
-
status: 'failed',
|
|
797
|
-
actions: ['normalize_fastmode_config_blocked'],
|
|
798
|
-
blockers: [`codex_config_guard:${guardResult.status}`],
|
|
799
|
-
warnings: [],
|
|
800
|
-
detail: {
|
|
801
|
-
config_path: configPath,
|
|
802
|
-
default_profile: normalized.defaultProfile,
|
|
803
|
-
retired_config_detected_count: retired.detected_count,
|
|
804
|
-
guard: guardResult
|
|
805
|
-
}
|
|
806
|
-
};
|
|
807
|
-
}
|
|
808
|
-
return {
|
|
809
|
-
ok: true,
|
|
810
|
-
status: 'ok',
|
|
811
|
-
actions: actions.length ? actions : ['fastmode_config_current'],
|
|
812
|
-
blockers: [],
|
|
813
|
-
warnings: [],
|
|
814
|
-
detail: {
|
|
815
|
-
config_path: configPath,
|
|
816
|
-
default_profile: normalized.defaultProfile,
|
|
817
|
-
retired_config_detected_count: retired.detected_count,
|
|
818
|
-
guard: guardResult
|
|
819
|
-
}
|
|
820
|
-
};
|
|
821
|
-
}
|
|
822
|
-
async function runHookTrustRefreshStage(root) {
|
|
823
|
-
const result = await codexHookTrustDoctor(root, { fix: true, managed: true, actual: true });
|
|
824
|
-
const blockers = result.ok === false ? (result.blockers || ['hook_trust_refresh_failed']) : [];
|
|
825
|
-
return {
|
|
826
|
-
ok: blockers.length === 0,
|
|
827
|
-
status: blockers.length ? 'failed' : 'ok',
|
|
828
|
-
actions: ['refreshed_hook_trust'],
|
|
829
|
-
blockers,
|
|
830
|
-
warnings: result.warnings || [],
|
|
831
|
-
detail: { entries: result.current_hash_count ?? null }
|
|
832
|
-
};
|
|
833
|
-
}
|
|
834
488
|
async function runReceiptRotationStage(root) {
|
|
835
489
|
const receiptPath = projectUpdateMigrationReceiptPath(root);
|
|
836
490
|
const dir = path.dirname(receiptPath);
|
|
@@ -866,137 +520,6 @@ function legacyStageApplies(fromVersion, minFromVersion) {
|
|
|
866
520
|
function compareVersionLike(a, b) {
|
|
867
521
|
return compareSemVer(a, b) ?? 0;
|
|
868
522
|
}
|
|
869
|
-
function insertTopLevelTomlKey(text, line) {
|
|
870
|
-
const raw = String(text || '').trimEnd();
|
|
871
|
-
const firstTable = raw.search(/^\s*\[/m);
|
|
872
|
-
if (firstTable < 0)
|
|
873
|
-
return `${line}\n${raw}`.trim() + '\n';
|
|
874
|
-
return `${raw.slice(0, firstTable).trimEnd()}\n${line}\n\n${raw.slice(firstTable).trimStart()}`.trim() + '\n';
|
|
875
|
-
}
|
|
876
|
-
function normalizeLegacyFastModeConfigForUpdate(text) {
|
|
877
|
-
let next = String(text || '');
|
|
878
|
-
const actions = [];
|
|
879
|
-
const misplaced = tomlTableString(next, 'user.fast_mode', 'default_profile');
|
|
880
|
-
const topLevel = topLevelTomlString(next, 'default_profile');
|
|
881
|
-
const legacyFastDefault = misplaced === 'sks-fast-high' || topLevel === 'sks-fast-high';
|
|
882
|
-
const before = next;
|
|
883
|
-
next = removeTopLevelTomlKeyLocal(next, 'default_profile');
|
|
884
|
-
next = removeTomlTableLocal(next, 'user.fast_mode');
|
|
885
|
-
next = removeTomlTableLocal(next, 'profiles.sks-fast-high');
|
|
886
|
-
next = removeTomlTableKeyLocal(next, 'notice', 'fast_default_opt_out');
|
|
887
|
-
if (next !== before)
|
|
888
|
-
actions.push('stripped_removed_fastmode_config_schema_keys');
|
|
889
|
-
if (legacyFastDefault && !topLevelTomlString(next, 'service_tier')) {
|
|
890
|
-
next = insertTopLevelTomlKey(next, 'service_tier = "fast"');
|
|
891
|
-
actions.push('migrated_legacy_fast_default_to_service_tier');
|
|
892
|
-
}
|
|
893
|
-
return { text: ensureTrailingNewline(next), actions, defaultProfile: misplaced || topLevel };
|
|
894
|
-
}
|
|
895
|
-
function removeTopLevelTomlKeyLocal(text, key) {
|
|
896
|
-
const lines = String(text || '').split('\n');
|
|
897
|
-
const firstTable = lines.findIndex((x) => /^\s*\[.+\]\s*$/.test(x));
|
|
898
|
-
const end = firstTable === -1 ? lines.length : firstTable;
|
|
899
|
-
const keyPattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`);
|
|
900
|
-
return lines.filter((line, index) => index >= end || !keyPattern.test(line)).join('\n').replace(/^\n+/, '').replace(/\n{3,}/g, '\n\n');
|
|
901
|
-
}
|
|
902
|
-
function removeTomlTableLocal(text, table) {
|
|
903
|
-
const lines = String(text || '').trimEnd().split('\n');
|
|
904
|
-
const header = `[${table}]`;
|
|
905
|
-
const start = lines.findIndex((x) => x.trim() === header);
|
|
906
|
-
if (start === -1)
|
|
907
|
-
return String(text || '');
|
|
908
|
-
let end = lines.length;
|
|
909
|
-
for (let i = start + 1; i < lines.length; i += 1) {
|
|
910
|
-
const ln = lines[i];
|
|
911
|
-
if (ln !== undefined && /^\s*\[.+\]\s*$/.test(ln)) {
|
|
912
|
-
end = i;
|
|
913
|
-
break;
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
return lines.filter((_, index) => index < start || index >= end).join('\n').replace(/^\n+/, '').replace(/\n{3,}/g, '\n\n');
|
|
917
|
-
}
|
|
918
|
-
function tomlTableString(text, table, key) {
|
|
919
|
-
const block = tomlTableBlock(text, table);
|
|
920
|
-
const match = block?.match(new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*"([^"]*)"\\s*$`, 'm'));
|
|
921
|
-
return match?.[1] || null;
|
|
922
|
-
}
|
|
923
|
-
function topLevelTomlString(text, key) {
|
|
924
|
-
const source = String(text || '');
|
|
925
|
-
const firstTable = source.search(/^\s*\[/m);
|
|
926
|
-
const top = firstTable < 0 ? source : source.slice(0, firstTable);
|
|
927
|
-
const match = top.match(new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*"([^"]*)"\\s*$`, 'm'));
|
|
928
|
-
return match?.[1] || null;
|
|
929
|
-
}
|
|
930
|
-
function tomlTableBlock(text, table) {
|
|
931
|
-
const lines = String(text || '').split(/\r?\n/);
|
|
932
|
-
const start = lines.findIndex((line) => tableHeaderMatches(line, table));
|
|
933
|
-
if (start < 0)
|
|
934
|
-
return null;
|
|
935
|
-
let end = lines.length;
|
|
936
|
-
for (let index = start + 1; index < lines.length; index += 1) {
|
|
937
|
-
if (/^\s*\[[^\]]+\]\s*$/.test(lines[index] || '')) {
|
|
938
|
-
end = index;
|
|
939
|
-
break;
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
return lines.slice(start, end).join('\n');
|
|
943
|
-
}
|
|
944
|
-
function removeTomlTableKeyLocal(text, table, key) {
|
|
945
|
-
const lines = String(text || '').split(/\r?\n/);
|
|
946
|
-
let inTable = false;
|
|
947
|
-
const out = [];
|
|
948
|
-
for (const line of lines) {
|
|
949
|
-
if (/^\s*\[[^\]]+\]\s*$/.test(line))
|
|
950
|
-
inTable = tableHeaderMatches(line, table);
|
|
951
|
-
if (inTable && new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`).test(line))
|
|
952
|
-
continue;
|
|
953
|
-
out.push(line);
|
|
954
|
-
}
|
|
955
|
-
return out.join('\n');
|
|
956
|
-
}
|
|
957
|
-
function upsertTomlTableKeyIfAbsentLocal(text, table, line) {
|
|
958
|
-
const key = tomlLineKey(line);
|
|
959
|
-
return tomlTableHasKey(text, table, key) ? text : upsertTomlTableKeyLocal(text, table, line);
|
|
960
|
-
}
|
|
961
|
-
function upsertTomlTableKeyLocal(text, table, line) {
|
|
962
|
-
const raw = String(text || '').trimEnd();
|
|
963
|
-
const key = tomlLineKey(line);
|
|
964
|
-
const lines = raw ? raw.split(/\r?\n/) : [];
|
|
965
|
-
const start = lines.findIndex((candidate) => tableHeaderMatches(candidate, table));
|
|
966
|
-
if (start < 0) {
|
|
967
|
-
return `${raw}${raw ? '\n\n' : ''}[${table}]\n${line}\n`;
|
|
968
|
-
}
|
|
969
|
-
let end = lines.length;
|
|
970
|
-
for (let index = start + 1; index < lines.length; index += 1) {
|
|
971
|
-
if (/^\s*\[[^\]]+\]\s*$/.test(lines[index] || '')) {
|
|
972
|
-
end = index;
|
|
973
|
-
break;
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
for (let index = start + 1; index < end; index += 1) {
|
|
977
|
-
if (new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`).test(lines[index] || '')) {
|
|
978
|
-
if (lines[index] === line)
|
|
979
|
-
return `${lines.join('\n')}\n`;
|
|
980
|
-
lines[index] = line;
|
|
981
|
-
return `${lines.join('\n')}\n`;
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
lines.splice(end, 0, line);
|
|
985
|
-
return `${lines.join('\n')}\n`;
|
|
986
|
-
}
|
|
987
|
-
function tomlTableHasKey(text, table, key) {
|
|
988
|
-
const block = tomlTableBlock(text, table);
|
|
989
|
-
return Boolean(block && new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`, 'm').test(block));
|
|
990
|
-
}
|
|
991
|
-
function tableHeaderMatches(line, table) {
|
|
992
|
-
return new RegExp(`^\\s*\\[${escapeRegExp(table)}\\]\\s*$`).test(line || '');
|
|
993
|
-
}
|
|
994
|
-
function tomlLineKey(line) {
|
|
995
|
-
return String(line || '').split('=')[0]?.trim() || '';
|
|
996
|
-
}
|
|
997
|
-
function ensureTrailingNewline(text) {
|
|
998
|
-
return `${String(text || '').trim()}\n`;
|
|
999
|
-
}
|
|
1000
523
|
export async function ensureCurrentMigrationBeforeCommand(input) {
|
|
1001
524
|
const env = input.env || process.env;
|
|
1002
525
|
const command = input.command;
|
package/dist/core/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const PACKAGE_VERSION = '8.
|
|
1
|
+
export const PACKAGE_VERSION = '8.2.0';
|
|
@@ -40,7 +40,7 @@ final class OperationCoordinator {
|
|
|
40
40
|
state: .queued, stage: "queued", progress: 0, startedAt: now,
|
|
41
41
|
updatedAt: now, publicSummary: summary, logPath: AppRuntime.lastActionLogPath,
|
|
42
42
|
retryable: true, targetVersion: targetVersion, projectRoot: projectRoot,
|
|
43
|
-
registry: registry, recovery: nil, providerApply: providerApply
|
|
43
|
+
registry: registry, recovery: nil, providerApply: providerApply, diagnostic: nil
|
|
44
44
|
)
|
|
45
45
|
if let group = mutationGroup { activeMutation = (snapshot.id, group) }
|
|
46
46
|
write(snapshot)
|
|
@@ -65,7 +65,7 @@ final class OperationCoordinator {
|
|
|
65
65
|
publicSummary: summary, logPath: snapshot.logPath, retryable: retryable,
|
|
66
66
|
targetVersion: snapshot.targetVersion, projectRoot: snapshot.projectRoot,
|
|
67
67
|
registry: snapshot.registry, recovery: snapshot.recovery,
|
|
68
|
-
providerApply: snapshot.providerApply
|
|
68
|
+
providerApply: snapshot.providerApply, diagnostic: snapshot.diagnostic
|
|
69
69
|
)
|
|
70
70
|
write(next)
|
|
71
71
|
if releaseMutationGuard, [.succeeded, .failed, .cancelled, .terminalUncertain].contains(state) {
|
|
@@ -118,7 +118,7 @@ final class OperationCoordinator {
|
|
|
118
118
|
retryable: status.state == .autoResumePending || status.state == .pausedResumable,
|
|
119
119
|
targetVersion: snapshot.targetVersion, projectRoot: snapshot.projectRoot,
|
|
120
120
|
registry: snapshot.registry, recovery: status,
|
|
121
|
-
providerApply: snapshot.providerApply
|
|
121
|
+
providerApply: snapshot.providerApply, diagnostic: snapshot.diagnostic
|
|
122
122
|
)
|
|
123
123
|
write(next)
|
|
124
124
|
if status.state == .pausedResumable, activeMutation?.id == snapshot.id {
|
|
@@ -153,7 +153,7 @@ final class OperationCoordinator {
|
|
|
153
153
|
retryable: projection.failedStage != nil,
|
|
154
154
|
targetVersion: snapshot.targetVersion, projectRoot: snapshot.projectRoot,
|
|
155
155
|
registry: snapshot.registry, recovery: snapshot.recovery,
|
|
156
|
-
providerApply: projection
|
|
156
|
+
providerApply: projection, diagnostic: snapshot.diagnostic
|
|
157
157
|
)
|
|
158
158
|
write(next)
|
|
159
159
|
if (nextState == .waitingForConfirmation || nextState == .succeeded)
|
|
@@ -164,6 +164,30 @@ final class OperationCoordinator {
|
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
/// Persists only the non-secret diagnostic identity/readiness projection on
|
|
168
|
+
/// the operation receipt. The CLI report body and provider credentials never
|
|
169
|
+
/// enter the operation store.
|
|
170
|
+
func recordDiagnostic(
|
|
171
|
+
_ snapshot: OperationSnapshot,
|
|
172
|
+
metadata: DiagnosticOperationMetadata
|
|
173
|
+
) -> OperationSnapshot {
|
|
174
|
+
queue.sync {
|
|
175
|
+
let next = OperationSnapshot(
|
|
176
|
+
schema: snapshot.schema, id: snapshot.id, kind: snapshot.kind,
|
|
177
|
+
state: snapshot.state, stage: snapshot.stage, progress: snapshot.progress,
|
|
178
|
+
startedAt: snapshot.startedAt,
|
|
179
|
+
updatedAt: ISO8601DateFormatter().string(from: Date()),
|
|
180
|
+
publicSummary: snapshot.publicSummary, logPath: snapshot.logPath,
|
|
181
|
+
retryable: snapshot.retryable, targetVersion: snapshot.targetVersion,
|
|
182
|
+
projectRoot: snapshot.projectRoot, registry: snapshot.registry,
|
|
183
|
+
recovery: snapshot.recovery, providerApply: snapshot.providerApply,
|
|
184
|
+
diagnostic: metadata
|
|
185
|
+
)
|
|
186
|
+
write(next)
|
|
187
|
+
return next
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
167
191
|
/// Executes one caller-declared retry-safe operation. The exact same closure
|
|
168
192
|
/// may be re-entered only for a transient network classification and at most
|
|
169
193
|
/// twice. Authentication, provider mode, account binding, external settings,
|