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,663 @@
|
|
|
1
|
+
import fsp from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { appendJsonlBounded, nowIso, writeJsonAtomic } from '../fsx.js';
|
|
4
|
+
export const SUBAGENT_EVIDENCE_SCHEMA = 'sks.subagent-evidence.v1';
|
|
5
|
+
export const SUBAGENT_EVENT_SCHEMA = 'sks.subagent-event.v1';
|
|
6
|
+
export const SUBAGENT_PARENT_SUMMARY_SCHEMA = 'sks.subagent-parent-summary.v1';
|
|
7
|
+
export const SUBAGENT_EVIDENCE_FILENAME = 'subagent-evidence.json';
|
|
8
|
+
export const SUBAGENT_EVENT_LOG_FILENAME = 'subagent-events.jsonl';
|
|
9
|
+
export const SUBAGENT_PARENT_SUMMARY_FILENAME = 'subagent-parent-summary.json';
|
|
10
|
+
export function normalizeSubagentEvent(payload, explicitEventName) {
|
|
11
|
+
const row = isRecord(payload) ? payload : {};
|
|
12
|
+
const nested = isRecord(row.payload)
|
|
13
|
+
? row.payload
|
|
14
|
+
: isRecord(row.data)
|
|
15
|
+
? row.data
|
|
16
|
+
: isRecord(row.input)
|
|
17
|
+
? row.input
|
|
18
|
+
: {};
|
|
19
|
+
const merged = { ...nested, ...row };
|
|
20
|
+
const eventName = normalizeEventName(explicitEventName
|
|
21
|
+
?? row.hook_event_name
|
|
22
|
+
?? row.hookEventName
|
|
23
|
+
?? row.event_name
|
|
24
|
+
?? row.eventName
|
|
25
|
+
?? row.event
|
|
26
|
+
?? row.type
|
|
27
|
+
?? nested.hook_event_name
|
|
28
|
+
?? nested.hookEventName
|
|
29
|
+
?? nested.event_name
|
|
30
|
+
?? nested.eventName
|
|
31
|
+
?? nested.event
|
|
32
|
+
?? nested.type);
|
|
33
|
+
if (!eventName)
|
|
34
|
+
return null;
|
|
35
|
+
const persistedOutcome = row.schema === SUBAGENT_EVENT_SCHEMA
|
|
36
|
+
? normalizePersistedOutcome(row.outcome, eventName)
|
|
37
|
+
: null;
|
|
38
|
+
const explicitThreadId = firstText(row.thread_id, row.threadId, row.agent_thread_id, row.agentThreadId, row.subagent_thread_id, row.subagentThreadId, nested.thread_id, nested.threadId, nested.agent_thread_id, nested.agentThreadId, nested.subagent_thread_id, nested.subagentThreadId, recordId(row.thread), recordId(nested.thread));
|
|
39
|
+
const agentId = firstText(row.agent_id, row.agentId, nested.agent_id, nested.agentId, recordId(row.agent), recordId(nested.agent));
|
|
40
|
+
const sessionId = firstText(row.session_id, row.sessionId, nested.session_id, nested.sessionId, recordId(row.session), recordId(nested.session));
|
|
41
|
+
// Official SubagentStart/SubagentStop payloads identify the child with
|
|
42
|
+
// agent_id. session_id is the parent/session scope and must never be used as
|
|
43
|
+
// a child identity because every sibling can share it.
|
|
44
|
+
const threadId = explicitThreadId || agentId || null;
|
|
45
|
+
const threadIdSource = explicitThreadId
|
|
46
|
+
? 'thread_id'
|
|
47
|
+
: agentId
|
|
48
|
+
? 'agent_id'
|
|
49
|
+
: null;
|
|
50
|
+
return {
|
|
51
|
+
schema: SUBAGENT_EVENT_SCHEMA,
|
|
52
|
+
event_name: eventName,
|
|
53
|
+
thread_id: threadId,
|
|
54
|
+
thread_id_source: threadIdSource,
|
|
55
|
+
agent_id: agentId || null,
|
|
56
|
+
session_id: sessionId || null,
|
|
57
|
+
turn_id: firstText(row.turn_id, row.turnId, nested.turn_id, nested.turnId) || null,
|
|
58
|
+
run_id: firstText(row.run_id, row.runId, row.workflow_run_id, row.workflowRunId, nested.run_id, nested.runId, nested.workflow_run_id, nested.workflowRunId) || null,
|
|
59
|
+
run_epoch: firstText(row.run_epoch, row.runEpoch, row.execution_epoch, row.executionEpoch, nested.run_epoch, nested.runEpoch, nested.execution_epoch, nested.executionEpoch) || null,
|
|
60
|
+
model: firstText(row.model, nested.model) || null,
|
|
61
|
+
outcome: persistedOutcome ?? (eventName === 'SubagentStart'
|
|
62
|
+
? 'started'
|
|
63
|
+
: stopFailed(merged)
|
|
64
|
+
? 'failed'
|
|
65
|
+
: stopAmbiguous(merged)
|
|
66
|
+
? 'ambiguous'
|
|
67
|
+
: 'stopped'),
|
|
68
|
+
occurred_at: firstText(row.occurred_at, row.timestamp, row.created_at, row.ts, nested.occurred_at, nested.timestamp, nested.created_at, nested.ts) || nowIso()
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function buildSubagentEvidence(input) {
|
|
72
|
+
const requestedSubagents = normalizeRequested(input.requestedSubagents);
|
|
73
|
+
const normalizedEvents = (input.events || [])
|
|
74
|
+
.map((event) => normalizeSubagentEvent(event))
|
|
75
|
+
.filter((event) => Boolean(event));
|
|
76
|
+
const parentSummary = normalizeSubagentParentSummary(input.parentSummary);
|
|
77
|
+
const runScope = resolveRunScope(input, normalizedEvents, parentSummary);
|
|
78
|
+
const scopedEvents = scopeSubagentEvents(normalizedEvents, runScope);
|
|
79
|
+
const events = scopedEvents.events;
|
|
80
|
+
const starts = new Set();
|
|
81
|
+
const successfulStops = new Set();
|
|
82
|
+
const failedStops = new Set();
|
|
83
|
+
const unmatchedStops = new Set();
|
|
84
|
+
const ambiguousStops = new Set();
|
|
85
|
+
const eventSources = new Set();
|
|
86
|
+
let missingThreadId = false;
|
|
87
|
+
const parentSummaryStructurallyTrustworthy = parentSummary.trustworthy
|
|
88
|
+
&& runScope.blockers.length === 0
|
|
89
|
+
&& runScope.parentBlockers.length === 0;
|
|
90
|
+
const parentCompletedStructurallyTrustworthy = parentSummaryStructurallyTrustworthy
|
|
91
|
+
&& parentSummary.status === 'completed';
|
|
92
|
+
for (const event of events) {
|
|
93
|
+
eventSources.add(event.event_name);
|
|
94
|
+
if (!event.thread_id) {
|
|
95
|
+
missingThreadId = true;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (event.event_name === 'SubagentStart') {
|
|
99
|
+
starts.add(event.thread_id);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (!starts.has(event.thread_id)) {
|
|
103
|
+
unmatchedStops.add(event.thread_id);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (event.outcome === 'failed') {
|
|
107
|
+
failedStops.add(event.thread_id);
|
|
108
|
+
successfulStops.delete(event.thread_id);
|
|
109
|
+
ambiguousStops.delete(event.thread_id);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (event.outcome === 'ambiguous') {
|
|
113
|
+
ambiguousStops.add(event.thread_id);
|
|
114
|
+
successfulStops.delete(event.thread_id);
|
|
115
|
+
failedStops.delete(event.thread_id);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const parentOutcome = parentSummary.thread_outcomes.get(event.thread_id);
|
|
119
|
+
if (parentOutcome === 'failed') {
|
|
120
|
+
failedStops.add(event.thread_id);
|
|
121
|
+
successfulStops.delete(event.thread_id);
|
|
122
|
+
ambiguousStops.delete(event.thread_id);
|
|
123
|
+
}
|
|
124
|
+
else if (parentOutcome === 'completed' && parentCompletedStructurallyTrustworthy) {
|
|
125
|
+
successfulStops.add(event.thread_id);
|
|
126
|
+
failedStops.delete(event.thread_id);
|
|
127
|
+
ambiguousStops.delete(event.thread_id);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
ambiguousStops.add(event.thread_id);
|
|
131
|
+
successfulStops.delete(event.thread_id);
|
|
132
|
+
failedStops.delete(event.thread_id);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const parentOutcomeThreadIds = [...parentSummary.thread_outcomes.keys()].sort();
|
|
136
|
+
const parentOutcomeThreadIdSet = new Set(parentOutcomeThreadIds);
|
|
137
|
+
const missingParentOutcomeThreadIds = [...starts]
|
|
138
|
+
.filter((threadId) => !parentOutcomeThreadIdSet.has(threadId))
|
|
139
|
+
.sort();
|
|
140
|
+
const unobservedParentOutcomeThreadIds = parentOutcomeThreadIds
|
|
141
|
+
.filter((threadId) => !starts.has(threadId));
|
|
142
|
+
const parentThreadIdentityBlockers = [
|
|
143
|
+
...missingParentOutcomeThreadIds.map((threadId) => `parent_thread_outcome_missing_for_started_thread:${threadId}`),
|
|
144
|
+
...unobservedParentOutcomeThreadIds.map((threadId) => `parent_thread_outcome_without_start:${threadId}`)
|
|
145
|
+
];
|
|
146
|
+
const parentSummaryTrustworthy = parentSummaryStructurallyTrustworthy
|
|
147
|
+
&& parentThreadIdentityBlockers.length === 0;
|
|
148
|
+
if (!parentSummaryTrustworthy) {
|
|
149
|
+
for (const threadId of successfulStops) {
|
|
150
|
+
successfulStops.delete(threadId);
|
|
151
|
+
if (!failedStops.has(threadId))
|
|
152
|
+
ambiguousStops.add(threadId);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const completedThreadIds = [...successfulStops]
|
|
156
|
+
.filter((threadId) => starts.has(threadId))
|
|
157
|
+
.sort();
|
|
158
|
+
const failedThreadIds = [...failedStops]
|
|
159
|
+
.filter((threadId) => starts.has(threadId))
|
|
160
|
+
.sort();
|
|
161
|
+
const startedThreadIds = [...starts].sort();
|
|
162
|
+
const stoppedThreadIds = new Set([...completedThreadIds, ...failedThreadIds]);
|
|
163
|
+
const openThreadIds = startedThreadIds.filter((threadId) => !stoppedThreadIds.has(threadId));
|
|
164
|
+
const preparationOnly = input.preparationOnly === true || isPreparationStatus(input.workflowStatus);
|
|
165
|
+
const parentSummaryPresent = input.parentSummaryPresent
|
|
166
|
+
?? parentSummary.present;
|
|
167
|
+
const blockers = [];
|
|
168
|
+
if (preparationOnly)
|
|
169
|
+
blockers.push('subagent_workflow_preparation_only');
|
|
170
|
+
if (requestedSubagents < 1)
|
|
171
|
+
blockers.push('requested_subagents_missing');
|
|
172
|
+
if (missingThreadId)
|
|
173
|
+
blockers.push('subagent_event_thread_id_missing');
|
|
174
|
+
if (startedThreadIds.length < requestedSubagents) {
|
|
175
|
+
blockers.push(`requested_subagent_starts_incomplete:${startedThreadIds.length}/${requestedSubagents}`);
|
|
176
|
+
}
|
|
177
|
+
else if (startedThreadIds.length > requestedSubagents) {
|
|
178
|
+
blockers.push(`requested_subagent_starts_exceeded:${startedThreadIds.length}/${requestedSubagents}`);
|
|
179
|
+
}
|
|
180
|
+
if (completedThreadIds.length < requestedSubagents) {
|
|
181
|
+
blockers.push(`requested_subagent_completions_incomplete:${completedThreadIds.length}/${requestedSubagents}`);
|
|
182
|
+
}
|
|
183
|
+
else if (completedThreadIds.length > requestedSubagents) {
|
|
184
|
+
blockers.push(`requested_subagent_completions_exceeded:${completedThreadIds.length}/${requestedSubagents}`);
|
|
185
|
+
}
|
|
186
|
+
if (failedThreadIds.length > 0)
|
|
187
|
+
blockers.push(`subagent_threads_failed:${failedThreadIds.length}`);
|
|
188
|
+
if (openThreadIds.length > 0)
|
|
189
|
+
blockers.push(`subagent_threads_still_open:${openThreadIds.length}`);
|
|
190
|
+
if (unmatchedStops.size > 0)
|
|
191
|
+
blockers.push(`subagent_stops_without_start:${unmatchedStops.size}`);
|
|
192
|
+
if (ambiguousStops.size > 0)
|
|
193
|
+
blockers.push(`subagent_thread_outcomes_ambiguous:${ambiguousStops.size}`);
|
|
194
|
+
blockers.push(...runScope.blockers, ...runScope.parentBlockers);
|
|
195
|
+
blockers.push(...parentThreadIdentityBlockers);
|
|
196
|
+
if (!parentSummaryPresent)
|
|
197
|
+
blockers.push('parent_summary_missing');
|
|
198
|
+
else if (!parentSummary.trustworthy)
|
|
199
|
+
blockers.push(...parentSummary.blockers);
|
|
200
|
+
if (parentSummary.status === 'failed')
|
|
201
|
+
blockers.push('parent_summary_failed');
|
|
202
|
+
for (const blocker of input.additionalBlockers || []) {
|
|
203
|
+
const normalized = String(blocker || '').trim();
|
|
204
|
+
if (normalized)
|
|
205
|
+
blockers.push(normalized);
|
|
206
|
+
}
|
|
207
|
+
const uniqueBlockers = uniqueStrings(blockers);
|
|
208
|
+
const ok = uniqueBlockers.length === 0;
|
|
209
|
+
const status = preparationOnly
|
|
210
|
+
? 'preparation_only'
|
|
211
|
+
: ok
|
|
212
|
+
? 'completed'
|
|
213
|
+
: failedThreadIds.length > 0
|
|
214
|
+
? 'blocked'
|
|
215
|
+
: 'incomplete';
|
|
216
|
+
return {
|
|
217
|
+
schema: SUBAGENT_EVIDENCE_SCHEMA,
|
|
218
|
+
workflow: 'official_codex_subagent',
|
|
219
|
+
requested_subagents: requestedSubagents,
|
|
220
|
+
started_threads: startedThreadIds.length,
|
|
221
|
+
completed_threads: completedThreadIds.length,
|
|
222
|
+
failed_threads: failedThreadIds.length,
|
|
223
|
+
started_thread_ids: startedThreadIds,
|
|
224
|
+
completed_thread_ids: completedThreadIds,
|
|
225
|
+
failed_thread_ids: failedThreadIds,
|
|
226
|
+
open_thread_ids: openThreadIds,
|
|
227
|
+
unmatched_stop_thread_ids: [...unmatchedStops].sort(),
|
|
228
|
+
event_sources: [...eventSources].sort(eventSourceOrder),
|
|
229
|
+
parent_summary_present: parentSummaryPresent,
|
|
230
|
+
parent_summary_trustworthy: parentSummaryTrustworthy,
|
|
231
|
+
parent_summary_status: parentSummary.status,
|
|
232
|
+
ambiguous_stop_thread_ids: [...ambiguousStops].sort(),
|
|
233
|
+
run_id: runScope.runId,
|
|
234
|
+
run_epoch: runScope.runEpoch,
|
|
235
|
+
run_scope_source: runScope.source,
|
|
236
|
+
rejected_stale_events: scopedEvents.staleEvents.length,
|
|
237
|
+
rejected_stale_thread_ids: uniqueStrings(scopedEvents.staleEvents.map((event) => event.thread_id || '')).sort(),
|
|
238
|
+
unbound_run_events: scopedEvents.unboundEvents.length,
|
|
239
|
+
preparation_only: preparationOnly,
|
|
240
|
+
status,
|
|
241
|
+
ok,
|
|
242
|
+
blockers: uniqueBlockers
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
export async function recordSubagentEvent(artifactDir, payload, explicitEventName) {
|
|
246
|
+
const event = normalizeSubagentEvent(payload, explicitEventName);
|
|
247
|
+
if (!event)
|
|
248
|
+
return null;
|
|
249
|
+
await appendJsonlBounded(path.join(artifactDir, SUBAGENT_EVENT_LOG_FILENAME), event, 1024 * 1024);
|
|
250
|
+
return event;
|
|
251
|
+
}
|
|
252
|
+
export async function readSubagentEvents(artifactDir) {
|
|
253
|
+
const text = await fsp.readFile(path.join(artifactDir, SUBAGENT_EVENT_LOG_FILENAME), 'utf8').catch(() => '');
|
|
254
|
+
const events = [];
|
|
255
|
+
for (const line of text.split(/\r?\n/)) {
|
|
256
|
+
if (!line.trim())
|
|
257
|
+
continue;
|
|
258
|
+
let parsed;
|
|
259
|
+
try {
|
|
260
|
+
parsed = JSON.parse(line);
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
const event = normalizeSubagentEvent(parsed);
|
|
266
|
+
if (event)
|
|
267
|
+
events.push(event);
|
|
268
|
+
}
|
|
269
|
+
return events;
|
|
270
|
+
}
|
|
271
|
+
export async function writeSubagentEvidence(artifactDir, input) {
|
|
272
|
+
const events = input.events ?? await readSubagentEvents(artifactDir);
|
|
273
|
+
const evidence = buildSubagentEvidence({ ...input, events });
|
|
274
|
+
await writeJsonAtomic(path.join(artifactDir, SUBAGENT_EVIDENCE_FILENAME), evidence);
|
|
275
|
+
return evidence;
|
|
276
|
+
}
|
|
277
|
+
export async function persistOrReuseTrustworthySubagentParentSummary(artifactDir, value, opts = {}) {
|
|
278
|
+
const incoming = normalizeSubagentParentSummary(value);
|
|
279
|
+
const file = path.join(artifactDir, SUBAGENT_PARENT_SUMMARY_FILENAME);
|
|
280
|
+
const workflowFailed = isFailureWorkflowStatus(opts.workflowStatus);
|
|
281
|
+
const activeRunId = firstText(opts.runId);
|
|
282
|
+
const incomingMatchesActiveRun = !activeRunId || !incoming.run_id || incoming.run_id === activeRunId;
|
|
283
|
+
if (incoming.trustworthy && incoming.status === 'failed' && incoming.raw && incomingMatchesActiveRun) {
|
|
284
|
+
await writeJsonAtomic(file, incoming.raw);
|
|
285
|
+
return incoming.raw;
|
|
286
|
+
}
|
|
287
|
+
if (workflowFailed || incoming.status === 'failed' || parentResultExplicitlyFailed(value)) {
|
|
288
|
+
await fsp.rm(file, { force: true }).catch(() => undefined);
|
|
289
|
+
if (workflowFailed && incoming.trustworthy && incoming.status === 'completed')
|
|
290
|
+
return null;
|
|
291
|
+
return value;
|
|
292
|
+
}
|
|
293
|
+
if (incoming.trustworthy && incoming.raw) {
|
|
294
|
+
if (!incomingMatchesActiveRun)
|
|
295
|
+
return reuseMatchingPersistedParentSummary(file, activeRunId, value);
|
|
296
|
+
await writeJsonAtomic(file, incoming.raw);
|
|
297
|
+
return incoming.raw;
|
|
298
|
+
}
|
|
299
|
+
return reuseMatchingPersistedParentSummary(file, activeRunId, value);
|
|
300
|
+
}
|
|
301
|
+
export function bindTrustworthySubagentParentSummaryToRun(value, runId) {
|
|
302
|
+
const normalizedRunId = firstText(runId);
|
|
303
|
+
if (!normalizedRunId)
|
|
304
|
+
return value;
|
|
305
|
+
const summary = normalizeSubagentParentSummary(value);
|
|
306
|
+
if (!summary.trustworthy || !summary.raw)
|
|
307
|
+
return value;
|
|
308
|
+
if (summary.run_id && summary.run_id !== normalizedRunId)
|
|
309
|
+
return null;
|
|
310
|
+
return summary.run_id
|
|
311
|
+
? summary.raw
|
|
312
|
+
: { ...summary.raw, run_id: normalizedRunId };
|
|
313
|
+
}
|
|
314
|
+
async function reuseMatchingPersistedParentSummary(file, activeRunId, fallback) {
|
|
315
|
+
const persisted = await fsp.readFile(file, 'utf8')
|
|
316
|
+
.then((text) => JSON.parse(text))
|
|
317
|
+
.catch(() => null);
|
|
318
|
+
const previous = normalizeSubagentParentSummary(persisted);
|
|
319
|
+
if (!previous.trustworthy || !previous.raw)
|
|
320
|
+
return fallback;
|
|
321
|
+
if (activeRunId && previous.run_id !== activeRunId)
|
|
322
|
+
return fallback;
|
|
323
|
+
return previous.raw;
|
|
324
|
+
}
|
|
325
|
+
export const normalizeSubagentEvidence = buildSubagentEvidence;
|
|
326
|
+
function normalizeEventName(value) {
|
|
327
|
+
const normalized = String(value || '').trim().toLowerCase().replace(/[^a-z]+/g, '');
|
|
328
|
+
if (normalized === 'subagentstart')
|
|
329
|
+
return 'SubagentStart';
|
|
330
|
+
if (normalized === 'subagentstop')
|
|
331
|
+
return 'SubagentStop';
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
function normalizePersistedOutcome(value, eventName) {
|
|
335
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
336
|
+
if (eventName === 'SubagentStart')
|
|
337
|
+
return normalized === 'started' ? 'started' : null;
|
|
338
|
+
if (normalized === 'stopped' || normalized === 'failed' || normalized === 'ambiguous')
|
|
339
|
+
return normalized;
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
function stopFailed(row) {
|
|
343
|
+
const status = firstText(row.status, row.outcome, row.result, row.state).toLowerCase();
|
|
344
|
+
const resultText = firstText(row.last_assistant_message, row.lastAssistantMessage, row.summary, row.message, row.result_text, row.resultText);
|
|
345
|
+
return row.ok === false
|
|
346
|
+
|| row.success === false
|
|
347
|
+
|| row.failed === true
|
|
348
|
+
|| Boolean(row.error)
|
|
349
|
+
|| /^(failed|failure|error|blocked|cancelled|canceled|interrupted|timed[_ -]?out)$/.test(status)
|
|
350
|
+
|| containsUnambiguousFailureText(resultText);
|
|
351
|
+
}
|
|
352
|
+
function stopAmbiguous(row) {
|
|
353
|
+
const resultText = firstText(row.last_assistant_message, row.lastAssistantMessage, row.summary, row.message, row.result_text, row.resultText);
|
|
354
|
+
return containsAmbiguousOutcomeText(resultText);
|
|
355
|
+
}
|
|
356
|
+
export function normalizeSubagentParentSummary(value) {
|
|
357
|
+
const present = hasMeaningfulSummary(value);
|
|
358
|
+
const parsed = parseStructuredParentSummary(value);
|
|
359
|
+
const threadOutcomes = new Map();
|
|
360
|
+
const blockers = [];
|
|
361
|
+
if (!parsed) {
|
|
362
|
+
if (present)
|
|
363
|
+
blockers.push('parent_summary_untrusted');
|
|
364
|
+
return {
|
|
365
|
+
present,
|
|
366
|
+
trustworthy: false,
|
|
367
|
+
status: present ? 'ambiguous' : null,
|
|
368
|
+
summary: null,
|
|
369
|
+
run_id: null,
|
|
370
|
+
run_epoch: null,
|
|
371
|
+
thread_outcomes: threadOutcomes,
|
|
372
|
+
blockers,
|
|
373
|
+
raw: null
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
const summary = String(parsed.summary || '').trim();
|
|
377
|
+
if (typeof parsed.summary !== 'string' || !summary)
|
|
378
|
+
blockers.push('parent_summary_text_missing');
|
|
379
|
+
const topLevelKeys = new Set(['schema', 'status', 'summary', 'thread_outcomes', 'changed_files', 'verification', 'blockers', 'run_id', 'run_epoch']);
|
|
380
|
+
for (const key of Object.keys(parsed)) {
|
|
381
|
+
if (!topLevelKeys.has(key))
|
|
382
|
+
blockers.push(`parent_summary_unknown_field:${key}`);
|
|
383
|
+
}
|
|
384
|
+
if (parsed.changed_files !== undefined && (!Array.isArray(parsed.changed_files) || parsed.changed_files.some((item) => typeof item !== 'string'))) {
|
|
385
|
+
blockers.push('parent_summary_changed_files_invalid');
|
|
386
|
+
}
|
|
387
|
+
if (parsed.verification !== undefined && !Array.isArray(parsed.verification))
|
|
388
|
+
blockers.push('parent_summary_verification_invalid');
|
|
389
|
+
if (parsed.blockers !== undefined && (!Array.isArray(parsed.blockers) || parsed.blockers.some((item) => typeof item !== 'string'))) {
|
|
390
|
+
blockers.push('parent_summary_blockers_invalid');
|
|
391
|
+
}
|
|
392
|
+
if (!Array.isArray(parsed.thread_outcomes) || parsed.thread_outcomes.length === 0) {
|
|
393
|
+
blockers.push('parent_thread_outcomes_missing');
|
|
394
|
+
}
|
|
395
|
+
for (const row of Array.isArray(parsed.thread_outcomes) ? parsed.thread_outcomes : []) {
|
|
396
|
+
if (!isRecord(row)) {
|
|
397
|
+
blockers.push('parent_thread_outcome_invalid');
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
const rowKeys = new Set(['thread_id', 'status', 'summary']);
|
|
401
|
+
for (const key of Object.keys(row)) {
|
|
402
|
+
if (!rowKeys.has(key))
|
|
403
|
+
blockers.push(`parent_thread_outcome_unknown_field:${key}`);
|
|
404
|
+
}
|
|
405
|
+
const threadId = firstText(row?.thread_id);
|
|
406
|
+
const status = strictTerminalOutcome(row?.status);
|
|
407
|
+
const rowSummary = typeof row?.summary === 'string' ? row.summary.trim() : '';
|
|
408
|
+
if (!threadId) {
|
|
409
|
+
blockers.push('parent_thread_outcome_thread_id_missing');
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
if (threadOutcomes.has(threadId)) {
|
|
413
|
+
blockers.push(`parent_thread_outcome_duplicate:${threadId}`);
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
threadOutcomes.set(threadId, status);
|
|
417
|
+
if (status === 'ambiguous')
|
|
418
|
+
blockers.push(`parent_thread_outcome_ambiguous:${threadId}`);
|
|
419
|
+
if (!rowSummary)
|
|
420
|
+
blockers.push(`parent_thread_outcome_summary_missing:${threadId}`);
|
|
421
|
+
if (status === 'completed' && containsFailedOrAmbiguousOutcomeText(rowSummary)) {
|
|
422
|
+
blockers.push(`parent_thread_outcome_text_contradiction:${threadId}`);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
const status = strictTerminalOutcome(parsed.status);
|
|
426
|
+
if (status === 'ambiguous')
|
|
427
|
+
blockers.push('parent_summary_status_ambiguous');
|
|
428
|
+
if (status === 'completed' && containsFailedOrAmbiguousOutcomeText(summary))
|
|
429
|
+
blockers.push('parent_summary_text_contradiction');
|
|
430
|
+
if (status === 'completed' && Array.isArray(parsed.blockers) && parsed.blockers.length > 0) {
|
|
431
|
+
blockers.push('parent_summary_completed_with_blockers');
|
|
432
|
+
}
|
|
433
|
+
return {
|
|
434
|
+
present: true,
|
|
435
|
+
trustworthy: blockers.length === 0,
|
|
436
|
+
status,
|
|
437
|
+
summary: summary || null,
|
|
438
|
+
run_id: firstText(parsed.run_id) || null,
|
|
439
|
+
run_epoch: firstText(parsed.run_epoch) || null,
|
|
440
|
+
thread_outcomes: threadOutcomes,
|
|
441
|
+
blockers: uniqueStrings(blockers.length ? blockers : []),
|
|
442
|
+
raw: parsed
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
function parseStructuredParentSummary(value) {
|
|
446
|
+
if (isRecord(value))
|
|
447
|
+
return validStructuredParentSummary(value);
|
|
448
|
+
if (typeof value !== 'string' || !value.trim())
|
|
449
|
+
return null;
|
|
450
|
+
const trimmed = value.trim();
|
|
451
|
+
const fenced = /^```(?:json)?\s*([\s\S]*?)\s*```$/i.exec(trimmed)?.[1]?.trim();
|
|
452
|
+
const candidates = [trimmed, ...(fenced ? [fenced] : [])];
|
|
453
|
+
for (const candidate of candidates) {
|
|
454
|
+
try {
|
|
455
|
+
const parsed = JSON.parse(candidate);
|
|
456
|
+
const valid = validStructuredParentSummary(parsed);
|
|
457
|
+
if (valid)
|
|
458
|
+
return valid;
|
|
459
|
+
}
|
|
460
|
+
catch { }
|
|
461
|
+
}
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
function validStructuredParentSummary(value) {
|
|
465
|
+
if (!isRecord(value) || value.schema !== SUBAGENT_PARENT_SUMMARY_SCHEMA)
|
|
466
|
+
return null;
|
|
467
|
+
if (!Array.isArray(value.thread_outcomes))
|
|
468
|
+
return null;
|
|
469
|
+
return value;
|
|
470
|
+
}
|
|
471
|
+
function strictTerminalOutcome(value) {
|
|
472
|
+
const status = String(value || '').trim().toLowerCase();
|
|
473
|
+
if (status === 'completed')
|
|
474
|
+
return 'completed';
|
|
475
|
+
if (status === 'blocked' || status === 'failed')
|
|
476
|
+
return 'failed';
|
|
477
|
+
return 'ambiguous';
|
|
478
|
+
}
|
|
479
|
+
function containsUnambiguousFailureText(value) {
|
|
480
|
+
const source = String(value || '').trim();
|
|
481
|
+
if (!source)
|
|
482
|
+
return false;
|
|
483
|
+
const scrubbed = source
|
|
484
|
+
.replace(/\b(?:no|without)\s+(?:errors?|failures?|blockers?|issues?)\b/gi, ' ')
|
|
485
|
+
.replace(/\bno\s+(?:\d+\s+)?(?:tests?|suites?|checks?|cases?)\s+(?:failed|failing|errored)\b/gi, ' ')
|
|
486
|
+
.replace(/\bnot\s+blocked\b/gi, ' ')
|
|
487
|
+
.replace(/\b(?:did\s+not|didn't)\s+fail\b/gi, ' ')
|
|
488
|
+
.replace(/\b(?:type\s*check|typecheck|build|compilation|compile|compiler|npm\s+test|tests?|test\s+suites?)\s+(?:did\s+not|didn't)\s+fail\b/gi, ' ')
|
|
489
|
+
.replace(/\b(?:failed|failure|error|blocked)[- ]paths?\b/gi, ' ')
|
|
490
|
+
.replace(/\b(?:could\s+not|unable\s+to)\s+(?:reproduce|find|detect|observe|identify)\b[^.!?\n]*/gi, ' ')
|
|
491
|
+
.replace(/(?:실패한|차단된|오류(?:가|는)?\s*발생한?)\s*(?:테스트|검사|항목|문제)(?:가|이|는|은)?\s*(?:없음|없다|없습니다)/g, ' ')
|
|
492
|
+
.replace(/(?:실패|오류|에러|차단|문제)(?:가|이|는|은)?\s*(?:없음|없다|없습니다|없이)/g, ' ')
|
|
493
|
+
.replace(/차단되지\s*않(?:음|았다|았습니다)/g, ' ');
|
|
494
|
+
return /^(?:failed|failure|error|blocked|cancelled|canceled|interrupted|timed\s*out|incomplete)\b/i.test(scrubbed)
|
|
495
|
+
|| /\b\d+\s+(?:tests?|suites?|checks?|cases?)\s+(?:failed|failing|errored)\b/i.test(scrubbed)
|
|
496
|
+
|| /\b(?:type\s*check|typecheck|build|compilation|compile|compiler|npm\s+test|npm\s+run\s+(?:test|build|typecheck)|tests?|test\s+suites?|lint|verification)\b[^.!?\n]{0,40}\b(?:failed|failing|failure|errored|errors?)\b/i.test(scrubbed)
|
|
497
|
+
|| /\b(?:compilation|compiler|typescript|tsc)\s+error(?:\s+TS\d+)?\b/i.test(scrubbed)
|
|
498
|
+
|| /\berror\s+TS\d+\b/i.test(scrubbed)
|
|
499
|
+
|| /\b(?:slice|thread|task|work|review|integration|execution|run|job|agent|subagent)\b[^.!?\n]{0,32}\b(?:failed|blocked|cancelled|canceled|interrupted|timed\s*out|not\s+completed|incomplete)\b/i.test(scrubbed)
|
|
500
|
+
|| /\b(?:could\s+not|unable\s+to|failed\s+to)\s+(?:complete|finish|deliver|execute|run|continue|return)\b/i.test(scrubbed)
|
|
501
|
+
|| /(?:작업|슬라이스|스레드|검수|통합|실행|에이전트|서브\s*에이전트)[^.!?\n]{0,20}(?:실패|차단|중단|미완료)/i.test(scrubbed)
|
|
502
|
+
|| /(?:완료|수행|실행|진행|통합)하지\s*못|완료되지\s*않|미완료/i.test(scrubbed);
|
|
503
|
+
}
|
|
504
|
+
function containsAmbiguousOutcomeText(value) {
|
|
505
|
+
const source = String(value || '').trim();
|
|
506
|
+
if (!source)
|
|
507
|
+
return false;
|
|
508
|
+
const completedReadOnlyReview = (/\bread[- ]only\b[^.!?\n]{0,180}\b(?:review|inspection|audit)\b[^.!?\n]{0,180}\b(?:covered|completed|finished)\b/i.test(source)
|
|
509
|
+
|| /읽기\s*전용[^.!?\n]{0,180}(?:검수|검토|감사)[^.!?\n]{0,180}(?:완료|점검|확인)/i.test(source)) && (/\bno files? (?:were )?(?:changed|modified)\b/i.test(source)
|
|
510
|
+
|| /파일[^.!?\n]{0,40}(?:변경|수정)(?:하지\s*않|없)/i.test(source));
|
|
511
|
+
const ambiguitySource = completedReadOnlyReview
|
|
512
|
+
? source
|
|
513
|
+
.replace(/\bno tests? (?:were )?(?:run|executed)\b/gi, ' ')
|
|
514
|
+
.replace(/\btests? (?:were )?not (?:run|executed)\b/gi, ' ')
|
|
515
|
+
.replace(/테스트[^.!?\n]{0,20}(?:미실행|실행하지\s*않)/gi, ' ')
|
|
516
|
+
: source;
|
|
517
|
+
const scrubbed = ambiguitySource
|
|
518
|
+
.replace(/\bno\s+(?:remaining\s+)?(?:unknowns?|ambiguities|pending\s+(?:checks?|work)|unverified\s+(?:checks?|work|gaps?))\b/gi, ' ')
|
|
519
|
+
.replace(/\bnot\s+(?:pending|unknown|unclear|ambiguous|inconclusive)\b/gi, ' ');
|
|
520
|
+
return /\b(?:tests?|test\s+suites?|checks?|type\s*check|typecheck|build|lint|verification)\b[^.!?\n]{0,32}\b(?:not\s+(?:run|executed|verified|completed)|pending|unknown|unclear|ambiguous|inconclusive)\b/i.test(scrubbed)
|
|
521
|
+
|| /\b(?:could\s+not|unable\s+to|failed\s+to)\s+(?:verify|confirm|determine)\b/i.test(scrubbed)
|
|
522
|
+
|| /\b(?:result|status|outcome)\b[^.!?\n]{0,20}\b(?:unknown|unclear|ambiguous|pending|inconclusive)\b/i.test(scrubbed)
|
|
523
|
+
|| /\b(?:partially|partly)\s+(?:completed|verified|tested)\b/i.test(scrubbed)
|
|
524
|
+
|| /(?:테스트|검사|타입\s*체크|빌드|검증)[^.!?\n]{0,16}(?:미실행|미검증|보류|불명확|알\s*수\s*없|확인하지\s*못)/i.test(scrubbed);
|
|
525
|
+
}
|
|
526
|
+
function containsFailedOrAmbiguousOutcomeText(value) {
|
|
527
|
+
return containsUnambiguousFailureText(value) || containsAmbiguousOutcomeText(value);
|
|
528
|
+
}
|
|
529
|
+
function parentResultExplicitlyFailed(value) {
|
|
530
|
+
if (typeof value === 'string')
|
|
531
|
+
return containsUnambiguousFailureText(value);
|
|
532
|
+
if (!isRecord(value))
|
|
533
|
+
return false;
|
|
534
|
+
const status = firstText(value.status, value.outcome, value.result, value.state).toLowerCase();
|
|
535
|
+
const resultText = firstText(value.summary, value.message, value.last_assistant_message, value.lastAssistantMessage, value.result_text, value.resultText);
|
|
536
|
+
return value.ok === false
|
|
537
|
+
|| value.success === false
|
|
538
|
+
|| value.failed === true
|
|
539
|
+
|| Boolean(value.error)
|
|
540
|
+
|| (Array.isArray(value.blockers) && value.blockers.length > 0)
|
|
541
|
+
|| /^(failed|failure|error|blocked|cancelled|canceled|interrupted|timed[_ -]?out|incomplete)$/.test(status)
|
|
542
|
+
|| containsUnambiguousFailureText(resultText);
|
|
543
|
+
}
|
|
544
|
+
function isFailureWorkflowStatus(value) {
|
|
545
|
+
return /^(parent_failed|failed|blocked|incomplete|cancelled|canceled|timed[_ -]?out)$/i.test(String(value || '').trim());
|
|
546
|
+
}
|
|
547
|
+
function resolveRunScope(input, events, parentSummary) {
|
|
548
|
+
const requestedRunId = firstText(input.runId);
|
|
549
|
+
const requestedRunEpoch = firstText(input.runEpoch);
|
|
550
|
+
const eventRunIds = uniqueStrings(events.map((event) => event.run_id || ''));
|
|
551
|
+
const eventTurnIds = uniqueStrings(events.map((event) => event.turn_id || ''));
|
|
552
|
+
const eventRunEpochs = uniqueStrings(events.map((event) => event.run_epoch || ''));
|
|
553
|
+
const latestEventRunId = latestText(events, (event) => event.run_id);
|
|
554
|
+
const latestEventTurnId = latestText(events, (event) => event.turn_id);
|
|
555
|
+
const latestEventRunEpoch = latestText(events, (event) => event.run_epoch);
|
|
556
|
+
const runId = requestedRunId || latestEventRunId || latestEventTurnId || parentSummary.run_id || null;
|
|
557
|
+
const runEpoch = requestedRunEpoch || latestEventRunEpoch || parentSummary.run_epoch || null;
|
|
558
|
+
const source = requestedRunId || requestedRunEpoch
|
|
559
|
+
? 'input'
|
|
560
|
+
: latestEventRunId
|
|
561
|
+
? 'event_run_id'
|
|
562
|
+
: latestEventTurnId
|
|
563
|
+
? 'event_turn_id'
|
|
564
|
+
: parentSummary.run_id || parentSummary.run_epoch
|
|
565
|
+
? 'parent_summary'
|
|
566
|
+
: latestEventRunEpoch
|
|
567
|
+
? 'event_run_epoch'
|
|
568
|
+
: null;
|
|
569
|
+
const blockers = [];
|
|
570
|
+
const parentBlockers = [];
|
|
571
|
+
const parentRunBindingRequired = Boolean(parentSummary.run_id)
|
|
572
|
+
|| (source !== 'event_turn_id' && Boolean(requestedRunId || eventRunIds.length > 0));
|
|
573
|
+
if (parentSummary.present && runId && parentRunBindingRequired) {
|
|
574
|
+
if (!parentSummary.run_id)
|
|
575
|
+
parentBlockers.push('parent_summary_run_id_missing');
|
|
576
|
+
else if (parentSummary.run_id !== runId)
|
|
577
|
+
parentBlockers.push('parent_summary_run_id_mismatch');
|
|
578
|
+
}
|
|
579
|
+
const parentEpochBindingRequired = Boolean(requestedRunEpoch || parentSummary.run_epoch || eventRunEpochs.length > 0);
|
|
580
|
+
if (parentSummary.present && runEpoch && parentEpochBindingRequired) {
|
|
581
|
+
if (!parentSummary.run_epoch)
|
|
582
|
+
parentBlockers.push('parent_summary_run_epoch_missing');
|
|
583
|
+
else if (parentSummary.run_epoch !== runEpoch)
|
|
584
|
+
parentBlockers.push('parent_summary_run_epoch_mismatch');
|
|
585
|
+
}
|
|
586
|
+
return {
|
|
587
|
+
runId,
|
|
588
|
+
runEpoch,
|
|
589
|
+
source,
|
|
590
|
+
blockers,
|
|
591
|
+
parentBlockers
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
function scopeSubagentEvents(events, scope) {
|
|
595
|
+
const accepted = [];
|
|
596
|
+
const staleEvents = [];
|
|
597
|
+
const unboundEvents = [];
|
|
598
|
+
for (const event of events) {
|
|
599
|
+
const eventRunId = scope.source === 'event_turn_id'
|
|
600
|
+
? event.turn_id
|
|
601
|
+
: scope.source === 'input' || scope.source === 'parent_summary'
|
|
602
|
+
? event.run_id || event.turn_id
|
|
603
|
+
: event.run_id;
|
|
604
|
+
if ((scope.runId && !eventRunId) || (scope.runEpoch && !event.run_epoch)) {
|
|
605
|
+
unboundEvents.push(event);
|
|
606
|
+
continue;
|
|
607
|
+
}
|
|
608
|
+
if ((scope.runId && eventRunId !== scope.runId) || (scope.runEpoch && event.run_epoch !== scope.runEpoch)) {
|
|
609
|
+
staleEvents.push(event);
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
accepted.push(event);
|
|
613
|
+
}
|
|
614
|
+
if (unboundEvents.length > 0)
|
|
615
|
+
scope.blockers.push(`subagent_events_run_scope_missing:${unboundEvents.length}`);
|
|
616
|
+
return { events: accepted, staleEvents, unboundEvents };
|
|
617
|
+
}
|
|
618
|
+
function latestText(values, pick) {
|
|
619
|
+
for (let index = values.length - 1; index >= 0; index -= 1) {
|
|
620
|
+
const value = pick(values[index]);
|
|
621
|
+
if (value)
|
|
622
|
+
return value;
|
|
623
|
+
}
|
|
624
|
+
return '';
|
|
625
|
+
}
|
|
626
|
+
function uniqueStrings(values) {
|
|
627
|
+
return [...new Set(values.filter(Boolean))];
|
|
628
|
+
}
|
|
629
|
+
function normalizeRequested(value) {
|
|
630
|
+
const parsed = Number(value);
|
|
631
|
+
if (!Number.isFinite(parsed))
|
|
632
|
+
return 0;
|
|
633
|
+
return Math.max(0, Math.floor(parsed));
|
|
634
|
+
}
|
|
635
|
+
function isPreparationStatus(value) {
|
|
636
|
+
return /^(delegation_context_ready|context_ready|prepared|preparation_only)$/.test(String(value || '').trim().toLowerCase());
|
|
637
|
+
}
|
|
638
|
+
function hasMeaningfulSummary(value) {
|
|
639
|
+
if (typeof value === 'string')
|
|
640
|
+
return value.trim().length > 0;
|
|
641
|
+
if (Array.isArray(value))
|
|
642
|
+
return value.length > 0;
|
|
643
|
+
return isRecord(value) && Object.keys(value).length > 0;
|
|
644
|
+
}
|
|
645
|
+
function eventSourceOrder(a, b) {
|
|
646
|
+
return (a === 'SubagentStart' ? 0 : 1) - (b === 'SubagentStart' ? 0 : 1);
|
|
647
|
+
}
|
|
648
|
+
function isRecord(value) {
|
|
649
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
650
|
+
}
|
|
651
|
+
function recordId(value) {
|
|
652
|
+
return isRecord(value) ? value.id : undefined;
|
|
653
|
+
}
|
|
654
|
+
function firstText(...values) {
|
|
655
|
+
for (const value of values) {
|
|
656
|
+
if (typeof value === 'string' && value.trim())
|
|
657
|
+
return value.trim();
|
|
658
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
659
|
+
return String(value);
|
|
660
|
+
}
|
|
661
|
+
return '';
|
|
662
|
+
}
|
|
663
|
+
//# sourceMappingURL=subagent-evidence.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const SUBAGENT_TERMS = Object.freeze({
|
|
2
|
+
workflow: 'subagent workflow',
|
|
3
|
+
agent: 'subagent',
|
|
4
|
+
thread: 'agent thread',
|
|
5
|
+
parent: 'parent agent',
|
|
6
|
+
customAgent: 'custom agent'
|
|
7
|
+
});
|
|
8
|
+
export const DEPRECATED_AGENT_TERMS = Object.freeze([
|
|
9
|
+
'shadow clone',
|
|
10
|
+
'clone roster',
|
|
11
|
+
'native agent swarm',
|
|
12
|
+
'native CLI session swarm',
|
|
13
|
+
'active pool',
|
|
14
|
+
'worker swarm'
|
|
15
|
+
]);
|
|
16
|
+
//# sourceMappingURL=terminology.js.map
|