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,188 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { readJson, sha256 } from '../fsx.js';
|
|
3
|
+
import { runCodexTask } from '../codex-control/codex-task-runner.js';
|
|
4
|
+
import { runSuperSearch } from '../super-search/index.js';
|
|
5
|
+
import { TERRA_SUBAGENT_EFFORT, TERRA_SUBAGENT_MODEL } from '../subagents/model-policy.js';
|
|
6
|
+
import {} from './research-source-shards.js';
|
|
7
|
+
export const RESEARCH_SOURCE_ACQUISITION_MODEL_POLICY = Object.freeze({
|
|
8
|
+
model: TERRA_SUBAGENT_MODEL,
|
|
9
|
+
model_reasoning_effort: TERRA_SUBAGENT_EFFORT
|
|
10
|
+
});
|
|
11
|
+
export async function runResearchSuperSearchShard(input) {
|
|
12
|
+
const missionId = String(input.plan?.mission_id || '');
|
|
13
|
+
const acquisitionDir = path.join(input.dir, 'research', `cycle-${input.cycle}`, 'source-acquisition', input.layer.id);
|
|
14
|
+
const sourceSearch = input.sourceSearch || createCodexSourceSearch(input);
|
|
15
|
+
const result = await runSuperSearch({
|
|
16
|
+
root: input.root,
|
|
17
|
+
missionDir: acquisitionDir,
|
|
18
|
+
missionId,
|
|
19
|
+
route: '$Research',
|
|
20
|
+
query: buildResearchLayerQuery(input.plan, input.layer),
|
|
21
|
+
mode: 'deep',
|
|
22
|
+
codexWebSearch: sourceSearch,
|
|
23
|
+
maxQueryVariants: 2,
|
|
24
|
+
maxHydratedSources: 4,
|
|
25
|
+
hardTimeoutMs: input.timeoutMs,
|
|
26
|
+
...(input.deadlineMs === undefined ? {} : { deadlineEpochMs: input.deadlineMs }),
|
|
27
|
+
env: { ...process.env, SKS_CODEX_WEB_SEARCH_AVAILABLE: '1' }
|
|
28
|
+
});
|
|
29
|
+
const sources = result.sources.map((source) => researchSourceRow(source, input.layer));
|
|
30
|
+
const verifiedEvidenceCandidates = sources.filter((source) => source.acquisition_verdict === 'verified_content').length;
|
|
31
|
+
const blockers = [
|
|
32
|
+
...result.proof.blockers.map((blocker) => `super_search:${blocker}`),
|
|
33
|
+
...(sources.length ? [] : ['super_search:source_rows_missing']),
|
|
34
|
+
...(input.layer.id === 'counterevidence_factcheck' && verifiedEvidenceCandidates === 0
|
|
35
|
+
? ['super_search:verified_counterevidence_candidate_missing']
|
|
36
|
+
: [])
|
|
37
|
+
];
|
|
38
|
+
return {
|
|
39
|
+
schema: 'sks.research-source-shard-output.v1',
|
|
40
|
+
mission_id: missionId,
|
|
41
|
+
cycle: input.cycle,
|
|
42
|
+
layer_id: input.layer.id,
|
|
43
|
+
queries: result.query_variants.map((query) => ({
|
|
44
|
+
query,
|
|
45
|
+
rationale: `Super Search ${result.mode} acquisition for ${input.layer.label}.`
|
|
46
|
+
})),
|
|
47
|
+
sources,
|
|
48
|
+
blockers: [...new Set(blockers)],
|
|
49
|
+
super_search: {
|
|
50
|
+
schema: 'sks.research-super-search-link.v1',
|
|
51
|
+
result_artifact: path.relative(input.dir, path.join(result.artifact_dir, 'super-search-result.json')),
|
|
52
|
+
proof_artifact: path.relative(input.dir, path.join(result.artifact_dir, 'super-search-proof.json')),
|
|
53
|
+
source_ledger_artifact: path.relative(input.dir, path.join(result.artifact_dir, 'source-ledger.json')),
|
|
54
|
+
claim_ledger_artifact: path.relative(input.dir, path.join(result.artifact_dir, 'claim-ledger.json')),
|
|
55
|
+
proof_ok: result.proof.ok,
|
|
56
|
+
verified_sources: result.proof.verified_source_count,
|
|
57
|
+
provider_independent: result.proof.provider_independent,
|
|
58
|
+
verified_provider_families: result.proof.verified_provider_families,
|
|
59
|
+
verified_independence_clusters: result.proof.verified_independence_clusters,
|
|
60
|
+
query_execution: result.query_execution
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export function buildResearchLayerQuery(plan, layer) {
|
|
65
|
+
const topic = String(plan?.prompt || 'research mission').trim();
|
|
66
|
+
const templates = layer.query_templates.slice(0, 3).map((query) => query.replace(/<topic>/g, topic));
|
|
67
|
+
return [
|
|
68
|
+
topic,
|
|
69
|
+
`Evidence layer: ${layer.label}.`,
|
|
70
|
+
layer.purpose,
|
|
71
|
+
`Prioritize primary or authoritative sources; preserve contrary evidence; never invent URLs. Suggested searches: ${templates.join(' | ')}`
|
|
72
|
+
].join(' ');
|
|
73
|
+
}
|
|
74
|
+
function createCodexSourceSearch(input) {
|
|
75
|
+
return async (query) => {
|
|
76
|
+
const queryId = sha256(query).slice(0, 12);
|
|
77
|
+
const result = await runCodexTask({
|
|
78
|
+
route: '$Research',
|
|
79
|
+
tier: 'worker',
|
|
80
|
+
missionId: String(input.plan?.mission_id || 'research-source-acquisition'),
|
|
81
|
+
workItemId: `super_search_${input.layer.id}_${queryId}`,
|
|
82
|
+
cwd: input.root,
|
|
83
|
+
prompt: buildSourceSearchPrompt(input.plan, input.layer, query),
|
|
84
|
+
outputSchema: researchSourceSearchOutputSchema,
|
|
85
|
+
outputSchemaId: 'sks.research-source-search-output.v1',
|
|
86
|
+
sandboxPolicy: 'read-only',
|
|
87
|
+
requestedScopeContract: {
|
|
88
|
+
id: `research-super-search-${input.layer.id}`,
|
|
89
|
+
route: '$Research',
|
|
90
|
+
read_only: true,
|
|
91
|
+
allowed_paths: [`.sneakoscope/missions/${input.plan?.mission_id || ''}/`],
|
|
92
|
+
write_paths: [],
|
|
93
|
+
allowed_write_prefixes: [`.sneakoscope/missions/${input.plan?.mission_id || ''}/`],
|
|
94
|
+
source_mutation_allowed: false
|
|
95
|
+
},
|
|
96
|
+
backendPreference: ['codex-sdk', 'python-codex-sdk'],
|
|
97
|
+
allowLocalLlm: false,
|
|
98
|
+
localLlmPolicy: { mode: 'disabled', requiresGptFinal: true },
|
|
99
|
+
mutationLedgerRoot: path.join(input.dir, 'research', `cycle-${input.cycle}`, 'super-search-codex-control', input.layer.id, queryId),
|
|
100
|
+
reliabilityPolicy: {
|
|
101
|
+
timeoutClass: 'standard',
|
|
102
|
+
idleTimeoutMs: input.timeoutMs,
|
|
103
|
+
hardTimeoutMs: input.timeoutMs,
|
|
104
|
+
...(input.deadlineMs === undefined ? {} : { deadlineEpochMs: input.deadlineMs })
|
|
105
|
+
},
|
|
106
|
+
model: RESEARCH_SOURCE_ACQUISITION_MODEL_POLICY.model,
|
|
107
|
+
reasoningEffort: RESEARCH_SOURCE_ACQUISITION_MODEL_POLICY.model_reasoning_effort,
|
|
108
|
+
modelReasoningEffort: RESEARCH_SOURCE_ACQUISITION_MODEL_POLICY.model_reasoning_effort,
|
|
109
|
+
serviceTier: 'fast'
|
|
110
|
+
});
|
|
111
|
+
const worker = await readJson(result.workerResultPath, null);
|
|
112
|
+
if (!result.ok || !worker)
|
|
113
|
+
return { results: [], blockers: result.blockers || ['research_source_search_failed'] };
|
|
114
|
+
return {
|
|
115
|
+
results: Array.isArray(worker.results) ? worker.results : [],
|
|
116
|
+
blockers: Array.isArray(worker.blockers) ? worker.blockers : []
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function buildSourceSearchPrompt(plan, layer, query) {
|
|
121
|
+
return [
|
|
122
|
+
'Use current web/source search tools for one read-only Super Search acquisition query.',
|
|
123
|
+
`Mission: ${plan?.mission_id || 'unknown'}`,
|
|
124
|
+
`Research topic: ${plan?.prompt || ''}`,
|
|
125
|
+
`Layer: ${layer.id} (${layer.label})`,
|
|
126
|
+
`Query: ${query}`,
|
|
127
|
+
'',
|
|
128
|
+
'Return only JSON matching sks.research-source-search-output.v1.',
|
|
129
|
+
'Every result must contain an exact reachable http(s) URL, title, and source-grounded snippet.',
|
|
130
|
+
'Do not invent citations, URLs, dates, authors, or source text. If search is unavailable, return an empty results array and an explicit blocker.'
|
|
131
|
+
].join('\n');
|
|
132
|
+
}
|
|
133
|
+
export function researchSourceRow(source, layer) {
|
|
134
|
+
const verified = source.acquisition_verdict === 'verified_content';
|
|
135
|
+
const evidenceText = [source.title, source.snippet].filter(Boolean).join(' ');
|
|
136
|
+
const sourceClaimId = `source-claim-${sha256([
|
|
137
|
+
source.canonical_url || source.original_url || source.source_id,
|
|
138
|
+
source.content_sha256 || '',
|
|
139
|
+
evidenceText.trim().toLowerCase()
|
|
140
|
+
].join('\0')).slice(0, 16)}`;
|
|
141
|
+
return {
|
|
142
|
+
id: source.source_id,
|
|
143
|
+
layer: layer.id,
|
|
144
|
+
kind: source.source_type,
|
|
145
|
+
title: source.title,
|
|
146
|
+
locator: source.canonical_url || source.original_url || source.content_artifact || source.source_id,
|
|
147
|
+
publisher_or_author: source.author || source.domain || source.provider_id,
|
|
148
|
+
...(source.published_at ? { published_at: source.published_at } : {}),
|
|
149
|
+
accessed_at: source.retrieved_at,
|
|
150
|
+
reliability: source.authority_tier === 'A0' || source.authority_tier === 'A1' ? 'high' : source.authority_tier === 'B' ? 'medium-high' : 'medium',
|
|
151
|
+
credibility: verified ? `verified_content:${source.trust_score.toFixed(2)}` : `${source.acquisition_verdict}:${source.trust_score.toFixed(2)}`,
|
|
152
|
+
stance: 'context',
|
|
153
|
+
claim_ids: [sourceClaimId],
|
|
154
|
+
content_artifact: source.content_artifact,
|
|
155
|
+
content_sha256: source.content_sha256,
|
|
156
|
+
content_length: source.content_length,
|
|
157
|
+
acquisition_verdict: source.acquisition_verdict,
|
|
158
|
+
domain: source.domain,
|
|
159
|
+
authority_tier: source.authority_tier,
|
|
160
|
+
primary_source: source.primary_source,
|
|
161
|
+
independence_cluster_id: source.independence_cluster_id,
|
|
162
|
+
notes: [
|
|
163
|
+
source.snippet.trim().slice(0, 900),
|
|
164
|
+
`Super Search provider=${source.provider_id}; authority=${source.authority_tier}; acquisition=${source.acquisition_verdict}; source_claim_id=${sourceClaimId}.`
|
|
165
|
+
].filter(Boolean).join(' ')
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
export const researchSourceSearchOutputSchema = {
|
|
169
|
+
type: 'object',
|
|
170
|
+
required: ['schema', 'results', 'blockers'],
|
|
171
|
+
properties: {
|
|
172
|
+
schema: { const: 'sks.research-source-search-output.v1' },
|
|
173
|
+
results: {
|
|
174
|
+
type: 'array',
|
|
175
|
+
items: {
|
|
176
|
+
type: 'object',
|
|
177
|
+
required: ['title', 'url', 'snippet'],
|
|
178
|
+
properties: {
|
|
179
|
+
title: { type: 'string' },
|
|
180
|
+
url: { type: 'string' },
|
|
181
|
+
snippet: { type: 'string' }
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
blockers: { type: 'array', items: { type: 'string' } }
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
//# sourceMappingURL=research-super-search.js.map
|
|
@@ -4,6 +4,8 @@ export function buildResearchSynthesisPrompt(input) {
|
|
|
4
4
|
'Do not write a short summary.',
|
|
5
5
|
'Do not pad with repeated paragraphs.',
|
|
6
6
|
'Every key claim must cite source-ledger ids.',
|
|
7
|
+
'In the Key Claims section, write every key claim id and its actual claim text in one local paragraph or table row, with at least one source id linked to that same claim in claim-evidence-matrix.json.',
|
|
8
|
+
'A global References list does not satisfy claim coverage. Claim-local citations must appear beside the claim they support.',
|
|
7
9
|
'Every recommendation must point to implementation-blueprint sections.',
|
|
8
10
|
'Every limitation must point to falsification-ledger cases or source blockers.',
|
|
9
11
|
'Return JSON only matching sks.research-synthesis-output.v1.',
|
|
@@ -27,15 +29,32 @@ function compactEvidencePack(input) {
|
|
|
27
29
|
source_ids: sourceRows.map((source) => ({
|
|
28
30
|
id: source.id,
|
|
29
31
|
layer: source.layer,
|
|
32
|
+
kind: source.kind,
|
|
30
33
|
title: source.title,
|
|
34
|
+
locator: source.locator,
|
|
35
|
+
publisher_or_author: source.publisher_or_author,
|
|
36
|
+
published_at: source.published_at || null,
|
|
37
|
+
accessed_at: source.accessed_at || null,
|
|
38
|
+
reliability: source.reliability,
|
|
39
|
+
credibility: source.credibility,
|
|
31
40
|
stance: source.stance,
|
|
32
|
-
claim_ids: source.claim_ids || []
|
|
41
|
+
claim_ids: source.claim_ids || [],
|
|
42
|
+
notes: source.notes || '',
|
|
43
|
+
content_artifact: source.content_artifact || null,
|
|
44
|
+
content_sha256: source.content_sha256 || null,
|
|
45
|
+
content_length: source.content_length || null,
|
|
46
|
+
acquisition_verdict: source.acquisition_verdict || null,
|
|
47
|
+
domain: source.domain || null,
|
|
48
|
+
authority_tier: source.authority_tier || null,
|
|
49
|
+
primary_source: source.primary_source === true,
|
|
50
|
+
independence_cluster_id: source.independence_cluster_id || null
|
|
33
51
|
})),
|
|
34
52
|
key_claims: (Array.isArray(input.claimMatrix?.claims) ? input.claimMatrix.claims : []).map((claim) => ({
|
|
35
53
|
id: claim.id,
|
|
36
54
|
claim: claim.claim,
|
|
37
55
|
source_ids: claim.source_ids || [],
|
|
38
56
|
counterevidence_ids: claim.counterevidence_ids || [],
|
|
57
|
+
counterevidence_links: claim.counterevidence_links || [],
|
|
39
58
|
test_or_probe: claim.test_or_probe || ''
|
|
40
59
|
})),
|
|
41
60
|
falsification_cases: Array.isArray(input.falsificationLedger?.cases) ? input.falsificationLedger.cases : [],
|
|
@@ -2,6 +2,7 @@ import path from 'node:path';
|
|
|
2
2
|
import { readJson, writeJsonAtomic, writeTextAtomic, nowIso } from '../fsx.js';
|
|
3
3
|
import { runCodexTask } from '../codex-control/codex-task-runner.js';
|
|
4
4
|
import { researchPaperArtifactForPlan } from '../research.js';
|
|
5
|
+
import { THINKING_SUBAGENT_MODEL, SUBAGENT_EFFORT } from '../subagents/model-policy.js';
|
|
5
6
|
import { analyzeResearchReportQuality, countWords } from './research-report-quality.js';
|
|
6
7
|
import { analyzeResearchRepetition } from './research-repetition-detector.js';
|
|
7
8
|
import { buildRealisticResearchPaper, buildRealisticResearchReport } from './research-realistic-report.js';
|
|
@@ -52,7 +53,7 @@ export async function runResearchCodexSynthesisWriter(input) {
|
|
|
52
53
|
}
|
|
53
54
|
const result = await runCodexTask({
|
|
54
55
|
route: '$Research',
|
|
55
|
-
tier: '
|
|
56
|
+
tier: 'orchestrator',
|
|
56
57
|
missionId: String(input.plan?.mission_id || 'research-synthesis'),
|
|
57
58
|
workItemId: 'research_synthesis',
|
|
58
59
|
cwd: input.root,
|
|
@@ -73,7 +74,16 @@ export async function runResearchCodexSynthesisWriter(input) {
|
|
|
73
74
|
allowLocalLlm: false,
|
|
74
75
|
localLlmPolicy: { mode: 'disabled', requiresGptFinal: true },
|
|
75
76
|
mutationLedgerRoot: path.join(input.dir, 'research', 'synthesis-codex-control'),
|
|
76
|
-
reliabilityPolicy: {
|
|
77
|
+
reliabilityPolicy: {
|
|
78
|
+
timeoutClass: 'standard',
|
|
79
|
+
idleTimeoutMs: input.timeoutMs || 120000,
|
|
80
|
+
hardTimeoutMs: input.timeoutMs || 120000,
|
|
81
|
+
...(input.deadlineMs === undefined ? {} : { deadlineEpochMs: input.deadlineMs })
|
|
82
|
+
},
|
|
83
|
+
model: THINKING_SUBAGENT_MODEL,
|
|
84
|
+
reasoningEffort: SUBAGENT_EFFORT,
|
|
85
|
+
modelReasoningEffort: SUBAGENT_EFFORT,
|
|
86
|
+
serviceTier: 'fast'
|
|
77
87
|
});
|
|
78
88
|
const worker = await readJson(result.workerResultPath, null);
|
|
79
89
|
const output = normalizeResearchSynthesisOutput(worker);
|
|
@@ -127,7 +137,8 @@ export function validateResearchSynthesisOutput(output, contract = null, claimMa
|
|
|
127
137
|
const report = output.report_markdown;
|
|
128
138
|
const paper = output.paper_markdown;
|
|
129
139
|
const sourceIdsCited = sourceIds.filter((id) => report.includes(id));
|
|
130
|
-
const
|
|
140
|
+
const claimCoverage = keyClaims.map((id) => claimLocalReportCoverage(report, claimMatrix, id));
|
|
141
|
+
const keyClaimsCovered = claimCoverage.filter((row) => row.ok).map((row) => row.claim_id);
|
|
131
142
|
const paperSections = ['Abstract', 'Introduction', 'Methodology', 'Findings', 'Discussion', 'Limitations', 'Conclusion', 'References'];
|
|
132
143
|
const blockers = [
|
|
133
144
|
...(output.schema === 'sks.research-synthesis-output.v1' ? [] : ['research_synthesis_schema_invalid']),
|
|
@@ -138,6 +149,9 @@ export function validateResearchSynthesisOutput(output, contract = null, claimMa
|
|
|
138
149
|
...reportQuality.blockers,
|
|
139
150
|
...repetition.blockers,
|
|
140
151
|
...(sourceIdsCited.length >= Math.min(8, sourceIds.length) ? [] : ['research_synthesis_unique_sources_below_contract']),
|
|
152
|
+
...claimCoverage.filter((row) => !row.id_present).map((row) => `research_synthesis_key_claim_id_missing:${row.claim_id}`),
|
|
153
|
+
...claimCoverage.filter((row) => !row.semantics_present).map((row) => `research_synthesis_key_claim_semantics_missing:${row.claim_id}`),
|
|
154
|
+
...claimCoverage.filter((row) => !row.local_citation_present).map((row) => `research_synthesis_key_claim_local_citation_missing:${row.claim_id}`),
|
|
141
155
|
...(keyClaimsCovered.length >= Number(contract?.min_key_claims || 8) ? [] : ['research_synthesis_key_claims_below_contract']),
|
|
142
156
|
...(repetition.repeated_paragraph_ratio <= 0.18 ? [] : ['research_synthesis_repeated_paragraph_ratio_high']),
|
|
143
157
|
...(repetition.template_phrase_hits.length ? ['research_synthesis_template_phrase_hits'] : []),
|
|
@@ -146,6 +160,72 @@ export function validateResearchSynthesisOutput(output, contract = null, claimMa
|
|
|
146
160
|
];
|
|
147
161
|
return { ok: blockers.length === 0, blockers: [...new Set(blockers)] };
|
|
148
162
|
}
|
|
163
|
+
function claimLocalReportCoverage(report, claimMatrix, claimId) {
|
|
164
|
+
const claim = (Array.isArray(claimMatrix?.claims) ? claimMatrix.claims : []).find((row) => String(row?.id || '') === claimId);
|
|
165
|
+
const claimText = String(claim?.claim || '').trim();
|
|
166
|
+
const linkedSourceIds = normalizeStringList(claim?.source_ids);
|
|
167
|
+
const blocks = markdownSection(report, 'Key Claims').split(/\n\s*\n/).map((block) => block.trim()).filter(Boolean);
|
|
168
|
+
let idPresent = false;
|
|
169
|
+
let semanticsPresent = false;
|
|
170
|
+
let localCitationPresent = false;
|
|
171
|
+
for (const block of blocks) {
|
|
172
|
+
const hasId = block.includes(claimId);
|
|
173
|
+
const hasSemantics = semanticallyContainsClaim(block, claimText);
|
|
174
|
+
const hasLocalCitation = linkedSourceIds.some((sourceId) => block.includes(sourceId));
|
|
175
|
+
idPresent ||= hasId;
|
|
176
|
+
semanticsPresent ||= hasSemantics;
|
|
177
|
+
localCitationPresent ||= hasId && hasSemantics && hasLocalCitation;
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
claim_id: claimId,
|
|
181
|
+
id_present: idPresent,
|
|
182
|
+
semantics_present: semanticsPresent,
|
|
183
|
+
local_citation_present: localCitationPresent,
|
|
184
|
+
ok: idPresent && semanticsPresent && localCitationPresent
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function markdownSection(markdown, heading) {
|
|
188
|
+
const target = normalizeHeading(heading);
|
|
189
|
+
const lines = String(markdown || '').split(/\r?\n/);
|
|
190
|
+
const out = [];
|
|
191
|
+
let capture = false;
|
|
192
|
+
let level = 0;
|
|
193
|
+
for (const line of lines) {
|
|
194
|
+
const match = /^(#{1,6})\s+(.+?)\s*#*\s*$/.exec(line);
|
|
195
|
+
if (match) {
|
|
196
|
+
const nextLevel = match[1]?.length || 0;
|
|
197
|
+
const normalized = normalizeHeading(match[2] || '');
|
|
198
|
+
if (capture && nextLevel <= level)
|
|
199
|
+
break;
|
|
200
|
+
if (!capture && normalized.includes(target)) {
|
|
201
|
+
capture = true;
|
|
202
|
+
level = nextLevel;
|
|
203
|
+
}
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (capture)
|
|
207
|
+
out.push(line);
|
|
208
|
+
}
|
|
209
|
+
return out.join('\n');
|
|
210
|
+
}
|
|
211
|
+
function semanticallyContainsClaim(block, claimText) {
|
|
212
|
+
const claimTokens = semanticTokens(claimText);
|
|
213
|
+
if (!claimTokens.length)
|
|
214
|
+
return false;
|
|
215
|
+
const blockTokens = new Set(semanticTokens(block));
|
|
216
|
+
const overlap = claimTokens.filter((token) => blockTokens.has(token)).length;
|
|
217
|
+
const minimumOverlap = claimTokens.length <= 2 ? claimTokens.length : claimTokens.length <= 5 ? 2 : 3;
|
|
218
|
+
const minimumCoverage = claimTokens.length <= 3 ? 1 : 0.3;
|
|
219
|
+
return overlap >= minimumOverlap && overlap / claimTokens.length >= minimumCoverage;
|
|
220
|
+
}
|
|
221
|
+
function semanticTokens(value) {
|
|
222
|
+
const stop = new Set(['about', 'after', 'before', 'been', 'being', 'could', 'evidence', 'finding', 'from', 'have', 'into', 'research', 'result', 'should', 'source', 'study', 'that', 'their', 'there', 'these', 'this', 'through', 'using', 'with']);
|
|
223
|
+
return normalizeStringList(String(value || '').toLowerCase().normalize('NFKC').match(/[\p{L}\p{N}]{4,}/gu) || [])
|
|
224
|
+
.filter((token) => !stop.has(token));
|
|
225
|
+
}
|
|
226
|
+
function normalizeHeading(value) {
|
|
227
|
+
return String(value || '').toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim();
|
|
228
|
+
}
|
|
149
229
|
async function readSynthesisInputs(dir) {
|
|
150
230
|
return {
|
|
151
231
|
sourceLedger: await readJson(path.join(dir, 'source-ledger.json'), null),
|
|
@@ -161,8 +241,9 @@ function mockResearchSynthesisOutput(plan, artifacts) {
|
|
|
161
241
|
const claims = Array.isArray(artifacts.claimMatrix?.claims) ? artifacts.claimMatrix.claims : [];
|
|
162
242
|
const sourceIds = sourceIdsFromLedger(artifacts.sourceLedger);
|
|
163
243
|
const counterIds = counterevidenceIdsFromLedger(artifacts.sourceLedger);
|
|
164
|
-
const
|
|
165
|
-
const
|
|
244
|
+
const keyClaimIds = Array.isArray(artifacts.claimMatrix?.key_claim_ids) ? artifacts.claimMatrix.key_claim_ids.map(String) : [];
|
|
245
|
+
const report = buildRealisticResearchReport({ plan, claims, keyClaimIds, sourceIds, counterevidenceIds: counterIds, blueprint: artifacts.implementationBlueprint, falsificationLedger: artifacts.falsificationLedger, experimentPlan: artifacts.experimentPlan, replicationPack: artifacts.replicationPack });
|
|
246
|
+
const paper = buildRealisticResearchPaper({ plan, claims, keyClaimIds, sourceIds, counterevidenceIds: counterIds });
|
|
166
247
|
return normalizeResearchSynthesisOutput({
|
|
167
248
|
schema: 'sks.research-synthesis-output.v1',
|
|
168
249
|
mission_id: String(plan?.mission_id || ''),
|
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { nowIso, writeJsonAtomic } from '../fsx.js';
|
|
3
|
-
import {
|
|
3
|
+
import { RESEARCH_AGENT_PERSONA_CONTRACT } from '../recallpulse/policy.js';
|
|
4
|
+
import { RESEARCH_SOURCE_LAYERS } from './research-source-layer-catalog.js';
|
|
4
5
|
export const RESEARCH_WORK_GRAPH_ARTIFACT = 'research-work-graph.json';
|
|
5
|
-
export const REQUIRED_SOURCE_SHARD_IDS = Object.freeze(
|
|
6
|
-
'source_shard_academic_literature',
|
|
7
|
-
'source_shard_official_government_data',
|
|
8
|
-
'source_shard_standards_primary_docs',
|
|
9
|
-
'source_shard_news_current_events',
|
|
10
|
-
'source_shard_public_discourse',
|
|
11
|
-
'source_shard_developer_practitioner',
|
|
12
|
-
'source_shard_counterevidence_factcheck',
|
|
13
|
-
'source_shard_local_project_evidence'
|
|
14
|
-
]);
|
|
6
|
+
export const REQUIRED_SOURCE_SHARD_IDS = Object.freeze(RESEARCH_SOURCE_LAYERS.map((layer) => `source_shard_${layer.id}`));
|
|
15
7
|
function researchStages() {
|
|
16
8
|
const sourceShards = RESEARCH_SOURCE_LAYERS.map((layer) => ({
|
|
17
9
|
id: `source_shard_${layer.id}`,
|
|
@@ -71,15 +63,27 @@ function researchStages() {
|
|
|
71
63
|
kind: 'research',
|
|
72
64
|
stage_kind: 'synthesis',
|
|
73
65
|
dependencies: ['claim_matrix_build', 'falsification', 'implementation_blueprint', 'experiment_plan'],
|
|
74
|
-
outputs: ['research-report.md', 'research-paper.md', '
|
|
66
|
+
outputs: ['research-report.md', 'research-paper.md', 'novelty-ledger.json']
|
|
75
67
|
},
|
|
76
68
|
{
|
|
77
69
|
id: 'final_review',
|
|
78
|
-
title: 'Static plus
|
|
70
|
+
title: 'Static plus official-subagent adversarial review and bounded revision',
|
|
79
71
|
kind: 'verification',
|
|
80
72
|
stage_kind: 'final_review',
|
|
81
73
|
dependencies: ['synthesis'],
|
|
82
|
-
outputs: [
|
|
74
|
+
outputs: [
|
|
75
|
+
'research-final-review.static.json',
|
|
76
|
+
'research-final-review.codex.json',
|
|
77
|
+
'research-final-review.json',
|
|
78
|
+
'research-adversarial-plan.json',
|
|
79
|
+
'research-adversarial-review.json',
|
|
80
|
+
'research-revision-ledger.json',
|
|
81
|
+
'research-adversarial-convergence.json',
|
|
82
|
+
'research-honest-mode.json',
|
|
83
|
+
'genius-opinion-summary.md',
|
|
84
|
+
'agent-ledger.json',
|
|
85
|
+
'debate-ledger.json'
|
|
86
|
+
]
|
|
83
87
|
},
|
|
84
88
|
{
|
|
85
89
|
id: 'verification',
|
|
@@ -116,7 +120,7 @@ function workItem(stage, index, allStages, plan = null) {
|
|
|
116
120
|
lease_requirements: stage.outputs.map((artifact) => ({ path: `${missionPrefix}${artifact}`, kind: 'read' })),
|
|
117
121
|
acceptance: { requires_patch_envelope: false, requires_verification: true, requires_gpt_final: stage.stage_kind === 'final_review' },
|
|
118
122
|
owner: null,
|
|
119
|
-
allocation_reason: 'Stage-aware read-only
|
|
123
|
+
allocation_reason: 'Stage-aware read-only Research graph: Super Search source acquisition, evidence synthesis, and official-subagent adversarial convergence',
|
|
120
124
|
allocation_score: 1,
|
|
121
125
|
allocation_hints: { domains: [stage.kind], write_paths: [], read_only_paths: stage.outputs },
|
|
122
126
|
lane: null,
|
|
@@ -132,14 +136,14 @@ function workItem(stage, index, allStages, plan = null) {
|
|
|
132
136
|
}
|
|
133
137
|
export function buildResearchWorkGraph(plan = null) {
|
|
134
138
|
const stages = researchStages();
|
|
135
|
-
const
|
|
139
|
+
const requestedReviewers = RESEARCH_AGENT_PERSONA_CONTRACT.length;
|
|
136
140
|
const workItems = stages.map((stage, index) => workItem(stage, index, stages, plan));
|
|
137
141
|
const sourceShardIds = workItems.filter((item) => item.stage_kind === 'source_shard').map((item) => item.id);
|
|
138
142
|
const closeoutIds = workItems.filter((item) => item.stage_kind !== 'source_shard').map((item) => item.id);
|
|
139
143
|
return {
|
|
140
144
|
schema: 'sks.naruto-work-graph.v1',
|
|
141
145
|
route: '$Naruto',
|
|
142
|
-
requested_clones:
|
|
146
|
+
requested_clones: requestedReviewers,
|
|
143
147
|
total_work_items: workItems.length,
|
|
144
148
|
readonly: true,
|
|
145
149
|
write_capable: false,
|
|
@@ -152,7 +156,10 @@ export function buildResearchWorkGraph(plan = null) {
|
|
|
152
156
|
write_allowed_count: 0,
|
|
153
157
|
worktree_policy: { mode: 'patch-envelope-only', required: false, main_repo_root: null, worktree_root: null, fallback_reason: 'Research route is read-only.' },
|
|
154
158
|
blockers: [],
|
|
155
|
-
ok: true
|
|
159
|
+
ok: true,
|
|
160
|
+
official_subagent_workflow: true,
|
|
161
|
+
official_subagent_reviewer_count: requestedReviewers,
|
|
162
|
+
legacy_process_swarm_used: false
|
|
156
163
|
};
|
|
157
164
|
}
|
|
158
165
|
export async function writeResearchWorkGraph(dir, plan = null) {
|
|
@@ -26,6 +26,11 @@ function sourceRows(sourceLedger = null) {
|
|
|
26
26
|
function missingFields(row) {
|
|
27
27
|
return REQUIRED_SOURCE_FIELDS.filter((field) => {
|
|
28
28
|
const value = row?.[field];
|
|
29
|
+
if (field === 'claim_ids') {
|
|
30
|
+
if (!Array.isArray(value))
|
|
31
|
+
return true;
|
|
32
|
+
return ['supports', 'undermines'].includes(String(row?.stance || '')) && value.length === 0;
|
|
33
|
+
}
|
|
29
34
|
if (Array.isArray(value))
|
|
30
35
|
return value.length === 0;
|
|
31
36
|
return value === undefined || value === null || String(value).trim() === '';
|
|
@@ -54,8 +59,14 @@ export function buildSourceQualityReport(sourceLedger = null, claimMatrix = null
|
|
|
54
59
|
const keyClaimIds = asArray(claimMatrix?.key_claim_ids).map(String);
|
|
55
60
|
const citedClaimIds = new Set(rows.flatMap((row) => asArray(row?.claim_ids).map(String)));
|
|
56
61
|
const uncitedKeyClaimIds = keyClaimIds.filter((id) => !citedClaimIds.has(id));
|
|
62
|
+
const untrustedClaimLinks = rows.flatMap((row) => {
|
|
63
|
+
const linked = asArray(row?.supports).length > 0 || asArray(row?.undermines).length > 0;
|
|
64
|
+
return linked && !trustedLinkedEvidence(row) ? [`source_claim_link_untrusted:${String(row?.id || 'unknown')}`] : [];
|
|
65
|
+
});
|
|
57
66
|
const blockers = [
|
|
58
67
|
...rowReports.flatMap((row) => row.ok ? [] : [`source_metadata_incomplete:${row.id || 'unknown'}`]),
|
|
68
|
+
...asArray(sourceLedger?.claim_link_blockers).map(String),
|
|
69
|
+
...untrustedClaimLinks,
|
|
59
70
|
...(keyClaimIds.length && uncitedKeyClaimIds.length ? ['key_claim_citation_coverage_incomplete'] : []),
|
|
60
71
|
...(sourceLedger?.citation_coverage?.all_key_claims_cited === false ? ['source_ledger_reports_uncited_key_claims'] : [])
|
|
61
72
|
];
|
|
@@ -83,6 +94,16 @@ export function buildSourceQualityReport(sourceLedger = null, claimMatrix = null
|
|
|
83
94
|
sources: rowReports
|
|
84
95
|
};
|
|
85
96
|
}
|
|
97
|
+
function trustedLinkedEvidence(row) {
|
|
98
|
+
if (/^(?:deterministic_fixture|mock|selftest(?:-|$))/i.test(String(row?.kind || '')))
|
|
99
|
+
return true;
|
|
100
|
+
return String(row?.acquisition_verdict || '') === 'verified_content'
|
|
101
|
+
&& /^verified_content:/i.test(String(row?.credibility || ''))
|
|
102
|
+
&& Boolean(String(row?.content_artifact || '').trim())
|
|
103
|
+
&& /^[a-f0-9]{64}$/i.test(String(row?.content_sha256 || '').trim())
|
|
104
|
+
&& Number(row?.content_length || 0) > 0
|
|
105
|
+
&& row?.super_search_provenance?.validated === true;
|
|
106
|
+
}
|
|
86
107
|
export async function readSourceQualityReport(dir) {
|
|
87
108
|
return readJson(path.join(dir, SOURCE_QUALITY_REPORT_ARTIFACT), null);
|
|
88
109
|
}
|