sneakoscope 7.3.0 → 7.6.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 +129 -10
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/cli/codex-app-command.js +1 -1
- package/dist/cli/command-manifest-lite.js +4 -1
- package/dist/cli/command-registry.js +2 -0
- package/dist/cli/install-helpers-codex-lb-chain.js +42 -0
- package/dist/cli/install-helpers-codex-lb-config.js +114 -9
- package/dist/cli/install-helpers-install-support.js +6 -16
- package/dist/cli/install-helpers.js +788 -600
- package/dist/cli/router.js +30 -2
- package/dist/commands/codex-app.js +37 -1
- package/dist/commands/codex-lb.js +491 -300
- package/dist/config/skills-manifest.json +57 -71
- package/dist/core/align/align-route.js +127 -0
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +8 -4
- package/dist/core/codex-app/codex-app-restart.js +83 -0
- package/dist/core/codex-app/codex-app-ui-state-snapshot.js +8 -4
- package/dist/core/codex-app/desktop-routing-snapshot.js +1 -1
- package/dist/core/codex-app/menubar/constants.js +5 -0
- package/dist/core/codex-app/menubar/generation-transaction-journal.js +1 -3
- package/dist/core/codex-app/menubar/installer.js +18 -0
- package/dist/core/codex-app/multi-provider-router.js +22 -10
- package/dist/core/codex-app/openrouter-activate.js +26 -1
- package/dist/core/codex-app.js +118 -26
- package/dist/core/codex-control/codex-app-server-runtime-env.js +86 -0
- package/dist/core/codex-control/codex-app-server-v2-client.js +78 -8
- package/dist/core/codex-control/codex-task-runner.js +2 -2
- package/dist/core/codex-lb/capability-runner.js +204 -0
- package/dist/core/codex-lb/capability-types.js +1 -0
- package/dist/core/codex-lb/codex-lb-env.js +9 -13
- package/dist/core/codex-lb/codex-lb-setup.js +45 -8
- package/dist/core/codex-lb/codex-lb-tool-catalog.js +52 -74
- package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +1 -1
- package/dist/core/codex-lb/desktop-auth-invariant.js +185 -0
- package/dist/core/codex-lb/desktop-bridge/client.js +34 -0
- package/dist/core/codex-lb/desktop-bridge/header-policy.js +106 -0
- package/dist/core/codex-lb/desktop-bridge/http-forward.js +101 -0
- package/dist/core/codex-lb/desktop-bridge/index.js +10 -0
- package/dist/core/codex-lb/desktop-bridge/launchd.js +81 -0
- package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +27 -0
- package/dist/core/codex-lb/desktop-bridge/security.js +274 -0
- package/dist/core/codex-lb/desktop-bridge/server.js +179 -0
- package/dist/core/codex-lb/desktop-bridge/state.js +119 -0
- package/dist/core/codex-lb/desktop-bridge/types.js +16 -0
- package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +151 -0
- package/dist/core/codex-lb/desktop-center-credentials.js +189 -0
- package/dist/core/codex-lb/desktop-controller.js +1410 -0
- package/dist/core/codex-lb/desktop-mode.js +32 -0
- package/dist/core/codex-lb/desktop-real-evidence.js +168 -0
- package/dist/core/codex-lb/desktop-service.js +613 -0
- package/dist/core/codex-lb/legacy-migration.js +575 -0
- package/dist/core/codex-lb/migration-receipt.js +246 -0
- package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +60 -0
- package/dist/core/codex-lb/probes/bridge-probe.js +75 -0
- package/dist/core/codex-lb/probes/catalog-probe.js +128 -0
- package/dist/core/codex-lb/probes/computer-use-probe.js +50 -0
- package/dist/core/codex-lb/probes/image-generation-probe.js +47 -0
- package/dist/core/codex-lb/probes/probe-evidence.js +39 -0
- package/dist/core/codex-lb/probes/voice-realtime-probe.js +44 -0
- package/dist/core/codex-lb/trusted-deep-evidence.js +403 -0
- package/dist/core/codex-native/core-skill-manifest.js +22 -6
- package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -1
- package/dist/core/commands/align-command.js +220 -0
- package/dist/core/commands/image-ux-review-command.js +280 -68
- package/dist/core/commands/naruto-command.js +257 -8
- package/dist/core/commands/ppt-command.js +2 -2
- package/dist/core/commands/telegram-command.js +402 -34
- package/dist/core/commands/triwiki-command.js +11 -1
- package/dist/core/commands/triwiki-graph-command.js +160 -0
- package/dist/core/commands/wiki-command.js +100 -20
- package/dist/core/doctor/skill-legacy-surface.js +1 -3
- package/dist/core/errors/message.js +3 -0
- package/dist/core/evidence/evidence-freshness.js +14 -0
- package/dist/core/feature-fixtures.js +9 -1
- package/dist/core/feature-registry.js +5 -3
- package/dist/core/fsx.js +7 -3
- package/dist/core/hooks-runtime/codex-commit-hooks-selftest.js +82 -0
- package/dist/core/hooks-runtime/context-graph-freshness-preflight.js +113 -0
- package/dist/core/hooks-runtime/hook-context.js +15 -2
- package/dist/core/hooks-runtime/managed-skill-generation-heal.js +46 -0
- package/dist/core/hooks-runtime/naruto-terminal-finalization.js +1 -0
- package/dist/core/hooks-runtime/official-subagent-lifecycle.js +1 -1
- package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
- package/dist/core/hooks-runtime.js +33 -89
- package/dist/core/image-ux-review/callout-extraction.js +6 -0
- package/dist/core/image-ux-review/imagegen-adapter.js +64 -23
- package/dist/core/image-ux-review/real-callout-extractor.js +1 -0
- package/dist/core/image-ux-review.js +230 -12
- package/dist/core/imagegen/codex-lb-imagegen-target.js +21 -7
- package/dist/core/imagegen/imagegen-capability.js +10 -4
- package/dist/core/imagegen/require-imagegen.js +29 -5
- package/dist/core/init/skills.js +25 -13
- package/dist/core/init.js +1 -1
- package/dist/core/install/installed-package-smoke.js +157 -4
- package/dist/core/managed-assets/managed-assets-manifest.js +2 -1
- package/dist/core/managed-path-safety.js +8 -10
- package/dist/core/mcp-config/backup.js +2 -4
- package/dist/core/mcp-config/config-reader.js +2 -4
- package/dist/core/mcp-config/scope.js +3 -5
- package/dist/core/naruto/context-graph-advisor-scope.js +242 -0
- package/dist/core/naruto/context-graph-advisor.js +0 -0
- package/dist/core/perf/release-latency-slo.js +12 -6
- package/dist/core/pipeline-internals/runtime-core.js +78 -0
- package/dist/core/pipeline-internals/runtime-gates.js +5 -2
- package/dist/core/policy/latest-version-guidance.js +113 -0
- package/dist/core/ppt.js +8 -8
- package/dist/core/preflight/parallel-preflight-engine.js +1 -1
- package/dist/core/proof/auto-finalize.js +98 -6
- package/dist/core/proof/route-proof-gate.js +12 -1
- package/dist/core/proof/route-proof-policy.js +8 -8
- package/dist/core/release/gate-manifest.js +32 -1
- package/dist/core/release/npm-stage-contract.js +21 -0
- package/dist/core/release/package-size-budget.js +2 -2
- package/dist/core/release/release-gate-contract.js +5 -0
- package/dist/core/release/release-proof-io.js +1 -3
- package/dist/core/release/release-real-contract.js +5 -4
- package/dist/core/release/release-stamp-proof.js +1 -3
- package/dist/core/release/stage-publish.js +27 -0
- package/dist/core/remote/audit-idempotency.js +50 -18
- package/dist/core/remote/codex-public-activity.js +283 -0
- package/dist/core/remote/index.js +1 -0
- package/dist/core/remote/ssh-worker-client.js +4 -1
- package/dist/core/remote/worker.js +206 -27
- package/dist/core/research/research-adversarial-review.js +1 -3
- package/dist/core/research/research-claim-synthesizer.js +1 -3
- package/dist/core/research/research-falsification-runner.js +1 -3
- package/dist/core/research/research-source-evidence.js +1 -3
- package/dist/core/responses-stream.js +65 -19
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/design-policy.js +7 -2
- package/dist/core/routes/dollar-manifest-lite.js +2 -4
- package/dist/core/routes/evidence.js +1 -1
- package/dist/core/routes.js +30 -10
- package/dist/core/safety/command-contract/contracts.js +2 -0
- package/dist/core/safety/command-contract/types.js +1 -1
- package/dist/core/search/context-graph-seeds.js +205 -0
- package/dist/core/search/context.js +0 -0
- package/dist/core/search/provider.js +2 -2
- package/dist/core/secret-redaction.js +6 -0
- package/dist/core/subagents/naruto-help-contract.js +2 -1
- package/dist/core/subagents/naruto-host-credentials.js +161 -0
- package/dist/core/subagents/official-subagent-preparation.js +4 -1
- package/dist/core/subagents/official-subagent-prompt.js +44 -2
- package/dist/core/subagents/official-subagent-runner.js +26 -8
- package/dist/core/subagents/triwiki-attention.js +135 -123
- package/dist/core/telegram/bot-api.js +85 -10
- package/dist/core/telegram/center-snapshot.js +718 -0
- package/dist/core/telegram/config.js +158 -31
- package/dist/core/telegram/hub.js +288 -33
- package/dist/core/telegram/index.js +2 -0
- package/dist/core/telegram/ingress-spool.js +419 -0
- package/dist/core/telegram/ledgers.js +188 -29
- package/dist/core/telegram/messages.js +26 -6
- package/dist/core/telegram/owner-lock.js +10 -7
- package/dist/core/telegram/runtime-projection.js +38 -3
- package/dist/core/telegram/runtime.js +298 -63
- package/dist/core/telegram/service.js +137 -8
- package/dist/core/telegram/setup.js +291 -73
- package/dist/core/text/strings.js +3 -0
- package/dist/core/triwiki/code-pack.js +12 -120
- package/dist/core/triwiki/context-graph/compiler/cache-key.js +277 -0
- package/dist/core/triwiki/context-graph/compiler/extract.js +104 -0
- package/dist/core/triwiki/context-graph/compiler/freshness.js +108 -0
- package/dist/core/triwiki/context-graph/compiler/index.js +237 -0
- package/dist/core/triwiki/context-graph/compiler/merge.js +0 -0
- package/dist/core/triwiki/context-graph/compiler/serialize.js +115 -0
- package/dist/core/triwiki/context-graph/contracts.js +236 -0
- package/dist/core/triwiki/context-graph/extractors/code/builders.js +150 -0
- package/dist/core/triwiki/context-graph/extractors/code/declarations.js +161 -0
- package/dist/core/triwiki/context-graph/extractors/code/index.js +265 -0
- package/dist/core/triwiki/context-graph/extractors/code/inventory.js +237 -0
- package/dist/core/triwiki/context-graph/extractors/code/module-graph.js +252 -0
- package/dist/core/triwiki/context-graph/extractors/code/modules.js +79 -0
- package/dist/core/triwiki/context-graph/extractors/code/references.js +184 -0
- package/dist/core/triwiki/context-graph/extractors/code/selection.js +100 -0
- package/dist/core/triwiki/context-graph/extractors/code/ts-config.js +161 -0
- package/dist/core/triwiki/context-graph/extractors/code/types.js +18 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/claims.js +289 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/index.js +54 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/proof-index.js +213 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/proofs.js +266 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/redaction.js +177 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/shared.js +0 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/sources.js +154 -0
- package/dist/core/triwiki/context-graph/extractors/index.js +7 -0
- package/dist/core/triwiki/context-graph/extractors/topology/commands.js +207 -0
- package/dist/core/triwiki/context-graph/extractors/topology/gate-edges.js +201 -0
- package/dist/core/triwiki/context-graph/extractors/topology/gates.js +182 -0
- package/dist/core/triwiki/context-graph/extractors/topology/globs.js +124 -0
- package/dist/core/triwiki/context-graph/extractors/topology/index.js +92 -0
- package/dist/core/triwiki/context-graph/extractors/topology/routes.js +135 -0
- package/dist/core/triwiki/context-graph/extractors/topology/shared.js +215 -0
- package/dist/core/triwiki/context-graph/graph-index.js +143 -0
- package/dist/core/triwiki/context-graph/ids.js +0 -0
- package/dist/core/triwiki/context-graph/lint/index.js +0 -0
- package/dist/core/triwiki/context-graph/lint/rules.js +232 -0
- package/dist/core/triwiki/context-graph/lint/warnings.js +93 -0
- package/dist/core/triwiki/context-graph/paths.js +116 -0
- package/dist/core/triwiki/context-graph/profiles.js +78 -0
- package/dist/core/triwiki/context-graph/projections/anchors.js +91 -0
- package/dist/core/triwiki/context-graph/projections/attention.js +58 -0
- package/dist/core/triwiki/context-graph/projections/code-pack-workspace.js +62 -0
- package/dist/core/triwiki/context-graph/projections/code-pack.js +144 -0
- package/dist/core/triwiki/context-graph/projections/index.js +7 -0
- package/dist/core/triwiki/context-graph/projections/module-view.js +140 -0
- package/dist/core/triwiki/context-graph/projections/node-summary.js +118 -0
- package/dist/core/triwiki/context-graph/projections/pack-contract.js +6 -0
- package/dist/core/triwiki/context-graph/query/explain.js +0 -0
- package/dist/core/triwiki/context-graph/query/index.js +178 -0
- package/dist/core/triwiki/context-graph/query/load.js +116 -0
- package/dist/core/triwiki/context-graph/query/pack.js +117 -0
- package/dist/core/triwiki/context-graph/query/rank.js +142 -0
- package/dist/core/triwiki/context-graph/query/ranking-config.js +64 -0
- package/dist/core/triwiki/context-graph/query/seeds.js +241 -0
- package/dist/core/triwiki/context-graph/query/snapshot-cache.js +72 -0
- package/dist/core/triwiki/context-graph/query/traverse.js +154 -0
- package/dist/core/triwiki/context-graph/query-types.js +29 -0
- package/dist/core/triwiki/context-graph/store/compile-lock.js +21 -0
- package/dist/core/triwiki/context-graph/store/event-log.js +48 -0
- package/dist/core/triwiki/context-graph/store/fragment-cache.js +85 -0
- package/dist/core/triwiki/context-graph/store/graph-status.js +85 -0
- package/dist/core/triwiki/context-graph/store/snapshot-store.js +155 -0
- package/dist/core/triwiki/triwiki-proof-bank-index-repair.js +115 -0
- package/dist/core/triwiki/triwiki-proof-bank-index-store.js +290 -0
- package/dist/core/triwiki/triwiki-proof-bank-index.js +126 -0
- package/dist/core/triwiki/triwiki-proof-bank.js +7 -1
- package/dist/core/verification/context-graph-affected.js +271 -0
- package/dist/core/version.js +1 -1
- package/dist/native/sks-menubar/Sources/AlertFactory.swift +11 -3
- package/dist/native/sks-menubar/Sources/AppDelegate.swift +9 -0
- package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +25 -3
- package/dist/native/sks-menubar/Sources/ControlKit.swift +19 -8
- package/dist/native/sks-menubar/Sources/DiagnosticsViewController.swift +1 -2
- package/dist/native/sks-menubar/Sources/MCPServersViewController.swift +45 -17
- package/dist/native/sks-menubar/Sources/OverviewSummary.swift +162 -0
- package/dist/native/sks-menubar/Sources/OverviewViewController.swift +136 -190
- package/dist/native/sks-menubar/Sources/ProcessClient.swift +107 -11
- package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +5 -1
- package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +16 -4
- package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +4 -1
- package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +131 -0
- package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +288 -341
- package/dist/native/sks-menubar/Sources/RemoteTelegramCenterState.swift +447 -0
- package/dist/native/sks-menubar/Sources/RemoteTelegramRendering.swift +484 -0
- package/dist/native/sks-menubar/Sources/RemoteTelegramViewController.swift +364 -115
- package/dist/native/sks-menubar/Sources/SettingsViewController.swift +73 -12
- package/dist/native/sks-menubar/Sources/SidebarItem.swift +3 -3
- package/dist/native/sks-menubar/Sources/StatusItemController.swift +13 -13
- package/dist/native/sks-menubar/Sources/TelegramHubSupervisor.swift +469 -0
- package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +1 -6
- package/dist/native/sks-menubar/Tests/AppRuntimeTestSupport.swift +12 -0
- package/dist/native/sks-menubar/Tests/NativeTelegramRegressionRunner.swift +55 -0
- package/dist/native/sks-menubar/Tests/ProcessClientTests.swift +33 -0
- package/dist/native/sks-menubar/Tests/ProvidersViewControllerTests.swift +142 -0
- package/dist/native/sks-menubar/Tests/RemoteTelegramCenterStateTests.swift +56 -0
- package/dist/native/sks-menubar/Tests/TelegramHubSupervisorTests.swift +55 -0
- package/dist/scripts/codex-lb-catalog-passthrough-check.js +120 -0
- package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +169 -0
- package/dist/scripts/codex-lb-desktop-bridge-check.js +394 -0
- package/dist/scripts/codex-lb-desktop-bridge-latency-check.js +196 -0
- package/dist/scripts/codex-lb-desktop-capabilities-check.js +287 -0
- package/dist/scripts/codex-lb-desktop-real-evidence-check.js +123 -0
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +10 -3
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +81 -40
- package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +99 -37
- package/dist/scripts/context-graph-check.js +191 -0
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +1 -1
- package/dist/scripts/gate-policy-audit-check.js +1 -1
- package/dist/scripts/helper-dedup-check.js +0 -2
- package/dist/scripts/installed-package-smoke-check.js +4 -1
- package/dist/scripts/latest-version-guidance-check.js +74 -0
- package/dist/scripts/release-metadata-check.js +21 -4
- package/dist/scripts/release-real-check.js +7 -0
- package/dist/scripts/ux-review-imagegen-blackbox-check.js +25 -1
- package/dist/scripts/ux-review-run-wires-imagegen-check.js +9 -1
- package/package.json +8 -3
- package/release-gates.v2.json +176 -1
- package/runtime-required-scripts.json +30 -0
- package/schemas/triwiki/context-graph.schema.json +119 -0
- package/dist/cli/install-helpers-codex-lb-selftest-chain.js +0 -112
- package/dist/cli/install-helpers-codex-lb-selftest.js +0 -481
- package/dist/core/triwiki/code-index-scanner.js +0 -309
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { CONTEXT_GRAPH_REPAIR_COMMAND } from '../triwiki/context-graph/contracts.js';
|
|
2
|
+
import { contextGraphCacheKey } from '../triwiki/context-graph/compiler/cache-key.js';
|
|
3
|
+
import { contextGraphStatus } from '../triwiki/context-graph/store/graph-status.js';
|
|
4
|
+
import { readContextGraphMeta } from '../triwiki/context-graph/store/snapshot-store.js';
|
|
5
|
+
import { contextGraphExtractors } from '../triwiki/context-graph/extractors/index.js';
|
|
6
|
+
export const CONTEXT_GRAPH_FRESHNESS_PREFLIGHT_SCHEMA = 'sks.context-graph-freshness-preflight.v1';
|
|
7
|
+
const CACHE_KEY_DERIVED_REASONS = [
|
|
8
|
+
'head_changed',
|
|
9
|
+
'dirty_fingerprint_changed',
|
|
10
|
+
'schema_revision_changed',
|
|
11
|
+
'tsconfig_changed',
|
|
12
|
+
'command_manifest_changed',
|
|
13
|
+
'gate_manifest_changed',
|
|
14
|
+
'proof_index_changed',
|
|
15
|
+
'wiki_context_changed',
|
|
16
|
+
'git_state_unknown',
|
|
17
|
+
'cache_key_changed'
|
|
18
|
+
];
|
|
19
|
+
const PLACEHOLDER_CACHE_KEY_PARTS = {
|
|
20
|
+
workspaceIdentity: 'unevaluated',
|
|
21
|
+
head: null,
|
|
22
|
+
gitState: 'unknown',
|
|
23
|
+
trackedDirtyFingerprint: 'unevaluated',
|
|
24
|
+
untrackedFingerprint: 'unevaluated',
|
|
25
|
+
schemaRevision: 'unevaluated',
|
|
26
|
+
tsconfigHash: 'unevaluated',
|
|
27
|
+
commandManifestHash: 'unevaluated',
|
|
28
|
+
gateManifestHash: 'unevaluated',
|
|
29
|
+
proofIndexHash: 'unevaluated',
|
|
30
|
+
wikiContextHash: 'unevaluated'
|
|
31
|
+
};
|
|
32
|
+
export async function contextGraphFreshnessPreflight(root, options = {}) {
|
|
33
|
+
const verifySources = options.verifySources !== false;
|
|
34
|
+
const extractors = options.extractors ?? contextGraphExtractors();
|
|
35
|
+
const supplied = options.cacheKey ?? null;
|
|
36
|
+
const metaLoad = await readContextGraphMeta(root);
|
|
37
|
+
const meta = metaLoad.status === 'ok' ? metaLoad.meta : null;
|
|
38
|
+
const cacheKey = supplied ?? neutralCacheKey(meta?.cacheKeyParts ?? PLACEHOLDER_CACHE_KEY_PARTS);
|
|
39
|
+
const recordedSources = meta ? Object.keys(meta.inputHashes ?? {}).length : 0;
|
|
40
|
+
const status = await contextGraphStatus(root, {
|
|
41
|
+
extractors,
|
|
42
|
+
cacheKey,
|
|
43
|
+
verifySources,
|
|
44
|
+
...(options.maxVerifiedSources === undefined ? {} : { maxVerifiedSources: options.maxVerifiedSources })
|
|
45
|
+
});
|
|
46
|
+
const sourcesVerified = verifySources
|
|
47
|
+
&& (options.maxVerifiedSources === undefined || options.maxVerifiedSources >= recordedSources);
|
|
48
|
+
const unverified = collectUnverifiedReasons(status.reasons, Boolean(supplied), sourcesVerified);
|
|
49
|
+
return {
|
|
50
|
+
schema: CONTEXT_GRAPH_FRESHNESS_PREFLIGHT_SCHEMA,
|
|
51
|
+
usable: status.status === 'fresh',
|
|
52
|
+
status: status.status,
|
|
53
|
+
reasons: status.reasons,
|
|
54
|
+
unverified_reasons: unverified,
|
|
55
|
+
coverage: supplied ? 'full' : sourcesVerified ? 'artifacts_and_sources' : 'artifacts_only',
|
|
56
|
+
snapshot_hash: status.snapshotHash,
|
|
57
|
+
generated_at: status.generatedAt,
|
|
58
|
+
node_count: status.nodeCount,
|
|
59
|
+
edge_count: status.edgeCount,
|
|
60
|
+
error_code: status.errorCode,
|
|
61
|
+
repair_command: CONTEXT_GRAPH_REPAIR_COMMAND
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export async function contextGraphFreshnessNote(root, options = {}) {
|
|
65
|
+
const budgetMs = Math.max(1, options.budgetMs ?? 750);
|
|
66
|
+
const preflight = await raceWithTimeout(contextGraphFreshnessPreflight(root, options), budgetMs).catch(() => null);
|
|
67
|
+
if (!preflight)
|
|
68
|
+
return null;
|
|
69
|
+
return contextGraphFreshnessNoteFor(preflight);
|
|
70
|
+
}
|
|
71
|
+
export function contextGraphFreshnessNoteFor(preflight) {
|
|
72
|
+
if (preflight.status === 'fresh')
|
|
73
|
+
return null;
|
|
74
|
+
if (preflight.status === 'missing') {
|
|
75
|
+
return `SKS note: the codebase context graph has not been built (${preflight.error_code}). Run \`${preflight.repair_command}\` before relying on graph-cited context.`;
|
|
76
|
+
}
|
|
77
|
+
if (preflight.status === 'corrupt') {
|
|
78
|
+
return `SKS note: the codebase context graph is unusable (${preflight.error_code}). Run \`${preflight.repair_command}\` to rebuild it; no older generation is substituted.`;
|
|
79
|
+
}
|
|
80
|
+
const reasons = preflight.reasons.join(', ');
|
|
81
|
+
return `SKS note: the codebase context graph is stale (${preflight.error_code}: ${reasons}). Run \`${preflight.repair_command}\` to refresh graph-cited context.`;
|
|
82
|
+
}
|
|
83
|
+
function neutralCacheKey(parts) {
|
|
84
|
+
return { key: contextGraphCacheKey(parts), parts, reusable: true, reasons: [], dirtyPaths: [] };
|
|
85
|
+
}
|
|
86
|
+
function collectUnverifiedReasons(fired, cacheKeySupplied, sourcesVerified) {
|
|
87
|
+
const firedSet = new Set(fired);
|
|
88
|
+
const out = [];
|
|
89
|
+
if (!cacheKeySupplied) {
|
|
90
|
+
for (const reason of CACHE_KEY_DERIVED_REASONS) {
|
|
91
|
+
if (!firedSet.has(reason))
|
|
92
|
+
out.push(reason);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (!sourcesVerified && !firedSet.has('source_hash_mismatch'))
|
|
96
|
+
out.push('source_hash_mismatch');
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
async function raceWithTimeout(work, ms) {
|
|
100
|
+
let timer = null;
|
|
101
|
+
const timeout = new Promise((resolve) => {
|
|
102
|
+
timer = setTimeout(() => resolve(null), ms);
|
|
103
|
+
if (timer.unref)
|
|
104
|
+
timer.unref();
|
|
105
|
+
});
|
|
106
|
+
try {
|
|
107
|
+
return await Promise.race([work, timeout]);
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
if (timer)
|
|
111
|
+
clearTimeout(timer);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -5,6 +5,7 @@ import { routePrompt } from '../pipeline.js';
|
|
|
5
5
|
import { allowlistedManagedRouteSkillNames, dollarCommand, INVALID_EXPLICIT_MANAGED_SKILL_NAME, managedSkillNamesForPrompt, routeRequiresSubagents, stripVisibleDecisionAnswerBlocks } from '../routes.js';
|
|
6
6
|
import { inspectConfinedPath } from '../managed-path-safety.js';
|
|
7
7
|
import { renderAuthoritativeSksSkillContext, resolveAuthoritativeSksSkillSources } from '../codex-native/sks-skill-paths.js';
|
|
8
|
+
import { healStaleGlobalManagedSkillGeneration, managedSkillResolutionIsHealable } from './managed-skill-generation-heal.js';
|
|
8
9
|
import { looksLikeActiveContinuationPrompt } from './naruto-decision-gate.js';
|
|
9
10
|
import { extractUserPrompt, looksLikeCodexGitAction, looksLikeCodexUiSettingsEvent } from './payload-signals.js';
|
|
10
11
|
const STANDALONE_PARENT_BASE_SKILLS = [
|
|
@@ -100,7 +101,7 @@ async function readStandaloneParentRouteContext(root, missionId) {
|
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
103
|
export async function authoritativeSksSkillAdmission(root, skillNames) {
|
|
103
|
-
|
|
104
|
+
let resolution = await resolveAuthoritativeSksSkillSources({ root, skillNames }).catch(() => null);
|
|
104
105
|
if (!resolution) {
|
|
105
106
|
return {
|
|
106
107
|
resolution: null,
|
|
@@ -111,16 +112,28 @@ export async function authoritativeSksSkillAdmission(root, skillNames) {
|
|
|
111
112
|
}
|
|
112
113
|
};
|
|
113
114
|
}
|
|
115
|
+
let healedGeneration = null;
|
|
116
|
+
if (managedSkillResolutionIsHealable(resolution)) {
|
|
117
|
+
healedGeneration = await healStaleGlobalManagedSkillGeneration().catch(() => null);
|
|
118
|
+
if (healedGeneration) {
|
|
119
|
+
const rechecked = await resolveAuthoritativeSksSkillSources({ root, skillNames }).catch(() => null);
|
|
120
|
+
if (rechecked)
|
|
121
|
+
resolution = rechecked;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
114
124
|
if (resolution.unresolved.length || resolution.blockers.length) {
|
|
115
125
|
const details = [
|
|
116
126
|
resolution.unresolved.length ? `unavailable=${resolution.unresolved.join(',')}` : '',
|
|
117
127
|
resolution.blockers.length ? `rejected=${resolution.blockers.join(',')}` : ''
|
|
118
128
|
].filter(Boolean).join('; ');
|
|
129
|
+
const repair = healedGeneration
|
|
130
|
+
? `Global managed skills were regenerated from sneakoscope ${healedGeneration.installed_version} to ${healedGeneration.runtime_version} and still do not match this runtime, so \`sks doctor --fix\` cannot clear it. Ask the user to install the sneakoscope build that matches this runtime (${healedGeneration.runtime_version}) and retry.`
|
|
131
|
+
: 'Ask the user to run `sks doctor --fix` (do not run it yourself), then retry.';
|
|
119
132
|
return {
|
|
120
133
|
resolution,
|
|
121
134
|
blocked: {
|
|
122
135
|
decision: 'block',
|
|
123
|
-
reason: `SKS managed skill availability check failed (${details}).
|
|
136
|
+
reason: `SKS managed skill availability check failed (${details}). ${repair}`,
|
|
124
137
|
systemMessage: 'SKS: managed skill availability check blocked this turn.'
|
|
125
138
|
}
|
|
126
139
|
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { PACKAGE_VERSION, readJson } from '../fsx.js';
|
|
4
|
+
const HEALABLE_BLOCKER_STATUSES = new Set([
|
|
5
|
+
'content_digest_mismatch',
|
|
6
|
+
'canonical_name_mismatch',
|
|
7
|
+
'not_sks_managed'
|
|
8
|
+
]);
|
|
9
|
+
const healedGenerations = new Map();
|
|
10
|
+
export function managedSkillResolutionIsHealable(resolution) {
|
|
11
|
+
if (!resolution)
|
|
12
|
+
return false;
|
|
13
|
+
const blockers = resolution.blockers || [];
|
|
14
|
+
if (blockers.some((blocker) => !HEALABLE_BLOCKER_STATUSES.has(String(blocker).split(':')[0] || '')))
|
|
15
|
+
return false;
|
|
16
|
+
return Boolean(resolution.unresolved.length || blockers.length);
|
|
17
|
+
}
|
|
18
|
+
export async function staleGlobalManagedSkillGeneration(home) {
|
|
19
|
+
const resolvedHome = path.resolve(home || process.env.HOME || os.homedir());
|
|
20
|
+
const marker = await readJson(path.join(resolvedHome, '.agents', 'skills', '.sks-generated.json'), null);
|
|
21
|
+
if (String(marker?.generated_by || '') !== 'sneakoscope')
|
|
22
|
+
return null;
|
|
23
|
+
const installedVersion = String(marker?.version || '').trim();
|
|
24
|
+
if (!installedVersion || installedVersion === PACKAGE_VERSION)
|
|
25
|
+
return null;
|
|
26
|
+
return { home: resolvedHome, installed_version: installedVersion, runtime_version: PACKAGE_VERSION };
|
|
27
|
+
}
|
|
28
|
+
export async function healStaleGlobalManagedSkillGeneration(home) {
|
|
29
|
+
const stale = await staleGlobalManagedSkillGeneration(home);
|
|
30
|
+
if (!stale)
|
|
31
|
+
return null;
|
|
32
|
+
const cached = healedGenerations.get(stale.home);
|
|
33
|
+
if (cached)
|
|
34
|
+
return cached;
|
|
35
|
+
const work = (async () => {
|
|
36
|
+
const { reconcileSkills } = await import('../init/skills.js');
|
|
37
|
+
const report = await reconcileSkills({
|
|
38
|
+
targetDir: path.join(stale.home, '.agents', 'skills'),
|
|
39
|
+
scope: 'global',
|
|
40
|
+
fix: true
|
|
41
|
+
}).catch(() => null);
|
|
42
|
+
return report?.ok === true ? stale : null;
|
|
43
|
+
})();
|
|
44
|
+
healedGenerations.set(stale.home, work);
|
|
45
|
+
return work;
|
|
46
|
+
}
|
|
@@ -160,6 +160,7 @@ async function resolveStaleOfficialSubagentComplianceBlocker(input) {
|
|
|
160
160
|
await appendJsonl(path.join(input.dir, 'events.jsonl'), {
|
|
161
161
|
ts: nowIso(),
|
|
162
162
|
type: 'pipeline.compliance_loop_guard.resolved',
|
|
163
|
+
proof_invalidating: false,
|
|
163
164
|
gate: 'official-subagent-evidence',
|
|
164
165
|
workflow_run_id: input.workflowRunId,
|
|
165
166
|
resolution_artifact: RESOLVED_HARD_BLOCKER_ARTIFACT
|
|
@@ -350,7 +350,7 @@ async function rebuildHostCapabilityEvidenceForFinalization(input) {
|
|
|
350
350
|
blockers: bound.blockers
|
|
351
351
|
};
|
|
352
352
|
}
|
|
353
|
-
function completeNarutoTerminalBundle(input) {
|
|
353
|
+
export function completeNarutoTerminalBundle(input) {
|
|
354
354
|
const runId = String(input.workflowRunId || '').trim();
|
|
355
355
|
const parent = normalizeSubagentParentSummary(input.parentSummary);
|
|
356
356
|
return Boolean(runId
|
|
@@ -87,6 +87,6 @@ export function interruptedToolOutputRecoveryBlockReason(input = {}) {
|
|
|
87
87
|
`SKS blocked same-thread continuation because custom tool call ${callId} has no correlated output (active mission: ${missionId}).`,
|
|
88
88
|
'The current Codex conversation state may be structurally invalid, so additional context cannot repair the pending Responses request.',
|
|
89
89
|
'Treat the call result as unknown and do not replay a possibly mutating action.',
|
|
90
|
-
'Upgrade the selected codex-lb to
|
|
90
|
+
'Upgrade the selected codex-lb to the official latest stable release (`sks codex-lb status --json` reports whether the deployment satisfies tool-heavy continuation), or explicitly disable only codex-lb routing with `sks codex-lb disable`, then open a fresh Codex thread and continue the persisted mission after inspecting side effects. ChatGPT OAuth is not replaced by either action.'
|
|
91
91
|
].join(' ');
|
|
92
92
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { projectRoot, readJson, writeJsonAtomic, appendJsonl, nowIso,
|
|
2
|
+
import { projectRoot, readJson, writeJsonAtomic, appendJsonl, nowIso, sha256, packageRoot } from './fsx.js';
|
|
3
3
|
import { looksInteractiveCommand, interactiveCommandReason } from './no-question-guard.js';
|
|
4
4
|
import { loadStateForSession, missionDir, sessionStateKey, setCurrent, stateFileForSession } from './mission.js';
|
|
5
5
|
import { checkDbOperation, dbBlockReason, handleMadSksUserConfirmation } from './db-safety.js';
|
|
@@ -42,6 +42,7 @@ import { activeAuthoritativeSksSkillRefresh, activeGoalOverlayContext, attachAut
|
|
|
42
42
|
import { sealedSubagentRoutingContext, subagentRouteContext } from './hooks-runtime/subagent-context.js';
|
|
43
43
|
export { loadHookPayload, normalizeHookResult };
|
|
44
44
|
export { refreshOfficialSubagentCompletionArtifacts };
|
|
45
|
+
export { selftestCodexCommitHooks } from './hooks-runtime/codex-commit-hooks-selftest.js';
|
|
45
46
|
async function loadState(root, payload = {}) {
|
|
46
47
|
const sessionKey = conversationId(payload);
|
|
47
48
|
if (!explicitConversationId(payload))
|
|
@@ -863,8 +864,9 @@ async function hookStop(root, state, payload, noQuestion, sessionKey = null) {
|
|
|
863
864
|
await refreshOfficialSubagentCompletionArtifacts(root, state, last, sessionKey).catch(() => null);
|
|
864
865
|
}
|
|
865
866
|
const routeDecision = await evaluateStop(root, state, payload, { noQuestion });
|
|
866
|
-
if (routeDecision)
|
|
867
|
+
if (routeDecision && !successfulAppNarutoStopNeedsVisibleSummary(state, routeDecision)) {
|
|
867
868
|
return routeDecision;
|
|
869
|
+
}
|
|
868
870
|
if (!noQuestion) {
|
|
869
871
|
const languageBasis = state?.prompt || state?.task || extractUserPrompt(payload) || last;
|
|
870
872
|
if (!hasHonestMode(last)) {
|
|
@@ -892,13 +894,23 @@ async function hookStop(root, state, payload, noQuestion, sessionKey = null) {
|
|
|
892
894
|
}
|
|
893
895
|
if (state?.honest_loop_required)
|
|
894
896
|
await resolveHonestModeLoopback(root, state, sessionKey);
|
|
895
|
-
return { continue: true };
|
|
897
|
+
return routeDecision || { continue: true };
|
|
896
898
|
}
|
|
897
899
|
return {
|
|
898
900
|
decision: 'block',
|
|
899
901
|
reason: 'SKS no-question run is not done. Continue autonomously, fix failing checks, update the active gate file, and do not ask the user.'
|
|
900
902
|
};
|
|
901
903
|
}
|
|
904
|
+
function successfulAppNarutoStopNeedsVisibleSummary(state = {}, routeDecision = {}) {
|
|
905
|
+
const route = String(state?.route || state?.route_command || state?.mode || '')
|
|
906
|
+
.replace(/^\$/, '')
|
|
907
|
+
.replace(/[-_]/g, '')
|
|
908
|
+
.toUpperCase();
|
|
909
|
+
return route === 'NARUTO'
|
|
910
|
+
&& Boolean(state?.session_scope)
|
|
911
|
+
&& routeDecision?.continue === true
|
|
912
|
+
&& !['hard_blocked', 'route_closed'].includes(String(routeDecision?.action || ''));
|
|
913
|
+
}
|
|
902
914
|
async function consumeLightRouteStop(root, payload = {}) {
|
|
903
915
|
const file = path.join(root, '.sneakoscope', 'state', LIGHT_ROUTE_STOP_ARTIFACT);
|
|
904
916
|
const record = await readJson(file, null).catch(() => null);
|
|
@@ -982,12 +994,22 @@ function hasHonestModeUnresolvedGap(text) {
|
|
|
982
994
|
}
|
|
983
995
|
export function honestModeGapLines(text) {
|
|
984
996
|
const issue = /(gap|remaining|unverified|not verified|not run|not complete|incomplete|failed|blocked|blocker|could not|couldn't|missing|미완료|미검증|미실행|실패|차단|누락|못했|못 했|안 했|안함|아직|남은)/i;
|
|
985
|
-
|
|
997
|
+
const lines = String(text || '')
|
|
986
998
|
.split(/\n/)
|
|
987
|
-
.map((line) => line.trim())
|
|
988
|
-
|
|
999
|
+
.map((line) => line.trim());
|
|
1000
|
+
return lines
|
|
1001
|
+
.filter((line, index) => issue.test(line)
|
|
1002
|
+
&& !honestGapLineResolved(line)
|
|
1003
|
+
&& !honestGapHeadingResolved(line, lines.slice(index + 1).find((candidate) => candidate.length > 0)))
|
|
989
1004
|
.slice(0, 12);
|
|
990
1005
|
}
|
|
1006
|
+
function honestGapHeadingResolved(line, nextLine) {
|
|
1007
|
+
const heading = String(line || '').replace(/^#{1,6}\s*/, '').replace(/\s*[::]\s*$/, '').trim();
|
|
1008
|
+
if (!/^(?:remaining|unresolved)\s+(?:gaps?|issues?)$|^(?:남은|미해결)\s*(?:문제|항목|갭|gap)$/i.test(heading)) {
|
|
1009
|
+
return false;
|
|
1010
|
+
}
|
|
1011
|
+
return /^(?:없음|없습니다|없다|none|no(?:ne)?|0|0개)[.!。]?$/i.test(String(nextLine || '').trim());
|
|
1012
|
+
}
|
|
991
1013
|
function honestGapLineResolved(line) {
|
|
992
1014
|
if (/(?:unverified|미검증)\s*:\s*\[\s*\]/i.test(line) && /blockers?\s*:\s*\[\s*\]/i.test(line))
|
|
993
1015
|
return true;
|
|
@@ -1003,7 +1025,9 @@ function honestGapLineResolved(line) {
|
|
|
1003
1025
|
return true;
|
|
1004
1026
|
if (/no\s+active\s+blocking\s+route\s+gate\s+detected/i.test(line))
|
|
1005
1027
|
return true;
|
|
1006
|
-
if (/(
|
|
1028
|
+
if (/(?:blockers?|차단(?:\s*(?:항목|요소|건))?)\s*(?:[:=]\s*)?0(?:건|개)?\b/i.test(line))
|
|
1029
|
+
return true;
|
|
1030
|
+
if (/(non[-\s]?blocker|non[-\s]?blocking|not\s+(?:a\s+)?blocker|no\s+blocker|does\s+not\s+block|not\s+blocking|비\s*차단|blocker\s*(?:는|가)?\s*(?:아님|아닙니다|없음)|차단(?:하지|하진|하지는)\s*않|막(?:지|지는)\s*않)/i.test(line))
|
|
1007
1031
|
return true;
|
|
1008
1032
|
if (/(요약\s*(?:없으면|없는\s*경우).*(?:차단|block).*(?:요약\s*(?:있으면|있는\s*경우)|통과|pass)|(?:missing|without)\s+summary.*(?:block|blocked).*(?:with\s+summary|pass|accepted))/i.test(line))
|
|
1009
1033
|
return true;
|
|
@@ -1050,7 +1074,7 @@ async function recordHonestModeLoopback(root, state = {}, lastMessage = '', sess
|
|
|
1050
1074
|
};
|
|
1051
1075
|
const file = path.join(dir, 'honest-loopback.json');
|
|
1052
1076
|
await writeJsonAtomic(file, artifact);
|
|
1053
|
-
await appendJsonl(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'pipeline.honest_mode.loopback', previous_phase: previousPhase, phase, attempt, issues: artifact.issue_lines });
|
|
1077
|
+
await appendJsonl(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'pipeline.honest_mode.loopback', proof_invalidating: false, previous_phase: previousPhase, phase, attempt, issues: artifact.issue_lines });
|
|
1054
1078
|
await setCurrent(root, {
|
|
1055
1079
|
phase,
|
|
1056
1080
|
honest_loop_required: true,
|
|
@@ -1068,7 +1092,7 @@ async function resolveHonestModeLoopback(root, state = {}, sessionKey = null) {
|
|
|
1068
1092
|
const id = state.mission_id;
|
|
1069
1093
|
const mode = String(state.mode || state.route || 'SKS').toUpperCase();
|
|
1070
1094
|
if (id)
|
|
1071
|
-
await appendJsonl(path.join(missionDir(root, id), 'events.jsonl'), { ts: nowIso(), type: 'pipeline.honest_mode.loopback_resolved', previous_phase: state.phase || null });
|
|
1095
|
+
await appendJsonl(path.join(missionDir(root, id), 'events.jsonl'), { ts: nowIso(), type: 'pipeline.honest_mode.loopback_resolved', proof_invalidating: false, previous_phase: state.phase || null });
|
|
1072
1096
|
await setCurrent(root, {
|
|
1073
1097
|
phase: `${mode}_HONEST_COMPLETE`,
|
|
1074
1098
|
honest_loop_required: false,
|
|
@@ -1080,83 +1104,3 @@ export async function emitHook(name) {
|
|
|
1080
1104
|
const result = await hookMain(name);
|
|
1081
1105
|
process.stdout.write(`${JSON.stringify(normalizeHookResult(name, result))}\n`);
|
|
1082
1106
|
}
|
|
1083
|
-
export async function selftestCodexCommitHooks() {
|
|
1084
|
-
const root = tmpdir();
|
|
1085
|
-
const hookBin = path.join(packageRoot(), 'dist', 'bin', 'sks.js');
|
|
1086
|
-
const env = { SKS_DISABLE_UPDATE_CHECK: '1' };
|
|
1087
|
-
const setup = await runProcess(process.execPath, [hookBin, 'setup', '--install-scope', 'project'], { cwd: root, env, timeoutMs: 15000, maxOutputBytes: 128 * 1024 });
|
|
1088
|
-
if (setup.code !== 0)
|
|
1089
|
-
throw new Error(`selftest failed: commit setup ${setup.code}: ${setup.stderr}`);
|
|
1090
|
-
const runHook = (name, payload) => runProcess(process.execPath, [hookBin, 'hook', name], { cwd: root, input: JSON.stringify({ cwd: root, ...payload }), env, timeoutMs: 15000, maxOutputBytes: 128 * 1024 });
|
|
1091
|
-
const id = 'commit-selftest';
|
|
1092
|
-
const hook = await runHook('user-prompt-submit', { conversation_id: id, action: 'codex_git_commit', prompt: 'Generate a git commit message for the staged diff.' });
|
|
1093
|
-
if (hook.code !== 0)
|
|
1094
|
-
throw new Error(`selftest failed: commit hook ${hook.code}: ${hook.stderr}`);
|
|
1095
|
-
const hookJson = JSON.parse(hook.stdout);
|
|
1096
|
-
if (hookJson.decision === 'block' || hookJson.hookSpecificOutput?.additionalContext || !String(hookJson.systemMessage || '').includes('git action'))
|
|
1097
|
-
throw new Error('selftest failed: commit route bypass');
|
|
1098
|
-
const stop = await runHook('stop', { conversation_id: id, last_assistant_message: 'Fix Codex App commit message hook bypass' });
|
|
1099
|
-
if (stop.code !== 0)
|
|
1100
|
-
throw new Error(`selftest failed: commit stop ${stop.code}: ${stop.stderr}`);
|
|
1101
|
-
const stopJson = JSON.parse(stop.stdout);
|
|
1102
|
-
if (stopJson.decision === 'block' || !String(stopJson.systemMessage || '').includes('accepted without route finalization'))
|
|
1103
|
-
throw new Error('selftest failed: commit stop bypass');
|
|
1104
|
-
const commitPushId = 'commit-push-selftest';
|
|
1105
|
-
const appCommitPushHook = await runHook('user-prompt-submit', { conversation_id: commitPushId, action: 'Codex App Git Actions Commit and Push', prompt: 'Commit and push changes.' });
|
|
1106
|
-
if (appCommitPushHook.code !== 0)
|
|
1107
|
-
throw new Error(`selftest failed: app commit-push hook ${appCommitPushHook.code}: ${appCommitPushHook.stderr}`);
|
|
1108
|
-
const appCommitPushJson = JSON.parse(appCommitPushHook.stdout);
|
|
1109
|
-
if (appCommitPushJson.decision === 'block' || appCommitPushJson.hookSpecificOutput?.additionalContext || !String(appCommitPushJson.systemMessage || '').includes('git action'))
|
|
1110
|
-
throw new Error('selftest failed: app commit-push route bypass');
|
|
1111
|
-
const appCommitPushStop = await runHook('stop', { conversation_id: commitPushId, last_assistant_message: 'Commit and push complete.' });
|
|
1112
|
-
if (appCommitPushStop.code !== 0)
|
|
1113
|
-
throw new Error(`selftest failed: app commit-push stop ${appCommitPushStop.code}: ${appCommitPushStop.stderr}`);
|
|
1114
|
-
if (JSON.parse(appCommitPushStop.stdout).decision === 'block')
|
|
1115
|
-
throw new Error('selftest failed: app commit-push stop bypass');
|
|
1116
|
-
const appPushId = 'app-push-selftest';
|
|
1117
|
-
const appPushHook = await runHook('user-prompt-submit', { conversation_id: appPushId, metadata: { source: 'codex_app', action: 'Git Actions Push' }, prompt: 'Push changes.' });
|
|
1118
|
-
if (appPushHook.code !== 0)
|
|
1119
|
-
throw new Error(`selftest failed: app push hook ${appPushHook.code}: ${appPushHook.stderr}`);
|
|
1120
|
-
const appPushJson = JSON.parse(appPushHook.stdout);
|
|
1121
|
-
if (appPushJson.decision === 'block' || appPushJson.hookSpecificOutput?.additionalContext || !String(appPushJson.systemMessage || '').includes('git action'))
|
|
1122
|
-
throw new Error('selftest failed: app push metadata route bypass');
|
|
1123
|
-
const appPushStop = await runHook('stop', { conversation_id: appPushId, metadata: { source: 'codex_app', action: 'Git Actions Push' }, last_assistant_message: 'Done.' });
|
|
1124
|
-
if (appPushStop.code !== 0)
|
|
1125
|
-
throw new Error(`selftest failed: app push stop ${appPushStop.code}: ${appPushStop.stderr}`);
|
|
1126
|
-
if (JSON.parse(appPushStop.stdout).decision === 'block')
|
|
1127
|
-
throw new Error('selftest failed: app push metadata stop bypass');
|
|
1128
|
-
const metadataLightId = 'metadata-light-commit-push-selftest';
|
|
1129
|
-
const metadataLightHook = await runHook('user-prompt-submit', { conversation_id: metadataLightId, prompt: 'Commit and push changes.' });
|
|
1130
|
-
if (metadataLightHook.code !== 0)
|
|
1131
|
-
throw new Error(`selftest failed: metadata-light commit-push hook ${metadataLightHook.code}: ${metadataLightHook.stderr}`);
|
|
1132
|
-
const metadataLightJson = JSON.parse(metadataLightHook.stdout);
|
|
1133
|
-
if (metadataLightJson.decision === 'block' || metadataLightJson.hookSpecificOutput?.additionalContext || !String(metadataLightJson.systemMessage || '').includes('git action'))
|
|
1134
|
-
throw new Error('selftest failed: metadata-light app commit-push route bypass');
|
|
1135
|
-
const metadataLightStop = await runHook('stop', { conversation_id: metadataLightId, last_assistant_message: 'Commit and push complete.' });
|
|
1136
|
-
if (metadataLightStop.code !== 0)
|
|
1137
|
-
throw new Error(`selftest failed: metadata-light commit-push stop ${metadataLightStop.code}: ${metadataLightStop.stderr}`);
|
|
1138
|
-
if (JSON.parse(metadataLightStop.stdout).decision === 'block')
|
|
1139
|
-
throw new Error('selftest failed: metadata-light commit-push stop bypass');
|
|
1140
|
-
const settingsHook = await runHook('user-prompt-submit', { model: 'future-codex-catalog-model', metadata: { source: 'codex_app_settings', feature: 'speed profile' } });
|
|
1141
|
-
if (settingsHook.code !== 0)
|
|
1142
|
-
throw new Error(`selftest failed: settings hook ${settingsHook.code}: ${settingsHook.stderr}`);
|
|
1143
|
-
const settingsJson = JSON.parse(settingsHook.stdout);
|
|
1144
|
-
if (settingsJson.decision === 'block' || settingsJson.hookSpecificOutput?.additionalContext || !String(settingsJson.systemMessage || '').includes('settings/profile event ignored'))
|
|
1145
|
-
throw new Error('selftest failed: settings/profile event should not route or block');
|
|
1146
|
-
const userHook = await runHook('user-prompt-submit', { prompt: '[커밋 메시지를 생성하지 못했습니다.] 코덱스 앱에서 이 버그 수정해줘' });
|
|
1147
|
-
if (userHook.code !== 0)
|
|
1148
|
-
throw new Error(`selftest failed: user commit hook ${userHook.code}: ${userHook.stderr}`);
|
|
1149
|
-
if (!JSON.parse(userHook.stdout).hookSpecificOutput?.additionalContext?.includes('$Naruto route prepared'))
|
|
1150
|
-
throw new Error('selftest failed: user prompt route');
|
|
1151
|
-
const userCommitPushHook = await runHook('user-prompt-submit', { prompt: '배포하게 커밋하고 푸쉬해줘' });
|
|
1152
|
-
if (userCommitPushHook.code !== 0)
|
|
1153
|
-
throw new Error(`selftest failed: user commit-push hook ${userCommitPushHook.code}: ${userCommitPushHook.stderr}`);
|
|
1154
|
-
const userCommitPushJson = JSON.parse(userCommitPushHook.stdout);
|
|
1155
|
-
if (userCommitPushJson.decision === 'block' || userCommitPushJson.hookSpecificOutput?.additionalContext || !String(userCommitPushJson.systemMessage || '').includes('git action'))
|
|
1156
|
-
throw new Error('selftest failed: user commit-push prompt should bypass route');
|
|
1157
|
-
const userCommitPushStop = await runHook('stop', { last_assistant_message: 'Commit and push complete.' });
|
|
1158
|
-
if (userCommitPushStop.code !== 0)
|
|
1159
|
-
throw new Error(`selftest failed: user commit-push stop ${userCommitPushStop.code}: ${userCommitPushStop.stderr}`);
|
|
1160
|
-
if (JSON.parse(userCommitPushStop.stdout).decision === 'block')
|
|
1161
|
-
throw new Error('selftest failed: user commit-push stop bypass');
|
|
1162
|
-
}
|
|
@@ -27,12 +27,18 @@ export function buildIssueLedgerFromGeneratedCallouts(generatedReviewLedger = {}
|
|
|
27
27
|
blockers.push('ux_review_text_only_fallback');
|
|
28
28
|
if (generated.length && !issues.length)
|
|
29
29
|
blockers.push(generated.some((image) => image.callout_extraction_status === 'pending') ? 'callout_extraction_pending' : 'callout_extraction_schema_failed');
|
|
30
|
+
const primaryGenerated = generated.find((image) => image.id === existing?.generated_image_id)
|
|
31
|
+
|| generated.find((image) => image.id === issues[0]?.generated_review_image_id)
|
|
32
|
+
|| generated[0]
|
|
33
|
+
|| null;
|
|
30
34
|
return {
|
|
31
35
|
schema: 'sks.image-ux-issue-ledger.v3',
|
|
32
36
|
schema_version: 3,
|
|
33
37
|
extraction_source: 'image-ux-generated-review-ledger.json',
|
|
34
38
|
extraction_method: 'codex_exec_resume_output_schema_preferred',
|
|
35
39
|
extraction_schema: 'schemas/codex/image-ux-issue-ledger.schema.json',
|
|
40
|
+
generated_image_id: primaryGenerated?.id || existing?.generated_image_id || issues[0]?.generated_review_image_id || null,
|
|
41
|
+
generated_image_sha256: primaryGenerated?.sha256 || existing?.generated_image_sha256 || issues[0]?.generated_image_sha256 || null,
|
|
36
42
|
extracted_from_generated_callout: issues.length > 0,
|
|
37
43
|
issues,
|
|
38
44
|
blocking_issue_count: issues.filter((issue) => ['P0', 'P1'].includes(issue.severity) && !['fixed', 'accepted_not_applicable'].includes(issue.status)).length,
|