sneakoscope 2.0.13 → 2.0.14
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 +2 -2
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/.sks-build-stamp.json +4 -4
- package/dist/bin/sks.js +1 -1
- package/dist/core/agents/agent-orchestrator.js +11 -4
- package/dist/core/agents/agent-output-validator.js +1 -1
- package/dist/core/codex-control/codex-fake-sdk-adapter.js +3 -3
- package/dist/core/codex-control/gpt-final-review-schema.js +61 -14
- package/dist/core/commands/naruto-command.js +1 -0
- package/dist/core/commands/research-command.js +71 -17
- package/dist/core/fsx.js +1 -1
- package/dist/core/naruto/naruto-real-worker-child.js +11 -3
- package/dist/core/naruto/naruto-real-worker-runtime.js +4 -0
- package/dist/core/pipeline/final-gpt-patch-stage.js +20 -3
- package/dist/core/research/implementation-blueprint-densifier.js +124 -0
- package/dist/core/research/research-claim-builder.js +114 -0
- package/dist/core/research/research-cycle-runner.js +115 -11
- package/dist/core/research/research-final-reviewer.js +155 -1
- package/dist/core/research/research-source-ledger-merge.js +186 -0
- package/dist/core/research/research-source-shards.js +176 -0
- package/dist/core/research/research-stage-runner.js +510 -11
- package/dist/core/research/research-work-graph.js +114 -23
- package/dist/core/research.js +12 -0
- package/dist/core/version.js +1 -1
- package/dist/scripts/codex-sdk-research-pipeline-check.js +40 -8
- package/dist/scripts/release-dag-full-coverage-check.js +14 -1
- package/dist/scripts/release-parallel-speed-budget-check.js +7 -2
- package/dist/scripts/research-blueprint-densifier-check.js +21 -0
- package/dist/scripts/research-claim-builder-check.js +19 -0
- package/dist/scripts/research-complete-package-fixture-check.js +23 -0
- package/dist/scripts/research-final-reviewer-blackbox.js +22 -0
- package/dist/scripts/research-parallel-source-shards-check.js +22 -0
- package/dist/scripts/research-quality-gate-check.js +28 -3
- package/dist/scripts/research-real-cycle-no-legacy-final-md-check.js +14 -0
- package/dist/scripts/research-short-report-rejection-check.js +46 -0
- package/dist/scripts/research-source-ledger-merge-check.js +26 -0
- package/dist/scripts/research-stage-cycle-runtime-blackbox.js +24 -0
- package/package.json +16 -1
- package/schemas/codex/agent-result.schema.json +1 -1
- package/schemas/research/research-source-shard.schema.json +46 -0
- package/dist/build-manifest.json +0 -1184
- package/dist/scripts/release-readiness-report.js +0 -1146
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/permission-request.command.input.schema.json +0 -61
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/permission-request.command.output.schema.json +0 -103
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/post-compact.command.input.schema.json +0 -52
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/post-compact.command.output.schema.json +0 -24
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/post-tool-use.command.input.schema.json +0 -67
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/post-tool-use.command.output.schema.json +0 -84
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/pre-compact.command.input.schema.json +0 -52
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/pre-compact.command.output.schema.json +0 -24
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/pre-tool-use.command.input.schema.json +0 -65
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/pre-tool-use.command.output.schema.json +0 -105
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/session-start.command.input.schema.json +0 -59
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/session-start.command.output.schema.json +0 -63
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/snapshot-metadata.json +0 -31
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/stop.command.input.schema.json +0 -63
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/stop.command.output.schema.json +0 -45
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/user-prompt-submit.command.input.schema.json +0 -59
- package/dist/vendor/openai-codex/rust-v0.131.0/hooks/user-prompt-submit.command.output.schema.json +0 -81
|
@@ -1,19 +1,99 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { nowIso, writeJsonAtomic } from '../fsx.js';
|
|
3
|
+
import { RESEARCH_SOURCE_LAYERS } from './research-source-shards.js';
|
|
3
4
|
export const RESEARCH_WORK_GRAPH_ARTIFACT = 'research-work-graph.json';
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
];
|
|
14
|
-
function
|
|
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
|
+
]);
|
|
15
|
+
function researchStages() {
|
|
16
|
+
const sourceShards = RESEARCH_SOURCE_LAYERS.map((layer) => ({
|
|
17
|
+
id: `source_shard_${layer.id}`,
|
|
18
|
+
title: `Source shard: ${layer.label}`,
|
|
19
|
+
kind: 'research',
|
|
20
|
+
stage_kind: 'source_shard',
|
|
21
|
+
layer_id: layer.id,
|
|
22
|
+
dependencies: [],
|
|
23
|
+
outputs: [`research/cycle-\${cycle}/source-shards/${layer.id}.json`]
|
|
24
|
+
}));
|
|
25
|
+
const shardIds = sourceShards.map((stage) => stage.id);
|
|
26
|
+
return [
|
|
27
|
+
...sourceShards,
|
|
28
|
+
{
|
|
29
|
+
id: 'source_ledger_merge',
|
|
30
|
+
title: 'Source-ledger partial merge',
|
|
31
|
+
kind: 'research',
|
|
32
|
+
stage_kind: 'source_merge',
|
|
33
|
+
dependencies: shardIds,
|
|
34
|
+
outputs: ['source-ledger.json', 'source-quality-report.json']
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'claim_matrix_build',
|
|
38
|
+
title: 'Claim-evidence matrix build from merged source shards',
|
|
39
|
+
kind: 'research',
|
|
40
|
+
stage_kind: 'claim_matrix_build',
|
|
41
|
+
dependencies: [...shardIds, 'source_ledger_merge'],
|
|
42
|
+
outputs: ['claim-evidence-matrix.json']
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: 'falsification',
|
|
46
|
+
title: 'Counterevidence and falsification stage',
|
|
47
|
+
kind: 'verification',
|
|
48
|
+
stage_kind: 'falsification',
|
|
49
|
+
dependencies: ['claim_matrix_build', 'source_shard_counterevidence_factcheck'],
|
|
50
|
+
outputs: ['falsification-ledger.json']
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 'implementation_blueprint',
|
|
54
|
+
title: 'Concrete implementation blueprint and handoff',
|
|
55
|
+
kind: 'documentation',
|
|
56
|
+
stage_kind: 'implementation_blueprint',
|
|
57
|
+
dependencies: ['claim_matrix_build', 'source_shard_local_project_evidence'],
|
|
58
|
+
outputs: ['implementation-blueprint.json', 'implementation-blueprint.md', 'team-handoff-goal.md']
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'experiment_plan',
|
|
62
|
+
title: 'Experiment plan and replication pack',
|
|
63
|
+
kind: 'verification',
|
|
64
|
+
stage_kind: 'experiment_plan',
|
|
65
|
+
dependencies: ['implementation_blueprint', 'falsification'],
|
|
66
|
+
outputs: ['experiment-plan.json', 'experiment-plan.md', 'replication-pack.json']
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'synthesis',
|
|
70
|
+
title: 'Research report and manuscript synthesis',
|
|
71
|
+
kind: 'research',
|
|
72
|
+
stage_kind: 'synthesis',
|
|
73
|
+
dependencies: ['claim_matrix_build', 'falsification', 'implementation_blueprint', 'experiment_plan'],
|
|
74
|
+
outputs: ['research-report.md', 'research-paper.md', 'genius-opinion-summary.md', 'agent-ledger.json', 'debate-ledger.json', 'novelty-ledger.json']
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: 'final_review',
|
|
78
|
+
title: 'Static plus Codex/GPT research final reviewer',
|
|
79
|
+
kind: 'verification',
|
|
80
|
+
stage_kind: 'final_review',
|
|
81
|
+
dependencies: ['synthesis'],
|
|
82
|
+
outputs: ['research-final-review.static.json', 'research-final-review.codex.json', 'research-final-review.json']
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: 'verification',
|
|
86
|
+
title: 'Research gate evaluation and route finalization input',
|
|
87
|
+
kind: 'final_review_input_pack',
|
|
88
|
+
stage_kind: 'verification',
|
|
89
|
+
dependencies: ['final_review'],
|
|
90
|
+
outputs: ['research-gate.json', 'research-gate.evaluated.json']
|
|
91
|
+
}
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
function workItem(stage, index, allStages, plan = null) {
|
|
15
95
|
const missionPrefix = plan?.mission_id ? `.sneakoscope/missions/${plan.mission_id}/` : '';
|
|
16
|
-
|
|
96
|
+
const item = {
|
|
17
97
|
id: stage.id,
|
|
18
98
|
kind: stage.kind,
|
|
19
99
|
title: stage.title,
|
|
@@ -22,29 +102,40 @@ function workItem(stage, index, plan = null) {
|
|
|
22
102
|
`${missionPrefix}research-plan.json`,
|
|
23
103
|
`${missionPrefix}research-quality-contract.json`,
|
|
24
104
|
`${missionPrefix}source-ledger.json`,
|
|
25
|
-
`${missionPrefix}claim-evidence-matrix.json
|
|
105
|
+
`${missionPrefix}claim-evidence-matrix.json`,
|
|
106
|
+
`${missionPrefix}falsification-ledger.json`
|
|
26
107
|
],
|
|
27
108
|
write_paths: [],
|
|
28
|
-
required_role: index <
|
|
109
|
+
required_role: index < RESEARCH_SOURCE_LAYERS.length ? 'research' : stage.kind === 'documentation' ? 'planner' : 'verifier',
|
|
29
110
|
write_allowed: false,
|
|
30
111
|
verification_required: true,
|
|
31
|
-
dependencies:
|
|
32
|
-
can_run_in_parallel_with:
|
|
112
|
+
dependencies: stage.dependencies,
|
|
113
|
+
can_run_in_parallel_with: allStages.filter((candidate) => candidate.id !== stage.id && !stage.dependencies.includes(candidate.id)).map((candidate) => candidate.id),
|
|
33
114
|
conflicts_with: [],
|
|
34
|
-
estimated_cost: { tokens: 4000, latency_ms: 60000, cpu_weight: 1, memory_mb: 256, gpu_weight: 0 },
|
|
115
|
+
estimated_cost: { tokens: stage.stage_kind === 'source_shard' ? 2500 : 4000, latency_ms: stage.stage_kind === 'source_shard' ? 30000 : 60000, cpu_weight: 1, memory_mb: 256, gpu_weight: 0 },
|
|
35
116
|
lease_requirements: stage.outputs.map((artifact) => ({ path: `${missionPrefix}${artifact}`, kind: 'read' })),
|
|
36
|
-
acceptance: { requires_patch_envelope: false, requires_verification: true, requires_gpt_final:
|
|
117
|
+
acceptance: { requires_patch_envelope: false, requires_verification: true, requires_gpt_final: stage.stage_kind === 'final_review' },
|
|
37
118
|
owner: null,
|
|
38
|
-
allocation_reason: 'Stage-aware read-only research pipeline work graph',
|
|
119
|
+
allocation_reason: 'Stage-aware read-only research pipeline work graph with source-layer shard parallelism',
|
|
39
120
|
allocation_score: 1,
|
|
40
121
|
allocation_hints: { domains: [stage.kind], write_paths: [], read_only_paths: stage.outputs },
|
|
41
122
|
lane: null,
|
|
42
123
|
worktree: { mode: 'patch-envelope-only', required: false, allocation_required: false }
|
|
43
124
|
};
|
|
125
|
+
return {
|
|
126
|
+
...item,
|
|
127
|
+
stage_kind: stage.stage_kind,
|
|
128
|
+
layer_id: stage.layer_id || null,
|
|
129
|
+
output_artifacts: stage.outputs,
|
|
130
|
+
required: stage.required !== false
|
|
131
|
+
};
|
|
44
132
|
}
|
|
45
133
|
export function buildResearchWorkGraph(plan = null) {
|
|
46
|
-
const
|
|
47
|
-
const
|
|
134
|
+
const stages = researchStages();
|
|
135
|
+
const requestedClones = Math.max(8, Number(plan?.native_agent_plan?.session_count || 0), RESEARCH_SOURCE_LAYERS.length);
|
|
136
|
+
const workItems = stages.map((stage, index) => workItem(stage, index, stages, plan));
|
|
137
|
+
const sourceShardIds = workItems.filter((item) => item.stage_kind === 'source_shard').map((item) => item.id);
|
|
138
|
+
const closeoutIds = workItems.filter((item) => item.stage_kind !== 'source_shard').map((item) => item.id);
|
|
48
139
|
return {
|
|
49
140
|
schema: 'sks.naruto-work-graph.v1',
|
|
50
141
|
route: '$Naruto',
|
|
@@ -54,8 +145,8 @@ export function buildResearchWorkGraph(plan = null) {
|
|
|
54
145
|
write_capable: false,
|
|
55
146
|
work_items: workItems,
|
|
56
147
|
active_waves: [
|
|
57
|
-
{ wave_id: '
|
|
58
|
-
{ wave_id: 'research-closeout-wave', work_item_ids:
|
|
148
|
+
{ wave_id: 'parallel-source-shard-wave', work_item_ids: sourceShardIds, write_paths: [], conflict_count: 0 },
|
|
149
|
+
{ wave_id: 'research-closeout-wave', work_item_ids: closeoutIds, write_paths: [], conflict_count: 0 }
|
|
59
150
|
],
|
|
60
151
|
mixed_work_kinds: [...new Set(workItems.map((item) => item.kind))],
|
|
61
152
|
write_allowed_count: 0,
|
package/dist/core/research.js
CHANGED
|
@@ -1528,6 +1528,18 @@ export async function writeMockResearchResult(dir, plan) {
|
|
|
1528
1528
|
evidence: ['mock research report', `mock research paper: ${paperArtifact}`, 'mock genius opinion summary', 'mock research source skill', 'mock layered source ledger', 'mock agent ledger', 'mock debate ledger', 'mock novelty ledger', 'mock falsification ledger'],
|
|
1529
1529
|
notes: ['mock mode records the new contract but does not call a model or perform live web browsing']
|
|
1530
1530
|
});
|
|
1531
|
+
await writeJsonAtomic(path.join(dir, 'research-final-review.codex.json'), {
|
|
1532
|
+
schema: 'sks.research-codex-final-review.v1',
|
|
1533
|
+
reviewed_at: nowIso(),
|
|
1534
|
+
verdict: 'approve',
|
|
1535
|
+
unsupported_claim_ids: [],
|
|
1536
|
+
missing_evidence: [],
|
|
1537
|
+
blueprint_findings: ['mock complete package fixture has implementation blueprint sections'],
|
|
1538
|
+
falsification_findings: ['mock complete package fixture has counterevidence and falsification cases'],
|
|
1539
|
+
required_revisions: [],
|
|
1540
|
+
confidence: 'high',
|
|
1541
|
+
mock: true
|
|
1542
|
+
});
|
|
1531
1543
|
await writeResearchNativeAgentBatchCompletion(dir, plan);
|
|
1532
1544
|
return evaluateResearchGate(dir);
|
|
1533
1545
|
}
|
package/dist/core/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const PACKAGE_VERSION = '2.0.
|
|
1
|
+
export const PACKAGE_VERSION = '2.0.14';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -1,15 +1,47 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @ts-nocheck
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
assertGate
|
|
7
|
-
|
|
8
|
-
assertGate(
|
|
9
|
-
assertGate(
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist, readText } from './lib/codex-sdk-gate-lib.js';
|
|
7
|
+
const researchCommand = readText('src/core/commands/research-command.ts');
|
|
8
|
+
assertGate(researchCommand.includes("backend: mock ? 'fake' : 'codex-sdk'"), 'Research pipeline must default native agents to codex-sdk');
|
|
9
|
+
assertGate(researchCommand.includes("flag(args, '--autoresearch') ? '$AutoResearch' : '$Research'"), 'Research/AutoResearch route selection missing');
|
|
10
|
+
assertGate(researchCommand.includes('narutoWorkGraph: researchWorkGraph'), 'Research pipeline must pass the stage-aware Naruto work graph');
|
|
11
|
+
assertGate(researchCommand.includes('readonly: true'), 'Research pipeline must force read-only native orchestration');
|
|
12
|
+
assertGate(researchCommand.includes('quality_metrics'), 'Research pipeline JSON output must include quality metrics');
|
|
13
|
+
assertGate(researchCommand.includes('const cycleResult = await runResearchCycle({'), 'Research default path must use runResearchCycle');
|
|
14
|
+
assertGate(researchCommand.includes('--legacy-research-cycle'), 'Legacy final.md loop must be opt-in only');
|
|
10
15
|
const researchCore = readText('src/core/research.ts');
|
|
11
16
|
assertGate(researchCore.includes('readResearchQualityContract'), 'Research gate must read research-quality-contract.json');
|
|
12
17
|
assertGate(researchCore.includes('claim_evidence_matrix_missing'), 'Research gate must require claim-evidence-matrix.json');
|
|
13
18
|
assertGate(researchCore.includes('research_final_review_not_approved'), 'Research gate must require final reviewer approval');
|
|
14
|
-
|
|
19
|
+
for (const [file, tokens] of Object.entries({
|
|
20
|
+
'src/core/research/research-work-graph.ts': ['buildResearchWorkGraph', 'source_shard_academic_literature'],
|
|
21
|
+
'src/core/research/research-cycle-runner.ts': ['runResearchCycle', 'Promise.race'],
|
|
22
|
+
'src/core/research/research-final-reviewer.ts': ['runResearchCodexFinalReviewer'],
|
|
23
|
+
'src/core/research/claim-evidence-matrix.ts': ['claim-evidence-matrix'],
|
|
24
|
+
'src/core/research/implementation-blueprint.ts': ['implementation-blueprint'],
|
|
25
|
+
'src/core/research/research-quality-contract.ts': ['research-quality-contract']
|
|
26
|
+
})) {
|
|
27
|
+
const text = readText(file);
|
|
28
|
+
for (const token of tokens)
|
|
29
|
+
assertGate(text.includes(token), `${file} missing token ${token}`);
|
|
30
|
+
}
|
|
31
|
+
const research = await importDist('core/research.js');
|
|
32
|
+
const fsx = await importDist('core/fsx.js');
|
|
33
|
+
const dirShort = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-codex-research-short-'));
|
|
34
|
+
const planShort = await research.writeResearchPlan(dirShort, 'codex sdk short rejection fixture', { missionId: 'M-CODEX-SHORT' });
|
|
35
|
+
await fsx.writeTextAtomic(path.join(dirShort, 'research-report.md'), `# Short Report\n\n${Array.from({ length: 300 }, (_unused, index) => `word${index}`).join(' ')}\n`);
|
|
36
|
+
await fsx.writeJsonAtomic(path.join(dirShort, 'source-ledger.json'), { schema_version: 1, web_search_passes: 1, source_layers: [], sources: [], counterevidence_sources: [], triangulation: { cross_layer_checks: [] }, citation_coverage: { all_key_claims_cited: false }, blockers: [] });
|
|
37
|
+
await fsx.writeJsonAtomic(path.join(dirShort, 'implementation-blueprint.json'), { schema: 'sks.research-implementation-blueprint.v1', sections: [] });
|
|
38
|
+
const shortGate = await research.evaluateResearchGate(dirShort);
|
|
39
|
+
assertGate(shortGate.passed === false, 'codex-sdk research pipeline must reject short report fixture', shortGate);
|
|
40
|
+
assertGate((shortGate.reasons || []).includes('research_report_too_short'), 'short rejection must include report length reason', shortGate);
|
|
41
|
+
const dirComplete = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-codex-research-complete-'));
|
|
42
|
+
const planComplete = await research.writeResearchPlan(dirComplete, 'codex sdk complete package fixture', { missionId: 'M-CODEX-COMPLETE' });
|
|
43
|
+
const completeGate = await research.writeMockResearchResult(dirComplete, planComplete);
|
|
44
|
+
assertGate(completeGate.passed === true, 'codex-sdk research pipeline must pass complete package fixture', completeGate);
|
|
45
|
+
assertGate(completeGate.metrics?.final_review_approved === true, 'complete package must include approved final review', completeGate.metrics);
|
|
46
|
+
emitGate('codex-sdk:research-pipeline', { route: '$Research', short_dir: dirShort, complete_dir: dirComplete });
|
|
15
47
|
//# sourceMappingURL=codex-sdk-research-pipeline-check.js.map
|
|
@@ -29,7 +29,20 @@ const requiredReleasePresetIds = [
|
|
|
29
29
|
'git:worktree-cross-rebase',
|
|
30
30
|
'local-collab:worktree-gpt-final-apply-policy',
|
|
31
31
|
'release:cache-glob-hashing',
|
|
32
|
-
'release:dag-full-coverage'
|
|
32
|
+
'release:dag-full-coverage',
|
|
33
|
+
'research:quality-contract',
|
|
34
|
+
'research:claim-matrix',
|
|
35
|
+
'research:source-quality-report',
|
|
36
|
+
'research:implementation-blueprint',
|
|
37
|
+
'research:experiment-plan',
|
|
38
|
+
'research:replication-pack',
|
|
39
|
+
'research:final-reviewer',
|
|
40
|
+
'research:work-graph',
|
|
41
|
+
'research:short-report-rejection',
|
|
42
|
+
'research:complete-package-fixture',
|
|
43
|
+
'research:stage-cycle-runtime-blackbox',
|
|
44
|
+
'research:final-reviewer-blackbox',
|
|
45
|
+
'codex-sdk:research-pipeline'
|
|
33
46
|
];
|
|
34
47
|
const missing = legacyIds.filter((id) => !gateIds.has(id) && !allowlist.has(id));
|
|
35
48
|
const missingRequiredReleasePreset = requiredReleasePresetIds.filter((id) => !gateIds.has(id) || !releasePresetIds.has(id));
|
|
@@ -12,12 +12,15 @@ const summary = JSON.parse(fs.readFileSync(latest.summaryPath, 'utf8'));
|
|
|
12
12
|
const slowest = slowestGateResults(latest.dir);
|
|
13
13
|
const warnOnly = process.env.SKS_RELEASE_SPEED_BUDGET_WARN_ONLY === '1';
|
|
14
14
|
const budgetMs = Number(process.env.SKS_RELEASE_SPEED_BUDGET_MS || 20 * 60 * 1000);
|
|
15
|
-
const cachedBudgetMs =
|
|
15
|
+
const cachedBudgetMs = Number(process.env.SKS_RELEASE_CACHED_SPEED_BUDGET_MS || 4 * 60 * 1000);
|
|
16
16
|
const cachedRatio = Number(summary.cached || 0) / Math.max(1, Number(summary.completed || summary.selected_gates || 1));
|
|
17
17
|
const cachedRun = cachedRatio >= 0.5;
|
|
18
18
|
const parallelismOk = cachedRun || summary.parallelism_gain >= 2;
|
|
19
19
|
const wallOk = cachedRun ? summary.wall_ms <= cachedBudgetMs : summary.wall_ms <= budgetMs;
|
|
20
|
-
const
|
|
20
|
+
const failureIds = Array.isArray(summary.failures) ? summary.failures.map((entry) => String(entry?.id || '')).filter(Boolean) : [];
|
|
21
|
+
const selfFailureIds = new Set(['release:parallel-speed-budget', 'release:stability-report']);
|
|
22
|
+
const blockingFailureIds = failureIds.filter((id) => !selfFailureIds.has(id));
|
|
23
|
+
const summaryOk = Number(summary.failed || 0) === 0 || (failureIds.length > 0 && blockingFailureIds.length === 0);
|
|
21
24
|
const report = {
|
|
22
25
|
schema: 'sks.release-speed.v1',
|
|
23
26
|
ok: summaryOk && parallelismOk && (wallOk || warnOnly),
|
|
@@ -34,6 +37,8 @@ const report = {
|
|
|
34
37
|
sum_gate_ms: summary.sum_gate_ms,
|
|
35
38
|
critical_path_ms: summary.critical_path_ms,
|
|
36
39
|
slowest_gates: slowest,
|
|
40
|
+
functional_failure_ids: blockingFailureIds,
|
|
41
|
+
ignored_self_failure_ids: failureIds.filter((id) => selfFailureIds.has(id)),
|
|
37
42
|
target_full_wall_ms: budgetMs,
|
|
38
43
|
target_cached_wall_ms: cachedBudgetMs,
|
|
39
44
|
target_changed_file_wall_ms: 90 * 1000,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const research = await importDist('core/research.js');
|
|
8
|
+
const workGraph = await importDist('core/research/research-work-graph.js');
|
|
9
|
+
const cycleRunner = await importDist('core/research/research-cycle-runner.js');
|
|
10
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-research-blueprint-'));
|
|
11
|
+
const plan = await research.writeResearchPlan(dir, 'blueprint densifier blackbox', { missionId: 'M-BLUEPRINT' });
|
|
12
|
+
const graph = workGraph.buildResearchWorkGraph(plan);
|
|
13
|
+
await cycleRunner.runResearchCycle({ root: process.cwd(), dir, plan, graph, cycle: 1, backend: 'mock', timeoutMs: 120000, maxParallelStages: 4, mock: true });
|
|
14
|
+
const blueprint = JSON.parse(fs.readFileSync(path.join(dir, 'implementation-blueprint.json'), 'utf8'));
|
|
15
|
+
assertGate(blueprint.repository_aware === true, 'blueprint must be repository-aware', blueprint);
|
|
16
|
+
assertGate((blueprint.existing_files || []).length > 0, 'blueprint must list concrete existing files', blueprint);
|
|
17
|
+
assertGate((blueprint.sections || []).length >= 8, 'blueprint must keep required sections', blueprint);
|
|
18
|
+
assertGate((blueprint.test_commands || []).some((cmd) => String(cmd).includes('research:stage-cycle-runtime-blackbox')), 'blueprint must include concrete test commands', blueprint);
|
|
19
|
+
assertGate(fs.existsSync(path.join(dir, 'team-handoff-goal.md')), 'team handoff goal must exist');
|
|
20
|
+
emitGate('research:blueprint-densifier', { dir, sections: blueprint.sections.length, files: blueprint.existing_files.length });
|
|
21
|
+
//# sourceMappingURL=research-blueprint-densifier-check.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const research = await importDist('core/research.js');
|
|
8
|
+
const workGraph = await importDist('core/research/research-work-graph.js');
|
|
9
|
+
const cycleRunner = await importDist('core/research/research-cycle-runner.js');
|
|
10
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-research-claim-builder-'));
|
|
11
|
+
const plan = await research.writeResearchPlan(dir, 'claim builder blackbox', { missionId: 'M-CLAIM-BUILDER' });
|
|
12
|
+
const graph = workGraph.buildResearchWorkGraph(plan);
|
|
13
|
+
await cycleRunner.runResearchCycle({ root: process.cwd(), dir, plan, graph, cycle: 1, backend: 'mock', timeoutMs: 120000, maxParallelStages: 4, mock: true });
|
|
14
|
+
const matrix = JSON.parse(fs.readFileSync(path.join(dir, 'claim-evidence-matrix.json'), 'utf8'));
|
|
15
|
+
assertGate(matrix.key_claim_ids.length >= 8, 'claim builder must produce key claims', matrix);
|
|
16
|
+
assertGate(matrix.triangulated_claim_count >= 6, 'claim builder must triangulate claims', matrix);
|
|
17
|
+
assertGate((matrix.unsupported_claims || []).length === 0, 'claim builder must not leave important claims unsupported in complete fixture', matrix);
|
|
18
|
+
emitGate('research:claim-builder', { dir, key_claims: matrix.key_claim_ids.length, triangulated: matrix.triangulated_claim_count });
|
|
19
|
+
//# sourceMappingURL=research-claim-builder-check.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const research = await importDist('core/research.js');
|
|
8
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-research-complete-package-'));
|
|
9
|
+
const plan = await research.writeResearchPlan(dir, 'complete package fixture blackbox', { missionId: 'M-COMPLETE-PACKAGE' });
|
|
10
|
+
const gate = await research.writeMockResearchResult(dir, plan);
|
|
11
|
+
const metrics = gate.metrics || {};
|
|
12
|
+
assertGate(gate.passed === true, 'complete mock research package must pass', gate);
|
|
13
|
+
assertGate(metrics.report_word_count >= 2200, 'report must satisfy word floor', metrics);
|
|
14
|
+
assertGate(metrics.source_entries_total_with_counterevidence >= 12, 'source count must satisfy contract', metrics);
|
|
15
|
+
assertGate(metrics.source_layers_covered >= 5, 'source layer coverage must satisfy contract', metrics);
|
|
16
|
+
assertGate(metrics.key_claims >= 8, 'key claims must satisfy contract', metrics);
|
|
17
|
+
assertGate(metrics.counterevidence_sources >= 2, 'counterevidence count must satisfy contract', metrics);
|
|
18
|
+
assertGate(metrics.final_review_approved === true, 'static plus mock Codex final review must approve', metrics);
|
|
19
|
+
assertGate(metrics.implementation_blueprint_validation?.ok === true, 'blueprint must validate', metrics);
|
|
20
|
+
assertGate(metrics.experiment_plan_validation?.ok === true, 'experiment plan must validate', metrics);
|
|
21
|
+
assertGate(metrics.replication_pack_validation?.ok === true, 'replication pack must validate', metrics);
|
|
22
|
+
emitGate('research:complete-package-fixture', { dir, metrics });
|
|
23
|
+
//# sourceMappingURL=research-complete-package-fixture-check.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const research = await importDist('core/research.js');
|
|
8
|
+
const reviewer = await importDist('core/research/research-final-reviewer.js');
|
|
9
|
+
const fsx = await importDist('core/fsx.js');
|
|
10
|
+
const badDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-research-final-review-bad-'));
|
|
11
|
+
await research.writeResearchPlan(badDir, 'bad final reviewer fixture', { missionId: 'M-FINAL-BAD' });
|
|
12
|
+
await fsx.writeTextAtomic(path.join(badDir, 'research-report.md'), '# Bad\n\nToo short.\n');
|
|
13
|
+
const bad = await reviewer.runResearchFinalReviewer(badDir, { codexRequired: true });
|
|
14
|
+
assertGate(bad.approved === false, 'static failure must not approve final review', bad);
|
|
15
|
+
const goodDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-research-final-review-good-'));
|
|
16
|
+
const plan = await research.writeResearchPlan(goodDir, 'good final reviewer fixture', { missionId: 'M-FINAL-GOOD' });
|
|
17
|
+
await research.writeMockResearchResult(goodDir, plan);
|
|
18
|
+
const good = JSON.parse(fs.readFileSync(path.join(goodDir, 'research-final-review.json'), 'utf8'));
|
|
19
|
+
assertGate(good.approved === true, 'complete package must approve final review with mock Codex reviewer', good);
|
|
20
|
+
assertGate(good.codex_review?.verdict === 'approve', 'merged final review must include Codex/mock approval', good);
|
|
21
|
+
emitGate('research:final-reviewer-blackbox', { bad_dir: badDir, good_dir: goodDir });
|
|
22
|
+
//# sourceMappingURL=research-final-reviewer-blackbox.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const workGraph = await importDist('core/research/research-work-graph.js');
|
|
5
|
+
const graph = workGraph.buildResearchWorkGraph({ mission_id: 'M-PARALLEL-SHARDS' });
|
|
6
|
+
const shards = graph.work_items.filter((item) => item.stage_kind === 'source_shard');
|
|
7
|
+
const shardIds = new Set(shards.map((item) => item.id));
|
|
8
|
+
const claim = graph.work_items.find((item) => item.id === 'claim_matrix_build');
|
|
9
|
+
const merge = graph.work_items.find((item) => item.id === 'source_ledger_merge');
|
|
10
|
+
assertGate(shards.length >= 8, 'work graph must create source layer shards', { count: shards.length });
|
|
11
|
+
assertGate(shards.some((item) => item.id === 'source_shard_academic_literature'), 'academic source shard missing');
|
|
12
|
+
assertGate(shards.some((item) => item.id === 'source_shard_official_government_data'), 'official government source shard missing');
|
|
13
|
+
assertGate(shards.some((item) => item.id === 'source_shard_standards_primary_docs'), 'standards source shard missing');
|
|
14
|
+
assertGate(shards.some((item) => item.id === 'source_shard_news_current_events'), 'news source shard missing');
|
|
15
|
+
assertGate(shards.some((item) => item.id === 'source_shard_public_discourse'), 'public discourse source shard missing');
|
|
16
|
+
assertGate(shards.some((item) => item.id === 'source_shard_developer_practitioner'), 'developer practitioner source shard missing');
|
|
17
|
+
assertGate(shards.some((item) => item.id === 'source_shard_counterevidence_factcheck'), 'counterevidence source shard missing');
|
|
18
|
+
assertGate(shards.some((item) => item.id === 'source_shard_local_project_evidence'), 'local project evidence source shard missing');
|
|
19
|
+
assertGate(merge && merge.dependencies.every((id) => shardIds.has(id)), 'source merge must depend on every source shard', merge);
|
|
20
|
+
assertGate(claim && [...shardIds].every((id) => claim.dependencies.includes(id)), 'claim matrix must depend on source shards', claim);
|
|
21
|
+
emitGate('research:parallel-source-shards', { shard_count: shards.length });
|
|
22
|
+
//# sourceMappingURL=research-parallel-source-shards-check.js.map
|
|
@@ -36,11 +36,11 @@ const checks = {
|
|
|
36
36
|
assertFileIncludes('src/core/research.ts', ['replication_pack_missing']);
|
|
37
37
|
},
|
|
38
38
|
'final-reviewer': () => {
|
|
39
|
-
assertFileIncludes('src/core/research/research-final-reviewer.ts', ['RESEARCH_FINAL_REVIEW_ARTIFACT', 'approved', 'runResearchFinalReviewer']);
|
|
39
|
+
assertFileIncludes('src/core/research/research-final-reviewer.ts', ['RESEARCH_FINAL_REVIEW_ARTIFACT', 'approved', 'runResearchFinalReviewer', 'runResearchStaticFinalReview', 'runResearchCodexFinalReviewer']);
|
|
40
40
|
assertFileIncludes('src/core/research.ts', ['research_final_review_not_approved']);
|
|
41
41
|
},
|
|
42
42
|
'work-graph': () => {
|
|
43
|
-
assertFileIncludes('src/core/research/research-work-graph.ts', ['RESEARCH_WORK_GRAPH_ARTIFACT', 'buildResearchWorkGraph', 'sks.naruto-work-graph.v1']);
|
|
43
|
+
assertFileIncludes('src/core/research/research-work-graph.ts', ['RESEARCH_WORK_GRAPH_ARTIFACT', 'buildResearchWorkGraph', 'sks.naruto-work-graph.v1', 'RESEARCH_SOURCE_LAYERS', 'source_shard_local_project_evidence']);
|
|
44
44
|
assertFileIncludes('src/core/commands/research-command.ts', ['narutoWorkGraph: researchWorkGraph', 'readonly: true', 'runResearchCycle']);
|
|
45
45
|
},
|
|
46
46
|
'prompt-contract': () => {
|
|
@@ -56,6 +56,10 @@ const checks = {
|
|
|
56
56
|
]);
|
|
57
57
|
assertFileIncludes('src/core/research/falsification.ts', ['falsification_cases_below_contract']);
|
|
58
58
|
},
|
|
59
|
+
'report-quality': () => {
|
|
60
|
+
assertFileIncludes('src/core/research/research-report-quality.ts', ['analyzeResearchReportQuality', 'REQUIRED_RESEARCH_REPORT_HEADINGS', 'research_report_references_missing_source_ids']);
|
|
61
|
+
assertFileIncludes('src/core/research.ts', ['report_word_count', 'report_quality', 'research_report_too_short']);
|
|
62
|
+
},
|
|
59
63
|
'schemas': () => {
|
|
60
64
|
for (const file of [
|
|
61
65
|
'schemas/research/research-quality-contract.schema.json',
|
|
@@ -64,9 +68,30 @@ const checks = {
|
|
|
64
68
|
'schemas/research/implementation-blueprint.schema.json',
|
|
65
69
|
'schemas/research/experiment-plan.schema.json',
|
|
66
70
|
'schemas/research/replication-pack.schema.json',
|
|
67
|
-
'schemas/research/research-final-review.schema.json'
|
|
71
|
+
'schemas/research/research-final-review.schema.json',
|
|
72
|
+
'schemas/research/research-source-shard.schema.json'
|
|
68
73
|
])
|
|
69
74
|
assertGate(readText(file).includes('"$schema"'), `${file} missing JSON Schema header`);
|
|
75
|
+
},
|
|
76
|
+
'stage-cycle-runner': () => {
|
|
77
|
+
assertFileIncludes('src/core/research/research-cycle-runner.ts', ['readyStages', 'Promise.race', 'max_observed_parallel', 'critical_path_length']);
|
|
78
|
+
assertFileIncludes('src/core/research/research-stage-runner.ts', ['ResearchStageResult', 'runSourceShardStage', 'runFinalReviewStage', 'cycle-${input.cycle}', 'stages']);
|
|
79
|
+
},
|
|
80
|
+
'parallel-source-shards': () => {
|
|
81
|
+
assertFileIncludes('src/core/research/research-work-graph.ts', ['source_shard_academic_literature', 'source_shard_official_government_data', 'source_shard_counterevidence_factcheck', 'source_shard_local_project_evidence']);
|
|
82
|
+
assertFileIncludes('src/core/research/research-source-shards.ts', ['ResearchSourceShardOutput', 'validateResearchSourceShardOutput', 'source_shard_empty_without_blocker']);
|
|
83
|
+
},
|
|
84
|
+
'source-ledger-merge': () => {
|
|
85
|
+
assertFileIncludes('src/core/research/research-source-ledger-merge.ts', ['mergeResearchSourceShards', 'source-ledger.json', 'source-quality-report.json', 'dedupeSources']);
|
|
86
|
+
},
|
|
87
|
+
'claim-builder': () => {
|
|
88
|
+
assertFileIncludes('src/core/research/research-claim-builder.ts', ['buildClaimEvidenceMatrixFromSourceShards', 'unsupported_important_claim', 'counterevidence_ids']);
|
|
89
|
+
},
|
|
90
|
+
'blueprint-densifier': () => {
|
|
91
|
+
assertFileIncludes('src/core/research/implementation-blueprint-densifier.ts', ['densifyImplementationBlueprint', 'git', 'ls-files', 'existing_files', 'parallel_work_decomposition']);
|
|
92
|
+
},
|
|
93
|
+
'real-cycle-no-legacy-final-md': () => {
|
|
94
|
+
assertFileIncludes('src/core/commands/research-command.ts', ['--legacy-research-cycle', 'SKS_RESEARCH_LEGACY_CYCLE', 'const cycleResult = await runResearchCycle({', 'legacy_final_md_loop']);
|
|
70
95
|
}
|
|
71
96
|
};
|
|
72
97
|
if (mode === 'all') {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, readText } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const source = readText('src/core/commands/research-command.ts');
|
|
5
|
+
const defaultIndex = source.indexOf('const cycleResult = await runResearchCycle({');
|
|
6
|
+
const legacyIndex = source.indexOf('const legacyResearchCycle');
|
|
7
|
+
const legacyExecIndex = source.indexOf('runCodexExec({');
|
|
8
|
+
assertGate(defaultIndex > 0, 'default research run must call runResearchCycle with object input');
|
|
9
|
+
assertGate(source.includes('--legacy-research-cycle'), 'legacy research cycle flag must exist');
|
|
10
|
+
assertGate(source.includes('SKS_RESEARCH_LEGACY_CYCLE'), 'legacy research cycle env flag must exist');
|
|
11
|
+
assertGate(source.includes('legacy_final_md_loop'), 'legacy final.md loop must be explicitly marked');
|
|
12
|
+
assertGate(legacyExecIndex > legacyIndex, 'runCodexExec final.md path must live after legacy gate');
|
|
13
|
+
emitGate('research:real-cycle-no-legacy-final-md', { defaultIndex, legacyIndex, legacyExecIndex });
|
|
14
|
+
//# sourceMappingURL=research-real-cycle-no-legacy-final-md-check.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const research = await importDist('core/research.js');
|
|
8
|
+
const fsx = await importDist('core/fsx.js');
|
|
9
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-research-short-report-'));
|
|
10
|
+
const plan = await research.writeResearchPlan(dir, 'short report rejection blackbox', { missionId: 'M-SHORT-REPORT' });
|
|
11
|
+
await fsx.writeTextAtomic(path.join(dir, 'research-report.md'), `# Short Report\n\n${Array.from({ length: 300 }, (_unused, index) => `word${index}`).join(' ')}\n`);
|
|
12
|
+
await fsx.writeJsonAtomic(path.join(dir, 'source-ledger.json'), {
|
|
13
|
+
schema_version: 1,
|
|
14
|
+
web_search_passes: 1,
|
|
15
|
+
source_layers: [{ id: 'academic_literature', label: 'Academic literature', required: true, status: 'covered', source_ids: ['short-source-1'], counterevidence_ids: [] }],
|
|
16
|
+
sources: [{
|
|
17
|
+
id: 'short-source-1',
|
|
18
|
+
layer: 'academic_literature',
|
|
19
|
+
kind: 'fixture',
|
|
20
|
+
title: 'One source',
|
|
21
|
+
locator: 'fixture://one',
|
|
22
|
+
publisher_or_author: 'fixture',
|
|
23
|
+
accessed_at: new Date().toISOString(),
|
|
24
|
+
reliability: 'low',
|
|
25
|
+
credibility: 'thin',
|
|
26
|
+
stance: 'supports',
|
|
27
|
+
claim_ids: ['short-claim-1'],
|
|
28
|
+
notes: 'Only one source should not satisfy the research quality contract.'
|
|
29
|
+
}],
|
|
30
|
+
counterevidence_sources: [],
|
|
31
|
+
triangulation: { cross_layer_checks: [], conflicts: [], synthesis_notes: [] },
|
|
32
|
+
citation_coverage: { all_key_claims_cited: false, key_claim_ids: ['short-claim-1'], cited_claim_ids: ['short-claim-1'], uncited_claim_ids: [], source_claim_map: { 'short-source-1': ['short-claim-1'] } },
|
|
33
|
+
blockers: []
|
|
34
|
+
});
|
|
35
|
+
await fsx.writeJsonAtomic(path.join(dir, 'claim-evidence-matrix.json'), { schema: 'sks.claim-evidence-matrix.v1', mission_id: plan.mission_id, claims: [], key_claim_ids: [], unsupported_claims: [], triangulated_claim_count: 0, blockers: [] });
|
|
36
|
+
await fsx.writeJsonAtomic(path.join(dir, 'implementation-blueprint.json'), { schema: 'sks.research-implementation-blueprint.v1', sections: [] });
|
|
37
|
+
await fsx.rmrf(path.join(dir, 'research-final-review.codex.json'));
|
|
38
|
+
const gate = await research.evaluateResearchGate(dir);
|
|
39
|
+
const reasons = new Set(gate.reasons || []);
|
|
40
|
+
assertGate(gate.passed === false, 'summary-only package must be blocked', gate);
|
|
41
|
+
for (const reason of ['research_report_too_short', 'source_entries_below_research_quality_contract', 'key_claims_below_contract', 'research_final_review_not_approved']) {
|
|
42
|
+
assertGate(reasons.has(reason), `missing rejection reason: ${reason}`, gate);
|
|
43
|
+
}
|
|
44
|
+
assertGate(reasons.has('implementation_blueprint_incomplete_sections') || reasons.has('implementation_blueprint_missing') || reasons.has('implementation_blueprint_sections_below_contract'), 'missing blueprint rejection reason', gate);
|
|
45
|
+
emitGate('research:short-report-rejection', { dir, reasons: gate.reasons });
|
|
46
|
+
//# sourceMappingURL=research-short-report-rejection-check.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const research = await importDist('core/research.js');
|
|
8
|
+
const shards = await importDist('core/research/research-source-shards.js');
|
|
9
|
+
const merge = await importDist('core/research/research-source-ledger-merge.js');
|
|
10
|
+
const fsx = await importDist('core/fsx.js');
|
|
11
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-research-source-merge-'));
|
|
12
|
+
const plan = await research.writeResearchPlan(dir, 'source ledger merge blackbox', { missionId: 'M-SOURCE-MERGE' });
|
|
13
|
+
const shardDir = path.join(dir, 'research', 'cycle-1', 'source-shards');
|
|
14
|
+
await fsx.ensureDir(shardDir);
|
|
15
|
+
for (const layer of shards.RESEARCH_SOURCE_LAYERS) {
|
|
16
|
+
await fsx.writeJsonAtomic(path.join(shardDir, `${layer.id}.json`), shards.defaultResearchSourceShardOutput(plan, layer, 1));
|
|
17
|
+
}
|
|
18
|
+
const result = await merge.mergeResearchSourceShards({ dir, cycle: 1, plan });
|
|
19
|
+
const ledger = JSON.parse(fs.readFileSync(path.join(dir, 'source-ledger.json'), 'utf8'));
|
|
20
|
+
assertGate(result.ok === true, 'source shard merge must pass', result);
|
|
21
|
+
assertGate(result.source_count >= 12, 'source merge must preserve enough source rows', result);
|
|
22
|
+
assertGate(result.layer_count >= 8, 'source merge must cover source shard layers', result);
|
|
23
|
+
assertGate(ledger.citation_coverage?.all_key_claims_cited === true, 'source merge must update citation coverage', ledger.citation_coverage);
|
|
24
|
+
assertGate(fs.existsSync(path.join(dir, 'source-quality-report.json')), 'source-quality-report must be updated');
|
|
25
|
+
emitGate('research:source-ledger-merge', { dir, source_count: result.source_count, layer_count: result.layer_count });
|
|
26
|
+
//# sourceMappingURL=research-source-ledger-merge-check.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const research = await importDist('core/research.js');
|
|
8
|
+
const workGraph = await importDist('core/research/research-work-graph.js');
|
|
9
|
+
const cycleRunner = await importDist('core/research/research-cycle-runner.js');
|
|
10
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-research-stage-cycle-'));
|
|
11
|
+
const plan = await research.writeResearchPlan(dir, 'stage cycle runtime blackbox', { missionId: 'M-STAGE-RUNTIME' });
|
|
12
|
+
const graph = workGraph.buildResearchWorkGraph(plan);
|
|
13
|
+
const result = await cycleRunner.runResearchCycle({ root: process.cwd(), dir, plan, graph, cycle: 1, backend: 'mock', timeoutMs: 120000, maxParallelStages: 4, mock: true });
|
|
14
|
+
const shardDir = path.join(dir, 'research', 'cycle-1', 'source-shards');
|
|
15
|
+
const shardFiles = fs.readdirSync(shardDir).filter((file) => file.endsWith('.json'));
|
|
16
|
+
assertGate(result.status === 'passed', 'mock stage cycle must pass', result);
|
|
17
|
+
assertGate(shardFiles.length >= 8, 'source shard outputs must exist', { shardFiles });
|
|
18
|
+
assertGate(fs.existsSync(path.join(dir, 'source-ledger.json')), 'source-ledger merge must exist');
|
|
19
|
+
assertGate(fs.existsSync(path.join(dir, 'claim-evidence-matrix.json')), 'claim matrix must exist');
|
|
20
|
+
assertGate(fs.existsSync(path.join(dir, 'implementation-blueprint.json')), 'blueprint must exist');
|
|
21
|
+
assertGate(fs.existsSync(path.join(dir, 'research-final-review.json')), 'final review must exist');
|
|
22
|
+
assertGate(result.parallelism?.max_observed_parallel >= 2, 'source shards must execute with observed parallelism', result.parallelism);
|
|
23
|
+
emitGate('research:stage-cycle-runtime-blackbox', { dir, parallelism: result.parallelism, shard_count: shardFiles.length });
|
|
24
|
+
//# sourceMappingURL=research-stage-cycle-runtime-blackbox.js.map
|