sneakoscope 6.1.0 → 6.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 +35 -11
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/bin/fast-inline.js +18 -9
- package/dist/bin/sks-dispatch.js +2 -2
- package/dist/cli/args.js +2 -0
- package/dist/cli/command-manifest-lite.js +2 -3
- package/dist/cli/command-registry.js +3 -4
- package/dist/cli/help-fast.js +1 -1
- package/dist/cli/install-helpers.js +116 -306
- package/dist/cli/install-tool-helpers.js +287 -0
- package/dist/cli/router.js +40 -4
- package/dist/commands/codex-lb.js +51 -20
- package/dist/commands/codex.js +39 -1
- package/dist/commands/doctor.js +242 -20
- package/dist/commands/tmux.js +5 -1
- package/dist/commands/zellij-monitor-pane.js +2 -0
- package/dist/commands/zellij-viewport-pane.js +3 -1
- package/dist/commands/zellij.js +1 -1
- package/dist/config/skills-manifest.json +59 -59
- package/dist/core/agent-bridge/agent-manifest.js +48 -0
- package/dist/core/agents/agent-command-surface.js +2 -1
- package/dist/core/agents/agent-effort-policy.js +38 -35
- package/dist/core/agents/agent-plan.js +100 -21
- package/dist/core/agents/agent-role-config.js +43 -46
- package/dist/core/agents/agent-runner-codex-exec.js +16 -3
- package/dist/core/agents/agent-schema.js +3 -2
- package/dist/core/agents/native-cli-session-swarm.js +1 -1
- package/dist/core/agents/zellij-right-lane-cockpit.js +2 -2
- package/dist/core/codex/agent-config-file-repair.js +94 -193
- package/dist/core/codex/codex-cli-update.js +723 -0
- package/dist/core/codex/codex-config-guard.js +185 -9
- package/dist/core/codex/codex-config-readability.js +21 -8
- package/dist/core/codex/codex-config-toml.js +14 -11
- package/dist/core/codex/codex-project-config-policy.js +3 -6
- package/dist/core/codex/codex-startup-config-postcheck.js +52 -42
- package/dist/core/codex-adapter.js +35 -22
- package/dist/core/codex-app/codex-agent-role-sync.js +13 -54
- package/dist/core/codex-app/codex-app-launcher.js +48 -17
- package/dist/core/codex-app/codex-app-restart.js +23 -2
- package/dist/core/codex-app/mcp-manager.js +679 -0
- package/dist/core/codex-app/sks-menubar.js +533 -8
- package/dist/core/codex-control/codex-0139-image-path-real-probe.js +15 -4
- package/dist/core/codex-control/codex-0139-web-search-probe.js +17 -6
- package/dist/core/codex-control/codex-lb-launch-recovery.js +293 -0
- package/dist/core/codex-control/codex-reliability-shield.js +89 -29
- package/dist/core/codex-control/codex-sdk-adapter.js +44 -8
- package/dist/core/codex-control/codex-task-runner.js +62 -9
- package/dist/core/codex-control/python-codex-sdk-adapter.js +30 -3
- package/dist/core/codex-exec-output-schema.js +35 -6
- package/dist/core/codex-lb/codex-lb-env.js +1 -1
- package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +291 -0
- package/dist/core/codex-native/codex-native-feature-broker.js +9 -16
- package/dist/core/codex-native/codex-native-repair-transaction.js +1 -1
- package/dist/core/codex-native/core-skill-manifest.js +8 -4
- package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -3
- package/dist/core/commands/agent-bridge-command.js +23 -2
- package/dist/core/commands/agent-command.js +19 -5
- package/dist/core/commands/basic-cli.js +47 -6
- package/dist/core/commands/command-utils.js +1 -1
- package/dist/core/commands/mad-sks-command.js +76 -10
- package/dist/core/commands/menubar-command.js +94 -0
- package/dist/core/commands/naruto-command.js +645 -1156
- package/dist/core/commands/research-command.js +293 -231
- package/dist/core/commands/run-command.js +100 -23
- package/dist/core/commands/team-command.js +2 -3
- package/dist/core/commands/team-legacy-observe-command.js +94 -359
- package/dist/core/commands/wiki-command.js +11 -5
- package/dist/core/db-safety.js +2 -2
- package/dist/core/decision-lattice.js +6 -6
- package/dist/core/doctor/codex-startup-config-repair.js +8 -3
- package/dist/core/doctor/doctor-codex-startup-repair.js +6 -141
- package/dist/core/feature-fixture-executor.js +71 -7
- package/dist/core/feature-fixture-runner.js +53 -12
- package/dist/core/feature-fixtures.js +47 -14
- package/dist/core/feature-registry.js +28 -27
- package/dist/core/fsx.js +1 -0
- package/dist/core/harness-conflicts.js +18 -9
- package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +14 -8
- package/dist/core/hooks-runtime/hook-io.js +8 -4
- package/dist/core/hooks-runtime/light-turn.js +70 -0
- package/dist/core/hooks-runtime/naruto-decision-gate.js +184 -0
- package/dist/core/hooks-runtime/payload-signals.js +270 -0
- package/dist/core/hooks-runtime/stop-repeat-guard.js +89 -0
- package/dist/core/hooks-runtime/team-digest.js +0 -1
- package/dist/core/hooks-runtime/tool-output-quarantine.js +93 -0
- package/dist/core/hooks-runtime.js +438 -354
- package/dist/core/init/skills.js +16 -30
- package/dist/core/init.js +144 -36
- package/dist/core/managed-assets/managed-assets-manifest.js +566 -10
- package/dist/core/mission.js +24 -1
- package/dist/core/pipeline-internals/runtime-core.js +570 -177
- package/dist/core/pipeline-internals/runtime-gates.js +174 -48
- package/dist/core/preflight/parallel-preflight-engine.js +66 -4
- package/dist/core/proof/route-adapter.js +1 -1
- package/dist/core/proof/route-proof-gate.js +7 -2
- package/dist/core/proof/selftest-proof-fixtures.js +3 -5
- package/dist/core/proof-field.js +1 -1
- package/dist/core/provider/model-router.js +42 -31
- package/dist/core/recallpulse/policy.js +12 -28
- package/dist/core/recallpulse.js +11 -6
- package/dist/core/release/npm-pack-proof.js +247 -0
- package/dist/core/release/package-dist-snapshot.js +151 -0
- package/dist/core/release/package-size-budget.js +4 -1
- package/dist/core/release/release-authorization-snapshot.js +115 -0
- package/dist/core/release/release-gate-affected-selector.js +14 -2
- package/dist/core/release/release-gate-cache-v2.js +30 -0
- package/dist/core/release/release-gate-contract.js +161 -0
- package/dist/core/release/release-gate-dag.js +1 -0
- package/dist/core/release/release-real-contract.js +90 -10
- package/dist/core/release-parallel-full-coverage.js +31 -143
- package/dist/core/research/claim-evidence-matrix.js +41 -6
- package/dist/core/research/experiment-plan.js +14 -10
- package/dist/core/research/falsification.js +9 -2
- package/dist/core/research/implementation-blueprint-densifier.js +82 -60
- package/dist/core/research/implementation-blueprint.js +32 -26
- package/dist/core/research/mock-result.js +122 -11
- package/dist/core/research/replication-pack.js +15 -8
- package/dist/core/research/research-adversarial-review.js +1068 -0
- package/dist/core/research/research-claim-builder.js +69 -17
- package/dist/core/research/research-claim-synthesizer.js +343 -0
- package/dist/core/research/research-cycle-runner.js +53 -3
- package/dist/core/research/research-falsification-runner.js +176 -0
- package/dist/core/research/research-final-reviewer.js +44 -125
- package/dist/core/research/research-plan-markdown.js +123 -0
- package/dist/core/research/research-realistic-report.js +14 -6
- package/dist/core/research/research-review-artifact-digest.js +66 -0
- package/dist/core/research/research-source-evidence.js +144 -0
- package/dist/core/research/research-source-layer-catalog.js +68 -0
- package/dist/core/research/research-source-ledger-merge.js +250 -12
- package/dist/core/research/research-source-shards.js +26 -70
- package/dist/core/research/research-stage-runner.js +237 -247
- package/dist/core/research/research-super-search.js +188 -0
- package/dist/core/research/research-synthesis-prompt.js +20 -1
- package/dist/core/research/research-synthesis-writer.js +86 -5
- package/dist/core/research/research-work-graph.js +25 -18
- package/dist/core/research/source-quality-report.js +21 -0
- package/dist/core/research.js +424 -390
- package/dist/core/retention.js +70 -2
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/dollar-manifest-lite.js +11 -11
- package/dist/core/routes.js +149 -69
- package/dist/core/runtime/task-profile.js +66 -0
- package/dist/core/runtime/verification-budget.js +12 -0
- package/dist/core/security/high-risk-contracts.js +6 -6
- package/dist/core/stop-gate/stop-gate-check.js +49 -12
- package/dist/core/subagents/agent-catalog.js +287 -0
- package/dist/core/subagents/model-policy.js +259 -0
- package/dist/core/subagents/naruto-help-contract.js +47 -0
- package/dist/core/subagents/official-subagent-config.js +488 -0
- package/dist/core/subagents/official-subagent-preparation.js +297 -0
- package/dist/core/subagents/official-subagent-prompt.js +159 -0
- package/dist/core/subagents/official-subagent-runner.js +129 -0
- package/dist/core/subagents/subagent-evidence.js +663 -0
- package/dist/core/subagents/terminology.js +16 -0
- package/dist/core/subagents/thread-budget.js +21 -0
- package/dist/core/subagents/triwiki-attention.js +168 -0
- package/dist/core/super-search/runtime-helpers.js +173 -19
- package/dist/core/super-search/runtime.js +140 -15
- package/dist/core/super-search/source-records.js +49 -8
- package/dist/core/team-review-policy.js +15 -0
- package/dist/core/triwiki/code-pack-head-freshness.js +291 -0
- package/dist/core/triwiki/triwiki-module-card.js +1 -1
- package/dist/core/triwiki-wrongness/wrongness-ledger.js +9 -2
- package/dist/core/version-manager.js +51 -1
- package/dist/core/version.js +1 -1
- package/dist/core/work-order-ledger.js +40 -1
- package/dist/core/zellij/zellij-fake-adapter.js +3 -1
- package/dist/core/zellij/zellij-launcher.js +49 -10
- package/dist/core/zellij/zellij-layout-builder.js +14 -5
- package/dist/core/zellij/zellij-official-subagent-activity.js +477 -0
- package/dist/core/zellij/zellij-official-subagent-telemetry.js +264 -0
- package/dist/core/zellij/zellij-pane-proof.js +9 -1
- package/dist/core/zellij/zellij-slot-pane-renderer.js +17 -5
- package/dist/core/zellij/zellij-slot-telemetry.js +15 -3
- package/dist/core/zellij/zellij-ui-mode.js +1 -1
- package/dist/core/zellij/zellij-update.js +14 -1
- package/dist/core/zellij/zellij-viewport-binder.js +3 -0
- package/dist/scripts/agent-role-config-repair-check.js +14 -16
- package/dist/scripts/architecture-guard-check.js +8 -1
- package/dist/scripts/canonical-test-runner.js +7 -1
- package/dist/scripts/check-route-modularity.js +0 -1
- package/dist/scripts/check-ts-contracts.js +1 -1
- package/dist/scripts/codex-control-all-pipelines-check.js +7 -3
- package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +27 -0
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +11 -1
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +9 -2
- package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +13 -2
- package/dist/scripts/codex-native-agent-role-content-check.js +27 -7
- package/dist/scripts/codex-native-repair-transaction-check.js +3 -1
- package/dist/scripts/codex-sdk-all-pipelines-check.js +7 -4
- package/dist/scripts/codex-sdk-backend-router-check.js +2 -0
- package/dist/scripts/codex-sdk-research-pipeline-check.js +30 -8
- package/dist/scripts/db-route-materialization-check.js +33 -0
- package/dist/scripts/docs-truthfulness-check.js +3 -1
- package/dist/scripts/doctor-codex-startup-repair-check.js +12 -15
- package/dist/scripts/doctor-fix-production-blackbox.js +12 -2
- package/dist/scripts/doctor-startup-config-repair-blackbox.js +8 -2
- package/dist/scripts/doctor-startup-config-repair-check.js +12 -2
- package/dist/scripts/install-update-preserves-config-check.js +6 -1
- package/dist/scripts/lib/codex-sdk-gate-lib.js +4 -0
- package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +0 -1
- package/dist/scripts/managed-role-manifest-parity-check.js +5 -4
- package/dist/scripts/naruto-codex-e2e-check.js +14 -7
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +4 -201
- package/dist/scripts/npm-publish-performance-check.js +20 -12
- package/dist/scripts/official-subagent-workflow-check.js +145 -0
- package/dist/scripts/package-published-contract-check.js +6 -29
- package/dist/scripts/packlist-performance-check.js +18 -21
- package/dist/scripts/parallel-verification-engine-check.js +2 -2
- package/dist/scripts/prepublish-release-check-or-fast.js +23 -86
- package/dist/scripts/python-codex-sdk-all-pipelines-check.js +8 -0
- package/dist/scripts/release-affected-selector-check.js +74 -1
- package/dist/scripts/release-check-stamp.js +153 -248
- package/dist/scripts/release-dag-full-coverage-check.js +7 -15
- package/dist/scripts/release-dynamic-presets-check.js +2 -1
- package/dist/scripts/release-gate-dag-runner-check.js +0 -1
- package/dist/scripts/release-gate-dag-runner.js +12 -1
- package/dist/scripts/release-gate-existence-audit.js +1 -2
- package/dist/scripts/release-parallel-full-coverage-check.js +12 -6
- package/dist/scripts/release-parallel-speed-budget-check.js +18 -2
- package/dist/scripts/release-real-check.js +26 -4
- package/dist/scripts/release-registry-check.js +61 -16
- package/dist/scripts/research-blueprint-densifier-check.js +2 -2
- package/dist/scripts/research-real-cycle-no-legacy-final-md-check.js +11 -7
- package/dist/scripts/sizecheck.js +2 -2
- package/dist/scripts/sks-3-1-4-directive-check-lib.js +8 -2
- package/dist/scripts/sks-3-1-5-directive-check-lib.js +3 -2
- package/dist/scripts/sks-3-1-6-directive-check-lib.js +5 -3
- package/dist/scripts/sks-menubar-install-check.js +14 -1
- package/dist/scripts/super-search-provider-interface-check.js +31 -18
- package/dist/scripts/trust-fixture-check.js +32 -10
- package/dist/scripts/wrongness-fixture-check.js +1 -1
- package/dist/scripts/zellij-layout-valid-check.js +5 -5
- package/dist/scripts/zellij-spawn-on-demand-layout-check.js +3 -3
- package/docs/demo.tape +1 -1
- package/infra-harness-gates.json +1486 -0
- package/package.json +15 -10
- package/release-gates.v2.json +4060 -0
- package/runtime-required-scripts.json +9 -0
- package/dist/commands/db.js +0 -6
- package/dist/core/commands/db-command.js +0 -146
- package/dist/core/research/prompt.js +0 -15
- package/dist/scripts/codex-0139-feature-probes-check.js +0 -30
- package/dist/scripts/codex-0139-marketplace-source-check.js +0 -13
- package/dist/scripts/codex-control-tool-call-sequence-repair-check.js +0 -14
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { stripVisibleDecisionAnswerBlocks } from '../routes.js';
|
|
2
|
+
export function extractLastMessage(payload = {}) {
|
|
3
|
+
return payload.last_assistant_message || payload.assistant_message || payload.message || payload.response || payload.raw || '';
|
|
4
|
+
}
|
|
5
|
+
export function extractUserPrompt(payload = {}) {
|
|
6
|
+
return payload.prompt
|
|
7
|
+
|| payload.user_prompt
|
|
8
|
+
|| payload.userPrompt
|
|
9
|
+
|| payload.message
|
|
10
|
+
|| payload.input?.prompt
|
|
11
|
+
|| payload.input?.message
|
|
12
|
+
|| payload.raw
|
|
13
|
+
|| '';
|
|
14
|
+
}
|
|
15
|
+
export function conversationId(payload = {}) {
|
|
16
|
+
return String(payload.conversation_id || payload.thread_id || payload.session_id || payload.chat_id || payload.cwd || 'default');
|
|
17
|
+
}
|
|
18
|
+
export function explicitConversationId(payload = {}) {
|
|
19
|
+
return payload.conversation_id || payload.thread_id || payload.session_id || payload.chat_id || null;
|
|
20
|
+
}
|
|
21
|
+
export function hookTurnId(payload = {}) {
|
|
22
|
+
return String(payload.turn_id || payload.turnId || payload.metadata?.turn_id || payload.metadata?.turnId || '');
|
|
23
|
+
}
|
|
24
|
+
export function extractCommand(payload = {}) {
|
|
25
|
+
return payload.command || payload.tool_input?.command || payload.toolInput?.command || payload.input?.command || payload.tool?.input?.command || '';
|
|
26
|
+
}
|
|
27
|
+
export function codexGitActionMetadataText(payload = {}) {
|
|
28
|
+
const seen = new Set();
|
|
29
|
+
const out = [];
|
|
30
|
+
const interesting = new Set([
|
|
31
|
+
'action',
|
|
32
|
+
'intent',
|
|
33
|
+
'operation',
|
|
34
|
+
'permission',
|
|
35
|
+
'description',
|
|
36
|
+
'kind',
|
|
37
|
+
'type',
|
|
38
|
+
'feature',
|
|
39
|
+
'tool_name',
|
|
40
|
+
'toolName',
|
|
41
|
+
'name',
|
|
42
|
+
'label',
|
|
43
|
+
'title',
|
|
44
|
+
'source',
|
|
45
|
+
'event',
|
|
46
|
+
'hook',
|
|
47
|
+
'hook_name',
|
|
48
|
+
'hookName',
|
|
49
|
+
'hook_event_name',
|
|
50
|
+
'hookEventName',
|
|
51
|
+
'id',
|
|
52
|
+
'command'
|
|
53
|
+
]);
|
|
54
|
+
const noisy = new Set([
|
|
55
|
+
'prompt',
|
|
56
|
+
'user_prompt',
|
|
57
|
+
'userPrompt',
|
|
58
|
+
'message',
|
|
59
|
+
'assistant_message',
|
|
60
|
+
'last_assistant_message',
|
|
61
|
+
'response',
|
|
62
|
+
'raw',
|
|
63
|
+
'stdout',
|
|
64
|
+
'stderr'
|
|
65
|
+
]);
|
|
66
|
+
function walk(value, depth = 0, parentKey = '') {
|
|
67
|
+
if (!value || typeof value !== 'object' || depth > 5 || seen.has(value))
|
|
68
|
+
return;
|
|
69
|
+
seen.add(value);
|
|
70
|
+
for (const [key, candidate] of Object.entries(value)) {
|
|
71
|
+
if (noisy.has(key))
|
|
72
|
+
continue;
|
|
73
|
+
if (typeof candidate === 'string') {
|
|
74
|
+
if (interesting.has(key) || /\b(?:codex[_\s-]*app|git[_\s-]*actions?|codex_git_|gitCommit|gitPush|pull\s+request)\b/i.test(candidate)) {
|
|
75
|
+
out.push(`${key}:${candidate}`);
|
|
76
|
+
}
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (candidate && typeof candidate === 'object') {
|
|
80
|
+
const allowedContainer = interesting.has(key)
|
|
81
|
+
|| /^(?:input|metadata|context|client|thread|session|request|payload|tool|tool_input|toolInput|permission_request|permissionRequest)$/i.test(key)
|
|
82
|
+
|| parentKey;
|
|
83
|
+
if (allowedContainer)
|
|
84
|
+
walk(candidate, depth + 1, key);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
walk(payload);
|
|
89
|
+
return out.join(' ');
|
|
90
|
+
}
|
|
91
|
+
export function codexGitActionMetadataSignal(text = '') {
|
|
92
|
+
const s = String(text || '');
|
|
93
|
+
if (!s)
|
|
94
|
+
return false;
|
|
95
|
+
const action = String(s)
|
|
96
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
97
|
+
.replace(/[_-]+/g, ' ');
|
|
98
|
+
if (/\bcodex\s*app\b[\s\S]{0,120}\bgit\b[\s\S]{0,120}\b(?:action|actions|commit|push|pr|pull request)\b/i.test(action))
|
|
99
|
+
return true;
|
|
100
|
+
if (/\bgit\s*actions?\b[\s\S]{0,120}\b(?:commit|push|pr|pull request|commit\s*(?:and|&)\s*push)\b/i.test(action))
|
|
101
|
+
return true;
|
|
102
|
+
if (/\bcodex\s*git\s*(?:commit|push|pr|pull request|commit\s*(?:and|&)\s*push)\b/i.test(action))
|
|
103
|
+
return true;
|
|
104
|
+
if (/\b(?:git\s*)?(?:commit|push|commit\s*(?:and|&)\s*push|create\s+(?:a\s+)?pull\s+request|pull\s+request|pr)\b/i.test(action)) {
|
|
105
|
+
return /\b(?:action|intent|operation|permission|feature|tool\s*name|source|event|hook|name|label|title|type|kind|id)\s*:/i.test(action);
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
export function toolFailed(payload = {}) {
|
|
110
|
+
const candidates = [
|
|
111
|
+
payload.exit_code,
|
|
112
|
+
payload.exitCode,
|
|
113
|
+
payload.tool_response?.exit_code,
|
|
114
|
+
payload.toolResponse?.exitCode,
|
|
115
|
+
payload.result?.exit_code,
|
|
116
|
+
payload.result?.exitCode
|
|
117
|
+
];
|
|
118
|
+
for (const candidate of candidates) {
|
|
119
|
+
if (candidate === undefined || candidate === null || candidate === '')
|
|
120
|
+
continue;
|
|
121
|
+
const n = Number(candidate);
|
|
122
|
+
if (Number.isFinite(n))
|
|
123
|
+
return n !== 0;
|
|
124
|
+
}
|
|
125
|
+
if (payload.isError === true || payload.tool_response?.isError === true || payload.toolResponse?.isError === true || payload.result?.isError === true)
|
|
126
|
+
return true;
|
|
127
|
+
if (payload.success === false || payload.tool_response?.success === false || payload.toolResponse?.success === false || payload.result?.success === false)
|
|
128
|
+
return true;
|
|
129
|
+
if (payload.executed === false)
|
|
130
|
+
return true;
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
export function compactAnswerContext(prompt = '') {
|
|
134
|
+
return [
|
|
135
|
+
'SKS answer-only pipeline active (light turn).',
|
|
136
|
+
'Answer the user directly. Do not create or continue a mission, prepare a route, reconcile project skills, load active route context, read TriWiki/code-pack preflight state, or open a subagent workflow for this turn.',
|
|
137
|
+
'Use tools only when the answer itself needs current repository facts, official documentation, web evidence, or another source explicitly requested by the user.',
|
|
138
|
+
`Question: ${String(prompt || '').trim()}`
|
|
139
|
+
].join('\n');
|
|
140
|
+
}
|
|
141
|
+
export function looksLikeMadSksConfirmationPrompt(prompt = '') {
|
|
142
|
+
return /^(yes|y|no|n|confirm|confirmed|approve|approved|proceed|continue|ok|okay|stop|abort|cancel|deny|denied|네|예|응|아니|아니요|허용|승인|진행|계속|중단|취소|거부|삭제\s*허용|테이블\s*삭제\s*허용)(?=$|\s|[.!?。!?,,])/i.test(String(prompt || '').trim());
|
|
143
|
+
}
|
|
144
|
+
export function observedParentModel(payload = {}) {
|
|
145
|
+
const value = payload.parent_model
|
|
146
|
+
|| payload.parentModel
|
|
147
|
+
|| payload.model
|
|
148
|
+
|| payload.metadata?.parent_model
|
|
149
|
+
|| payload.metadata?.model
|
|
150
|
+
|| payload.session?.model
|
|
151
|
+
|| null;
|
|
152
|
+
return typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
153
|
+
}
|
|
154
|
+
export function observedParentModelMismatch(model, expectedModel) {
|
|
155
|
+
const value = String(model || '').trim();
|
|
156
|
+
if (!value)
|
|
157
|
+
return false;
|
|
158
|
+
return value.toLowerCase() !== expectedModel && !/gpt[-_. ]?5\.6[-_. ]?sol|\bsol(?:\s+max)?\b/i.test(value);
|
|
159
|
+
}
|
|
160
|
+
export function looksLikeCodexUiSettingsEvent(payload = {}) {
|
|
161
|
+
const prompt = stripVisibleDecisionAnswerBlocks(extractUserPrompt(payload));
|
|
162
|
+
const haystack = [
|
|
163
|
+
payload.action,
|
|
164
|
+
payload.intent,
|
|
165
|
+
payload.operation,
|
|
166
|
+
payload.permission,
|
|
167
|
+
payload.description,
|
|
168
|
+
payload.kind,
|
|
169
|
+
payload.type,
|
|
170
|
+
payload.feature,
|
|
171
|
+
payload.source,
|
|
172
|
+
payload.event,
|
|
173
|
+
payload.hook,
|
|
174
|
+
payload.hook_name,
|
|
175
|
+
payload.metadata?.action,
|
|
176
|
+
payload.metadata?.intent,
|
|
177
|
+
payload.metadata?.operation,
|
|
178
|
+
payload.metadata?.feature,
|
|
179
|
+
payload.metadata?.source,
|
|
180
|
+
payload.context?.surface,
|
|
181
|
+
payload.session?.surface
|
|
182
|
+
].filter(Boolean).join(' ');
|
|
183
|
+
return !prompt && /\b(?:settings|preferences|profile|speed|fast[_\s-]*mode|reasoning|model[_\s-]*select|codex[_\s-]*app)\b/i.test(haystack);
|
|
184
|
+
}
|
|
185
|
+
export function looksLikeCodexGitAction(payload = {}) {
|
|
186
|
+
const prompt = stripVisibleDecisionAnswerBlocks(extractUserPrompt(payload));
|
|
187
|
+
const metadataText = codexGitActionMetadataText(payload);
|
|
188
|
+
const haystack = [
|
|
189
|
+
metadataText,
|
|
190
|
+
payload.action,
|
|
191
|
+
payload.intent,
|
|
192
|
+
payload.operation,
|
|
193
|
+
payload.permission,
|
|
194
|
+
payload.description,
|
|
195
|
+
payload.kind,
|
|
196
|
+
payload.type,
|
|
197
|
+
payload.feature,
|
|
198
|
+
payload.tool_name,
|
|
199
|
+
payload.toolName,
|
|
200
|
+
payload.source,
|
|
201
|
+
payload.event,
|
|
202
|
+
payload.hook,
|
|
203
|
+
payload.hook_name,
|
|
204
|
+
payload.input?.action,
|
|
205
|
+
payload.input?.intent,
|
|
206
|
+
payload.input?.operation,
|
|
207
|
+
payload.input?.feature,
|
|
208
|
+
payload.input?.source,
|
|
209
|
+
payload.metadata?.action,
|
|
210
|
+
payload.metadata?.intent,
|
|
211
|
+
payload.metadata?.operation,
|
|
212
|
+
payload.metadata?.feature,
|
|
213
|
+
payload.metadata?.source
|
|
214
|
+
].filter(Boolean).join(' ');
|
|
215
|
+
const codexAppGitSignal = /\bcodex[_\s-]*app\b[\s\S]{0,80}\bgit\b[\s\S]{0,80}\b(?:action|actions|commit|push|pr)\b/i.test(haystack);
|
|
216
|
+
const gitActionSignal = /\bgit[_\s-]*actions?\b[\s\S]{0,80}\b(?:commit|push|commit[\s_-]*(?:and|&)?[\s_-]*push)\b/i.test(haystack);
|
|
217
|
+
const appSignal = codexGitActionMetadataSignal(metadataText)
|
|
218
|
+
|| codexAppGitSignal
|
|
219
|
+
|| gitActionSignal
|
|
220
|
+
|| /\b(?:codex[_\s-]*(?:app[_\s-]*)?)?(?:git[_\s-]*)?(?:commit[_\s-]*message|git[_\s-]*commit|git[_\s-]*push|git[_\s-]*pr|codex_git_commit|codex_git_push|codex_git_pr)\b/i.test(haystack)
|
|
221
|
+
|| /커밋\s*메시지\s*생성/i.test(haystack);
|
|
222
|
+
const promptSignal = /\bgenerate(?:\s+a)?(?:\s+git)?\s+commit\s+message\b/i.test(prompt)
|
|
223
|
+
|| /\bcommit\s+message\b[\s\S]{0,80}\b(?:staged|diff|changes?|git)\b/i.test(prompt)
|
|
224
|
+
|| looksLikeStockCodexGitActionPrompt(prompt)
|
|
225
|
+
|| /커밋\s*메시지\s*생성/i.test(prompt);
|
|
226
|
+
if (!appSignal && !promptSignal)
|
|
227
|
+
return false;
|
|
228
|
+
if (looksLikeStockCodexGitActionPrompt(prompt))
|
|
229
|
+
return true;
|
|
230
|
+
if (appSignal)
|
|
231
|
+
return true;
|
|
232
|
+
return !looksLikeUserImplementationRequest(prompt);
|
|
233
|
+
}
|
|
234
|
+
export function looksLikeStockCodexGitActionPrompt(prompt = '') {
|
|
235
|
+
const text = String(prompt || '').trim();
|
|
236
|
+
if (!text || text.length > 120)
|
|
237
|
+
return false;
|
|
238
|
+
return /^(?:generate\s+(?:a\s+)?git\s+commit\s+message(?:\s+for\s+(?:the\s+)?(?:staged\s+)?diff)?|commit\s+changes|commit\s+and\s+push\s+changes|push\s+changes|create\s+(?:a\s+)?commit|create\s+(?:a\s+)?pull\s+request)\.?$/i.test(text);
|
|
239
|
+
}
|
|
240
|
+
export function looksLikeCodexGitActionStopCompletion(last = '', payload = {}) {
|
|
241
|
+
const text = String(last || '').trim();
|
|
242
|
+
const metadataText = codexGitActionMetadataText(payload);
|
|
243
|
+
const haystack = [
|
|
244
|
+
metadataText,
|
|
245
|
+
payload.action,
|
|
246
|
+
payload.intent,
|
|
247
|
+
payload.operation,
|
|
248
|
+
payload.kind,
|
|
249
|
+
payload.type,
|
|
250
|
+
payload.feature,
|
|
251
|
+
payload.source,
|
|
252
|
+
payload.event,
|
|
253
|
+
payload.metadata?.action,
|
|
254
|
+
payload.metadata?.intent,
|
|
255
|
+
payload.metadata?.operation,
|
|
256
|
+
payload.metadata?.feature,
|
|
257
|
+
payload.metadata?.source
|
|
258
|
+
].filter(Boolean).join(' ');
|
|
259
|
+
if (codexGitActionMetadataSignal(metadataText))
|
|
260
|
+
return true;
|
|
261
|
+
if (/\bcodex[_\s-]*app\b[\s\S]{0,80}\bgit\b[\s\S]{0,80}\b(?:action|commit|push|pr)\b/i.test(haystack))
|
|
262
|
+
return true;
|
|
263
|
+
if (!text || text.length > 180)
|
|
264
|
+
return false;
|
|
265
|
+
return /^(?:commit(?:ted)?(?:\s+and\s+pushed)?(?:\s+changes)?(?:\s+complete[.!]?)?|push(?:ed)?(?:\s+changes)?(?:\s+complete[.!]?)?|created\s+(?:a\s+)?pull\s+request[.!]?)$/i.test(text);
|
|
266
|
+
}
|
|
267
|
+
function looksLikeUserImplementationRequest(text = '') {
|
|
268
|
+
return /(fix|bug|broken|error|issue|implement|change|update|repair|수정|버그|오류|에러|문제|고쳐|고치|해결|변경|수리|패치|안생기|안\s*생기)/i.test(String(text || ''));
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=payload-signals.js.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { nowIso, readJson, sha256, writeJsonAtomic } from '../fsx.js';
|
|
3
|
+
import { appendMissionStatus } from '../recallpulse.js';
|
|
4
|
+
import { conversationId } from './payload-signals.js';
|
|
5
|
+
const STOP_REPEAT_GUARD_ARTIFACT = 'stop-hook-repeat-guard.json';
|
|
6
|
+
const STOP_REPEAT_GUARD_WINDOW_MS = 10 * 60 * 1000;
|
|
7
|
+
const STOP_REPEAT_GUARD_MAX_ENTRIES = 25;
|
|
8
|
+
const DEFAULT_STOP_REPEAT_GUARD_LIMIT = 2;
|
|
9
|
+
export async function finalizationRepeatDecision(root, state = {}, payload = {}, reason = '', kind = 'finalization') {
|
|
10
|
+
const now = nowIso();
|
|
11
|
+
const guardPath = path.join(root, '.sneakoscope', 'state', STOP_REPEAT_GUARD_ARTIFACT);
|
|
12
|
+
const previous = await readJson(guardPath, {}).catch(() => ({}));
|
|
13
|
+
const limit = stopRepeatGuardLimit();
|
|
14
|
+
const entries = pruneStopRepeatEntries(previous.entries || {}, now);
|
|
15
|
+
const key = stopRepeatKey(state, payload, reason, kind);
|
|
16
|
+
const prior = entries[key] || {};
|
|
17
|
+
const repeatCount = stopRepeatInWindow(prior, now)
|
|
18
|
+
? Number(prior.repeat_count || 0) + 1
|
|
19
|
+
: 1;
|
|
20
|
+
const record = {
|
|
21
|
+
schema_version: 1,
|
|
22
|
+
updated_at: now,
|
|
23
|
+
window_ms: STOP_REPEAT_GUARD_WINDOW_MS,
|
|
24
|
+
limit,
|
|
25
|
+
entries: {
|
|
26
|
+
...entries,
|
|
27
|
+
[key]: {
|
|
28
|
+
kind,
|
|
29
|
+
route: state.route_command || state.route || state.mode || null,
|
|
30
|
+
mission_id: state.mission_id || null,
|
|
31
|
+
conversation_id: conversationId(payload),
|
|
32
|
+
first_seen: stopRepeatInWindow(prior, now) ? (prior.first_seen || now) : now,
|
|
33
|
+
last_seen: now,
|
|
34
|
+
repeat_count: repeatCount,
|
|
35
|
+
tripped: repeatCount >= limit,
|
|
36
|
+
reason
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
await writeJsonAtomic(guardPath, record).catch(() => null);
|
|
41
|
+
if (state.mission_id) {
|
|
42
|
+
await appendMissionStatus(root, state.mission_id, {
|
|
43
|
+
category: repeatCount >= limit ? 'warning' : 'blocker',
|
|
44
|
+
audience: ['user', 'route', 'final-summary'],
|
|
45
|
+
stage_id: 'before_final',
|
|
46
|
+
message: repeatCount >= limit
|
|
47
|
+
? `Repeated ${kind} stop prompt was suppressed; route completion is still unclaimed until evidence passes.`
|
|
48
|
+
: reason,
|
|
49
|
+
dedupe_key: key,
|
|
50
|
+
evidence: [STOP_REPEAT_GUARD_ARTIFACT]
|
|
51
|
+
}).catch(() => null);
|
|
52
|
+
}
|
|
53
|
+
if (repeatCount < limit)
|
|
54
|
+
return null;
|
|
55
|
+
return {
|
|
56
|
+
continue: true,
|
|
57
|
+
systemMessage: `SKS stop hook repeat guard suppressed repeated ${kind} prompt after ${repeatCount} identical block(s). No completion success is claimed by the hook.`
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function stopRepeatKey(state = {}, payload = {}, reason = '', kind = '') {
|
|
61
|
+
return sha256(JSON.stringify({
|
|
62
|
+
kind,
|
|
63
|
+
reason,
|
|
64
|
+
conversation_id: conversationId(payload),
|
|
65
|
+
mission_id: state.mission_id || null,
|
|
66
|
+
route: state.route_command || state.route || state.mode || null,
|
|
67
|
+
gate: state.stop_gate || null
|
|
68
|
+
})).slice(0, 24);
|
|
69
|
+
}
|
|
70
|
+
function stopRepeatGuardLimit() {
|
|
71
|
+
const raw = Number.parseInt(process.env.SKS_STOP_REPEAT_GUARD_LIMIT || '', 10);
|
|
72
|
+
if (!Number.isFinite(raw))
|
|
73
|
+
return DEFAULT_STOP_REPEAT_GUARD_LIMIT;
|
|
74
|
+
return Math.max(1, Math.min(20, raw));
|
|
75
|
+
}
|
|
76
|
+
function stopRepeatInWindow(entry = {}, now = nowIso()) {
|
|
77
|
+
const last = Date.parse(entry.last_seen || '');
|
|
78
|
+
const current = Date.parse(now);
|
|
79
|
+
if (!Number.isFinite(last) || !Number.isFinite(current))
|
|
80
|
+
return false;
|
|
81
|
+
return current - last <= STOP_REPEAT_GUARD_WINDOW_MS;
|
|
82
|
+
}
|
|
83
|
+
function pruneStopRepeatEntries(entries = {}, now = nowIso()) {
|
|
84
|
+
return Object.fromEntries(Object.entries(entries)
|
|
85
|
+
.filter(([, entry]) => stopRepeatInWindow(entry, now))
|
|
86
|
+
.sort((a, b) => Date.parse(b[1]?.last_seen || '') - Date.parse(a[1]?.last_seen || ''))
|
|
87
|
+
.slice(0, STOP_REPEAT_GUARD_MAX_ENTRIES));
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=stop-repeat-guard.js.map
|
|
@@ -30,7 +30,6 @@ export async function teamLiveDigest(root, state = {}) {
|
|
|
30
30
|
const lines = events.map(formatTeamDigestEvent);
|
|
31
31
|
const context = boundText([
|
|
32
32
|
`SKS Team live digest: mission ${id}, phase ${phase}, source ${source}.`,
|
|
33
|
-
`Open Zellij multi-view with: sks team open-zellij ${id}`,
|
|
34
33
|
`Open live view with: sks team watch ${id}`,
|
|
35
34
|
'Recent events:',
|
|
36
35
|
...lines.map((line) => `- ${line}`)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { nowIso, readJson, sha256, writeJsonAtomic } from '../fsx.js';
|
|
3
|
+
export const TOOL_OUTPUT_QUARANTINE_SCHEMA = 'sks.tool-output-quarantine.v1';
|
|
4
|
+
export function missingToolOutputCallId(text) {
|
|
5
|
+
return String(text || '').match(/\[No tool output found for (?:custom\s+)?tool call\s+([^\].\s]+)\.?\]/i)?.[1] || null;
|
|
6
|
+
}
|
|
7
|
+
export function missingToolOutputCallIdFromPayload(payload = {}) {
|
|
8
|
+
const candidates = [
|
|
9
|
+
payload.prompt,
|
|
10
|
+
payload.user_prompt,
|
|
11
|
+
payload.userPrompt,
|
|
12
|
+
payload.last_assistant_message,
|
|
13
|
+
payload.assistant_message,
|
|
14
|
+
payload.previous_assistant_message,
|
|
15
|
+
payload.prior_assistant_message,
|
|
16
|
+
payload.response,
|
|
17
|
+
payload.raw,
|
|
18
|
+
payload.error,
|
|
19
|
+
payload.error_message,
|
|
20
|
+
payload.errorMessage,
|
|
21
|
+
payload.last_error,
|
|
22
|
+
payload.raw_error,
|
|
23
|
+
payload.rawError,
|
|
24
|
+
payload.result
|
|
25
|
+
];
|
|
26
|
+
const seen = new Set();
|
|
27
|
+
let visited = 0;
|
|
28
|
+
const scan = (value, depth = 0) => {
|
|
29
|
+
if (visited >= 128 || depth > 4 || value === null || value === undefined)
|
|
30
|
+
return null;
|
|
31
|
+
visited += 1;
|
|
32
|
+
if (typeof value === 'string' || typeof value === 'number')
|
|
33
|
+
return missingToolOutputCallId(value);
|
|
34
|
+
if (typeof value !== 'object' || seen.has(value))
|
|
35
|
+
return null;
|
|
36
|
+
seen.add(value);
|
|
37
|
+
if (Array.isArray(value)) {
|
|
38
|
+
for (const item of value) {
|
|
39
|
+
const found = scan(item, depth + 1);
|
|
40
|
+
if (found)
|
|
41
|
+
return found;
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
for (const nested of Object.values(value)) {
|
|
46
|
+
const found = scan(nested, depth + 1);
|
|
47
|
+
if (found)
|
|
48
|
+
return found;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
};
|
|
52
|
+
for (const candidate of candidates) {
|
|
53
|
+
const found = scan(candidate);
|
|
54
|
+
if (found)
|
|
55
|
+
return found;
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
export function toolOutputQuarantinePath(root, sessionKey) {
|
|
60
|
+
return path.join(root, '.sneakoscope', 'state', 'tool-output-quarantine', `${sha256(String(sessionKey || 'default')).slice(0, 32)}.json`);
|
|
61
|
+
}
|
|
62
|
+
export async function readToolOutputQuarantine(root, sessionKey) {
|
|
63
|
+
const record = await readJson(toolOutputQuarantinePath(root, sessionKey), null).catch(() => null);
|
|
64
|
+
return record?.schema === TOOL_OUTPUT_QUARANTINE_SCHEMA && record.active === true ? record : null;
|
|
65
|
+
}
|
|
66
|
+
export async function quarantineMissingToolOutput(input) {
|
|
67
|
+
const previous = await readToolOutputQuarantine(input.root, input.sessionKey);
|
|
68
|
+
const now = nowIso();
|
|
69
|
+
const record = {
|
|
70
|
+
schema: TOOL_OUTPUT_QUARANTINE_SCHEMA,
|
|
71
|
+
active: true,
|
|
72
|
+
session_key_hash: sha256(String(input.sessionKey || 'default')).slice(0, 24),
|
|
73
|
+
call_id: String(input.callId || previous?.call_id || 'unknown'),
|
|
74
|
+
mission_id: String(input.missionId || previous?.mission_id || '').trim() || null,
|
|
75
|
+
turn_id: String(input.turnId || '').trim() || previous?.turn_id || null,
|
|
76
|
+
first_seen_at: previous?.first_seen_at || now,
|
|
77
|
+
updated_at: now,
|
|
78
|
+
recovery: 'fresh_thread_required'
|
|
79
|
+
};
|
|
80
|
+
await writeJsonAtomic(toolOutputQuarantinePath(input.root, input.sessionKey), record);
|
|
81
|
+
return record;
|
|
82
|
+
}
|
|
83
|
+
export function interruptedToolOutputRecoveryBlockReason(input = {}) {
|
|
84
|
+
const callId = String(input.callId || 'unknown');
|
|
85
|
+
const missionId = String(input.missionId || '').trim() || 'none';
|
|
86
|
+
return [
|
|
87
|
+
`SKS blocked same-thread continuation because custom tool call ${callId} has no correlated output (active mission: ${missionId}).`,
|
|
88
|
+
'The current Codex conversation state may be structurally invalid, so additional context cannot repair the pending Responses request.',
|
|
89
|
+
'Treat the call result as unknown and do not replay a possibly mutating action.',
|
|
90
|
+
'Upgrade the selected codex-lb to 1.21.0-beta.3 or later, or explicitly switch with `sks codex-lb use-oauth`, then open a fresh Codex thread and continue the persisted mission after inspecting side effects.'
|
|
91
|
+
].join(' ');
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=tool-output-quarantine.js.map
|