sneakoscope 4.2.0 → 4.4.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 +9 -8
- 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/bin/sks.js +1 -1
- package/dist/cli/command-registry.js +2 -1
- package/dist/cli/ultra-search-command.js +163 -0
- package/dist/cli/xai-command.js +28 -168
- package/dist/core/agents/agent-codex-cockpit.js +3 -3
- package/dist/core/agents/agent-wrongness.js +1 -1
- package/dist/core/codex-control/codex-app-server-v2-client.js +86 -2
- package/dist/core/codex-control/codex-reliability-shield.js +26 -5
- package/dist/core/codex-control/codex-task-runner.js +7 -1
- package/dist/core/codex-control/model-call-concurrency.js +1 -1
- package/dist/core/commands/qa-loop-command.js +23 -7
- package/dist/core/fsx.js +1 -1
- package/dist/core/hooks-runtime.js +1 -1
- package/dist/core/qa-loop/qa-app-server-driver.js +134 -0
- package/dist/core/qa-loop/qa-contract-v2.js +231 -0
- package/dist/core/qa-loop/qa-gate-v2.js +132 -0
- package/dist/core/qa-loop/qa-runtime-artifacts.js +53 -0
- package/dist/core/qa-loop/qa-surface-router.js +114 -0
- package/dist/core/qa-loop/qa-types.js +18 -0
- package/dist/core/qa-loop.js +83 -26
- package/dist/core/release/gate-manifest.js +1 -0
- package/dist/core/release/sla-scheduler.js +1 -1
- package/dist/core/release-parallel-full-coverage.js +1 -1
- package/dist/core/routes.js +22 -6
- package/dist/core/source-intelligence/source-intelligence-policy.js +45 -26
- package/dist/core/source-intelligence/source-intelligence-proof.js +10 -16
- package/dist/core/source-intelligence/source-intelligence-runner.js +56 -42
- package/dist/core/triwiki/triwiki-affected-graph.js +3 -2
- package/dist/core/trust-kernel/trust-report.js +3 -5
- package/dist/core/ultra-search/index.js +3 -0
- package/dist/core/ultra-search/runtime.js +502 -0
- package/dist/core/ultra-search/types.js +3 -0
- package/dist/core/version.js +1 -1
- package/dist/scripts/agent-visual-consistency-check.js +1 -1
- package/dist/scripts/codex-control-all-pipelines-check.js +1 -0
- package/dist/scripts/codex-control-model-capacity-fallback-check.js +53 -0
- package/dist/scripts/config-managed-merge-callsite-coverage-check.js +7 -1
- package/dist/scripts/loop-directive-check-lib.js +78 -1
- package/dist/scripts/qa-loop-app-server-driver-check.js +74 -0
- package/dist/scripts/qa-loop-surface-router-check.js +49 -0
- package/dist/scripts/release-check-dynamic-execute.js +1 -1
- package/dist/scripts/release-metadata-1-19-check.js +2 -2
- package/dist/scripts/release-parallel-check.js +2 -2
- package/dist/scripts/release-parallel-full-coverage-check.js +1 -1
- package/dist/scripts/release-readiness-report.js +6 -6
- package/dist/scripts/runtime-ts-rust-boundary-check.js +1 -1
- package/dist/scripts/sks-1-18-gate-lib.js +2 -2
- package/dist/scripts/source-intelligence-all-modes-check.js +9 -19
- package/dist/scripts/source-intelligence-policy-check.js +6 -6
- package/dist/scripts/triwiki-affected-graph-check.js +2 -2
- package/dist/scripts/ultra-search-provider-interface-check.js +27 -0
- package/package.json +7 -4
- package/dist/core/mcp/xai-mcp-detector.js +0 -157
- package/dist/core/mcp/xai-search-adapter.js +0 -100
- package/dist/scripts/xai-mcp-capability-check.js +0 -14
package/dist/core/qa-loop.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { exists, nowIso, readJson, readText, writeJsonAtomic, writeTextAtomic, PACKAGE_VERSION } from './fsx.js';
|
|
3
|
-
import { CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_IMAGEGEN_REQUIRED_POLICY, CODEX_WEB_VERIFICATION_EVIDENCE_SOURCE, CODEX_WEB_VERIFICATION_POLICY, evidenceMentionsForbiddenBrowserAutomation, evidenceMentionsForbiddenWebComputerUseEvidence } from './routes.js';
|
|
3
|
+
import { CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_CHROME_EXTENSION_EVIDENCE_SOURCE, CODEX_COMPUTER_USE_EVIDENCE_SOURCE, CODEX_IMAGEGEN_REQUIRED_POLICY, CODEX_IN_APP_BROWSER_EVIDENCE_SOURCE, CODEX_WEB_VERIFICATION_EVIDENCE_SOURCE, CODEX_WEB_VERIFICATION_POLICY, evidenceMentionsForbiddenBrowserAutomation, evidenceMentionsForbiddenWebComputerUseEvidence } from './routes.js';
|
|
4
4
|
import { appendAgentLedgerEvent, initializeAgentCentralLedger } from './agents/agent-central-ledger.js';
|
|
5
5
|
import { resolveCodexAppExecutionProfile } from './codex-app/codex-app-execution-profile.js';
|
|
6
6
|
import { resolveCodexNativeInvocationPlan } from './codex-native/codex-native-invocation-router.js';
|
|
7
7
|
import { imageDimensions, sha256File } from './wiki-image/image-hash.js';
|
|
8
|
+
import { initializeQaRuntimeArtifacts } from './qa-loop/qa-runtime-artifacts.js';
|
|
9
|
+
import { evaluateQaGateV2 } from './qa-loop/qa-gate-v2.js';
|
|
10
|
+
import { DEFAULT_QA_MAX_CYCLES, QA_GATE_V2_ARTIFACT, QA_SURFACE_SELECTION_ARTIFACT } from './qa-loop/qa-types.js';
|
|
8
11
|
export const QA_LOOP_ROUTE = 'QALoop';
|
|
9
12
|
export const QA_LOOP_VISUAL_EVIDENCE_ARTIFACT = 'qa-loop/visual-evidence.json';
|
|
10
13
|
const QA_REPORT_SUFFIX = 'qa-report.md';
|
|
11
|
-
const
|
|
14
|
+
const UI_SURFACE_ROUTER_ACK = 'use_codex_surface_router_browser_chrome_computer_no_synthetic_evidence';
|
|
15
|
+
const LEGACY_UI_CHROME_EXTENSION_FIRST_ACK = 'use_codex_chrome_extension_first_no_computer_use_for_web_ui_or_mark_unverified';
|
|
12
16
|
const GPT_IMAGE_2_ANNOTATED_REVIEW_REQUIRED_ACK = 'yes_gpt_image_2_annotated_review';
|
|
13
17
|
const IMAGE_FILE_RE = /\.(png|jpe?g|webp|gif)$/i;
|
|
14
18
|
export const QA_NATIVE_AGENT_PERSONAS = Object.freeze([
|
|
@@ -166,7 +170,7 @@ export function inferQaLoopAnswers(prompt = '') {
|
|
|
166
170
|
'검증하지 못한 UI/API 범위는 통과로 주장하지 않고 QA 리포트에 남긴다.'
|
|
167
171
|
];
|
|
168
172
|
if (isUiScope(scope))
|
|
169
|
-
acceptance.push('UI E2E 통과 증거는
|
|
173
|
+
acceptance.push('UI E2E 통과 증거는 surface router가 고른 @Browser/@Chrome/@Computer 실제 action·observation ledger와 필요한 screenshot/hash를 기록해야 한다.');
|
|
170
174
|
if (wantsGptImage2Review)
|
|
171
175
|
acceptance.push('gpt-image-2 annotated review image가 필요한 경우 실제 Codex App $imagegen/gpt-image-2 출력 파일 path, sha256, model, provider를 기록해야 한다.');
|
|
172
176
|
return {
|
|
@@ -181,17 +185,17 @@ export function inferQaLoopAnswers(prompt = '') {
|
|
|
181
185
|
EXTERNAL_SIDE_EFFECT_POLICY: 'block_all_external_side_effects',
|
|
182
186
|
...login,
|
|
183
187
|
CREDENTIAL_STORAGE_ACK: 'never_store_credentials_in_artifacts_or_wiki',
|
|
184
|
-
UI_CHROME_EXTENSION_ACK:
|
|
188
|
+
UI_CHROME_EXTENSION_ACK: UI_SURFACE_ROUTER_ACK,
|
|
185
189
|
QA_VISUAL_REVIEW_IMAGEGEN_REQUIRED: wantsGptImage2Review ? GPT_IMAGE_2_ANNOTATED_REVIEW_REQUIRED_ACK : 'not_required',
|
|
186
190
|
TEAM_MODE_ALLOWED: 'no_parent_only',
|
|
187
|
-
MAX_QA_CYCLES:
|
|
191
|
+
MAX_QA_CYCLES: String(DEFAULT_QA_MAX_CYCLES),
|
|
188
192
|
ACCEPTANCE_CRITERIA: acceptance,
|
|
189
193
|
NON_GOALS: [
|
|
190
194
|
'결제, 실제 이메일/SMS 발송, 관리자 권한 변경, 데이터 삭제, 프로덕션 데이터 변경은 테스트하지 않는다.'
|
|
191
195
|
],
|
|
192
196
|
RISK_BOUNDARY: [
|
|
193
197
|
'실제 사용자 데이터, 인증 권한, 결제, 메시지 발송, 웹훅, 외부 서비스 상태를 생성/수정/삭제하지 않는다.',
|
|
194
|
-
'Codex
|
|
198
|
+
'선택된 Codex App visual surface의 실제 action·observation evidence가 없으면 UI 검증 완료로 주장하지 않는다.',
|
|
195
199
|
'로그인이 필요하지만 임시 테스트 자격증명이 없으면 인증 구간은 차단/미검증으로 기록한다.'
|
|
196
200
|
],
|
|
197
201
|
MID_RUN_UNKNOWN_POLICY: ['preserve_existing_behavior', 'defer_optional_scope', 'block_only_if_no_safe_path']
|
|
@@ -245,7 +249,7 @@ export function qaLoopQuestionSlots() {
|
|
|
245
249
|
{ id: 'TEMP_TEST_CREDENTIALS_READY', question: 'If login is required, are test-only credentials ready to provide ephemerally during the run?', required: true, type: 'enum', options: ['not_required', 'yes_temp_only', 'no_block_authenticated_tests'] },
|
|
246
250
|
{ id: 'TEST_CREDENTIALS_RUNTIME_SOURCE', question: 'If login is required, how will test-only credentials be provided without saving the values?', required: true, type: 'enum', options: ['not_required', 'ephemeral_chat_only', 'environment_variables', 'secret_manager'] },
|
|
247
251
|
{ id: 'CREDENTIAL_STORAGE_ACK', question: 'Acknowledge credential handling policy.', required: true, type: 'enum', options: ['never_store_credentials_in_artifacts_or_wiki'] },
|
|
248
|
-
{ id: 'UI_CHROME_EXTENSION_ACK', question: 'Acknowledge UI E2E evidence policy:
|
|
252
|
+
{ id: 'UI_CHROME_EXTENSION_ACK', question: 'Acknowledge UI E2E evidence policy: QA-LOOP routes local/public web to @Browser, signed-in web to @Chrome, native/cross-app GUI to @Computer, and never treats synthetic artifacts as real proof.', required: true, type: 'enum', options: [UI_SURFACE_ROUTER_ACK, LEGACY_UI_CHROME_EXTENSION_FIRST_ACK] },
|
|
249
253
|
{ id: 'TEAM_MODE_ALLOWED', question: 'May QA-LOOP use Team/subagents where useful?', required: true, type: 'enum', options: ['yes_parallel_where_safe', 'no_parent_only'] },
|
|
250
254
|
{ id: 'MAX_QA_CYCLES', question: 'How many no-question QA cycles are allowed before pausing?', required: true, type: 'string' },
|
|
251
255
|
{ id: 'ACCEPTANCE_CRITERIA', question: 'List the QA completion criteria.', required: true, type: 'array_or_string' },
|
|
@@ -269,8 +273,8 @@ export function validateQaLoopAnswers(schema, answers = {}) {
|
|
|
269
273
|
errors.push({ slot: 'QA_MUTATION_POLICY', error: 'production_deployed_qa_is_read_only_smoke_only' });
|
|
270
274
|
if (answers.DESTRUCTIVE_DEPLOYED_TESTS_ALLOWED !== 'never')
|
|
271
275
|
errors.push({ slot: 'DESTRUCTIVE_DEPLOYED_TESTS_ALLOWED', error: 'destructive_deployed_tests_never_allowed' });
|
|
272
|
-
if (isUiScope(answers.QA_SCOPE) && answers.UI_CHROME_EXTENSION_ACK
|
|
273
|
-
errors.push({ slot: 'UI_CHROME_EXTENSION_ACK', error: '
|
|
276
|
+
if (isUiScope(answers.QA_SCOPE) && ![UI_SURFACE_ROUTER_ACK, LEGACY_UI_CHROME_EXTENSION_FIRST_ACK].includes(answers.UI_CHROME_EXTENSION_ACK))
|
|
277
|
+
errors.push({ slot: 'UI_CHROME_EXTENSION_ACK', error: 'ui_e2e_requires_codex_surface_router_ack' });
|
|
274
278
|
if (answers.LOGIN_REQUIRED === 'yes' && !['yes_temp_only', 'no_block_authenticated_tests'].includes(answers.TEMP_TEST_CREDENTIALS_READY))
|
|
275
279
|
errors.push({ slot: 'TEMP_TEST_CREDENTIALS_READY', error: 'authenticated_tests_require_ephemeral_test_credentials_or_must_be_blocked' });
|
|
276
280
|
if (answers.LOGIN_REQUIRED === 'yes' && answers.TEMP_TEST_CREDENTIALS_READY === 'yes_temp_only' && answers.TEST_CREDENTIALS_RUNTIME_SOURCE === 'not_required')
|
|
@@ -322,6 +326,7 @@ export function defaultQaGate(contract = {}, opts = {}) {
|
|
|
322
326
|
const gptImage2ReviewRequired = qaGptImage2AnnotatedReviewRequired(contract, contract.prompt);
|
|
323
327
|
const reportFile = opts.reportFile || qaReportFilename();
|
|
324
328
|
const corrective = a.QA_CORRECTIVE_POLICY !== 'report_only_no_code_changes';
|
|
329
|
+
const selectedSurface = opts.qaRuntime?.surface?.selected_surface || null;
|
|
325
330
|
return {
|
|
326
331
|
passed: false,
|
|
327
332
|
clarification_contract_sealed: Boolean(contract.sealed_hash),
|
|
@@ -333,6 +338,15 @@ export function defaultQaGate(contract = {}, opts = {}) {
|
|
|
333
338
|
deployed_destructive_tests_blocked: a.TARGET_ENVIRONMENT === 'local_dev_server' || a.DESTRUCTIVE_DEPLOYED_TESTS_ALLOWED === 'never',
|
|
334
339
|
credentials_not_persisted: false,
|
|
335
340
|
ui_e2e_required: uiRequired,
|
|
341
|
+
qa_contract_v2_required: opts.qaRuntime ? true : false,
|
|
342
|
+
qa_surface_selection_artifact: opts.qaRuntime ? QA_SURFACE_SELECTION_ARTIFACT : null,
|
|
343
|
+
qa_gate_v2_artifact: opts.qaRuntime ? QA_GATE_V2_ARTIFACT : null,
|
|
344
|
+
qa_surface_selected: selectedSurface,
|
|
345
|
+
ui_selected_surface: selectedSurface,
|
|
346
|
+
ui_live_surface_preflight_passed: !uiRequired,
|
|
347
|
+
ui_real_action_count: 0,
|
|
348
|
+
ui_observation_count: 0,
|
|
349
|
+
same_flow_replay_complete: false,
|
|
336
350
|
chrome_extension_preflight_passed: !uiRequired,
|
|
337
351
|
ui_chrome_extension_evidence: !uiRequired,
|
|
338
352
|
ui_computer_use_evidence: false,
|
|
@@ -385,6 +399,13 @@ export async function writeQaLoopArtifacts(dir, mission, contract) {
|
|
|
385
399
|
const root = missionRootFromDir(dir);
|
|
386
400
|
const executionProfile = root ? await resolveCodexAppExecutionProfile({ root }).catch(() => null) : null;
|
|
387
401
|
const codexNativeInvocation = root ? await resolveQaCodexNativeInvocation(root, mission.id).catch(() => null) : null;
|
|
402
|
+
const qaRuntime = await initializeQaRuntimeArtifacts(dir, {
|
|
403
|
+
...contract,
|
|
404
|
+
prompt: mission.prompt || contract.prompt,
|
|
405
|
+
mission_id: mission.id || contract.mission_id
|
|
406
|
+
}, {
|
|
407
|
+
missionId: mission.id || contract.mission_id || null
|
|
408
|
+
}).catch(() => null);
|
|
388
409
|
if (executionProfile)
|
|
389
410
|
await writeJsonAtomic(path.join(dir, 'qa-loop', 'execution-profile.json'), executionProfile).catch(() => undefined);
|
|
390
411
|
if (codexNativeInvocation)
|
|
@@ -397,11 +418,20 @@ export async function writeQaLoopArtifacts(dir, mission, contract) {
|
|
|
397
418
|
codex_app_execution_profile: executionProfile ? compactExecutionProfile(executionProfile) : null,
|
|
398
419
|
codex_native_invocation: codexNativeInvocation,
|
|
399
420
|
target: { scope: a.QA_SCOPE, environment: a.TARGET_ENVIRONMENT, base_url: a.TARGET_BASE_URL, api_base_url: a.API_BASE_URL },
|
|
400
|
-
|
|
421
|
+
qa_runtime_v2: qaRuntime ? {
|
|
422
|
+
contract_artifact: 'qa-loop/qa-contract-v2.json',
|
|
423
|
+
surface_selection_artifact: QA_SURFACE_SELECTION_ARTIFACT,
|
|
424
|
+
selected_surface: qaRuntime.surface.selected_surface,
|
|
425
|
+
journey_graph_artifact: 'qa-loop/qa-journey-graph.json',
|
|
426
|
+
gate_artifact: QA_GATE_V2_ARTIFACT
|
|
427
|
+
} : null,
|
|
428
|
+
safety: { mutation_policy: a.QA_MUTATION_POLICY, deployed_destructive_tests_allowed: 'never', credentials: 'temp_only_never_saved', ui_evidence: 'codex_surface_router_live_action_required_for_ui_e2e', visual_review: 'gpt_image_2_annotated_review_required_when_contract_requests_it' },
|
|
401
429
|
checklist
|
|
402
430
|
});
|
|
403
431
|
await writeJsonAtomic(path.join(dir, QA_LOOP_VISUAL_EVIDENCE_ARTIFACT), buildQaLoopVisualEvidenceArtifact(mission, contract));
|
|
404
|
-
await writeJsonAtomic(path.join(dir, 'qa-gate.json'), defaultQaGate(contract, { reportFile, executionProfile, codexNativeInvocation }));
|
|
432
|
+
await writeJsonAtomic(path.join(dir, 'qa-gate.json'), defaultQaGate(contract, { reportFile, executionProfile, codexNativeInvocation, qaRuntime }));
|
|
433
|
+
if (qaRuntime)
|
|
434
|
+
await evaluateQaGateV2(dir).catch(() => undefined);
|
|
405
435
|
await writeTextAtomic(path.join(dir, reportFile), qaReportTemplate(mission, contract, checklist));
|
|
406
436
|
return { checklist_count: checklist.length, report_file: reportFile };
|
|
407
437
|
}
|
|
@@ -441,8 +471,18 @@ export async function ensureQaLoopVisualEvidenceContract(dir, mission = {}, cont
|
|
|
441
471
|
}
|
|
442
472
|
export async function evaluateQaGate(dir) {
|
|
443
473
|
const gate = await readJson(path.join(dir, 'qa-gate.json'), {});
|
|
474
|
+
const surfaceSelection = await readJson(path.join(dir, QA_SURFACE_SELECTION_ARTIFACT), null);
|
|
475
|
+
const selectedSurface = gate.ui_selected_surface || gate.qa_surface_selected || surfaceSelection?.selected_surface || null;
|
|
476
|
+
const expectedEvidenceSource = evidenceSourceForSurface(selectedSurface);
|
|
477
|
+
const gateV2 = gate.qa_contract_v2_required === true ? await evaluateQaGateV2(dir).catch((err) => ({
|
|
478
|
+
passed: false,
|
|
479
|
+
blockers: [`qa_gate_v2_evaluation_failed:${err?.message || String(err)}`],
|
|
480
|
+
unverified: []
|
|
481
|
+
})) : null;
|
|
444
482
|
const reportFile = qaReportFileFromGate(gate);
|
|
445
483
|
const reasons = [];
|
|
484
|
+
if (gateV2 && gateV2.passed !== true)
|
|
485
|
+
reasons.push(...(gateV2.blockers || []));
|
|
446
486
|
for (const key of ['clarification_contract_sealed', 'qa_report_written', 'qa_ledger_complete', 'checklist_completed', 'safety_reviewed', 'deployed_destructive_tests_blocked', 'credentials_not_persisted', 'honest_mode_complete']) {
|
|
447
487
|
if (gate[key] !== true)
|
|
448
488
|
reasons.push(`${key}_missing`);
|
|
@@ -460,17 +500,22 @@ export async function evaluateQaGate(dir) {
|
|
|
460
500
|
if (gate.unsafe_external_side_effects === true)
|
|
461
501
|
reasons.push('unsafe_external_side_effects');
|
|
462
502
|
if (gate.ui_e2e_required === true) {
|
|
463
|
-
if (
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
503
|
+
if (!selectedSurface || selectedSurface === 'codex_chrome_extension') {
|
|
504
|
+
if (gate.chrome_extension_preflight_passed !== true)
|
|
505
|
+
reasons.push('chrome_extension_preflight_missing');
|
|
506
|
+
if (gate.ui_chrome_extension_evidence !== true)
|
|
507
|
+
reasons.push('ui_chrome_extension_evidence_missing');
|
|
508
|
+
}
|
|
509
|
+
else if (gate.ui_live_surface_preflight_passed !== true) {
|
|
510
|
+
reasons.push('ui_live_surface_preflight_missing');
|
|
511
|
+
}
|
|
512
|
+
if (gate.ui_computer_use_evidence === true && selectedSurface !== 'codex_computer_use')
|
|
468
513
|
reasons.push('ui_computer_use_evidence_forbidden_for_web');
|
|
469
|
-
if (gate.ui_evidence_source !==
|
|
470
|
-
reasons.push(
|
|
514
|
+
if (expectedEvidenceSource && gate.ui_evidence_source !== expectedEvidenceSource)
|
|
515
|
+
reasons.push(`ui_evidence_source_not_${expectedEvidenceSource}`);
|
|
471
516
|
if (evidenceMentionsForbiddenBrowserAutomation({ evidence: gate.evidence, notes: gate.notes, ui_evidence_source: gate.ui_evidence_source }))
|
|
472
517
|
reasons.push('forbidden_browser_automation_evidence');
|
|
473
|
-
if (evidenceMentionsForbiddenWebComputerUseEvidence({ evidence: gate.evidence, ui_evidence_source: gate.ui_evidence_source }))
|
|
518
|
+
if (selectedSurface !== 'codex_computer_use' && evidenceMentionsForbiddenWebComputerUseEvidence({ evidence: gate.evidence, ui_evidence_source: gate.ui_evidence_source }))
|
|
474
519
|
reasons.push('computer_use_web_evidence_forbidden');
|
|
475
520
|
reasons.push(...await missingQaLoopVisualEvidence(dir, gate));
|
|
476
521
|
}
|
|
@@ -502,7 +547,7 @@ export async function evaluateQaGate(dir) {
|
|
|
502
547
|
reasons.push('qa_ledger_missing');
|
|
503
548
|
const uniqueReasons = [...new Set(reasons)];
|
|
504
549
|
const passed = gate.passed === true && uniqueReasons.length === 0;
|
|
505
|
-
const result = { checked_at: nowIso(), passed, reasons: uniqueReasons, gate };
|
|
550
|
+
const result = { checked_at: nowIso(), passed, reasons: uniqueReasons, gate, gate_v2: gateV2 };
|
|
506
551
|
await writeJsonAtomic(path.join(dir, 'qa-gate.evaluated.json'), result);
|
|
507
552
|
return result;
|
|
508
553
|
}
|
|
@@ -592,9 +637,9 @@ CONTRACT:
|
|
|
592
637
|
${JSON.stringify(contract, null, 2)}
|
|
593
638
|
${imageContractText}${appHandoffText}${executionProfileText}
|
|
594
639
|
VISUAL EVIDENCE CONTRACT:
|
|
595
|
-
- For
|
|
596
|
-
- If decision-contract.json answers set QA_VISUAL_REVIEW_IMAGEGEN_REQUIRED=${GPT_IMAGE_2_ANNOTATED_REVIEW_REQUIRED_ACK}, use Codex App $imagegen/gpt-image-2 (${CODEX_APP_IMAGE_GENERATION_DOC_URL}) to produce a real generated annotated review image from the
|
|
597
|
-
- Do not substitute prose-only critique, Playwright/Selenium/Puppeteer
|
|
640
|
+
- For UI QA, do not mark live UI evidence true unless qa-loop/qa-surface-selection.json selected the correct @Browser/@Chrome/@Computer surface and action/observation ledgers record real user-like actions.
|
|
641
|
+
- If decision-contract.json answers set QA_VISUAL_REVIEW_IMAGEGEN_REQUIRED=${GPT_IMAGE_2_ANNOTATED_REVIEW_REQUIRED_ACK}, use Codex App $imagegen/gpt-image-2 (${CODEX_APP_IMAGE_GENERATION_DOC_URL}) to produce a real generated annotated review image from the selected-surface source screenshot. Record its path, sha256, model=gpt-image-2, provider=Codex App $imagegen, and source_screenshot_artifact in ${QA_LOOP_VISUAL_EVIDENCE_ARTIFACT} and qa-gate.json.
|
|
642
|
+
- Do not substitute prose-only critique, Playwright/Selenium/Puppeteer screenshots, static screenshots, plugin cache, placeholder images, fake fixtures, or direct API fallback as full UI visual evidence.
|
|
598
643
|
Previous tail:
|
|
599
644
|
${String(previous || '').slice(-2500)}
|
|
600
645
|
`;
|
|
@@ -623,7 +668,7 @@ function qaChecklist(a) {
|
|
|
623
668
|
['preflight.roles', 'Map roles, permissions, protected areas.']
|
|
624
669
|
];
|
|
625
670
|
if (qaUiRequired(a))
|
|
626
|
-
cases.push(['ui.
|
|
671
|
+
cases.push(['ui.surface_router', CODEX_WEB_VERIFICATION_POLICY], ['ui.navigation', 'Check primary navigation, deep links, back/forward, refresh, and protected routes.'], ['ui.auth', 'Check login, logout, session expiry, unauthorized access, and role-specific visibility.'], ['ui.forms', 'Check required fields, validation, disabled states, success, and failure.'], ['ui.states', 'Check loading, empty, error, retry, offline/timeout, and slow network states.'], ['ui.crud', 'Check allowed create/change flows and block forbidden destructive flows by environment.'], ['ui.responsive', 'Check desktop, tablet, mobile, overflow, long text, and keyboard focus order.'], ['ui.a11y', 'Check labels, focus traps, modals, contrast-sensitive controls, and screen-reader names.'], ['ui.visual', 'Capture evidence for meaningful UI regressions without storing secrets.']);
|
|
627
672
|
if (qaApiRequired(a))
|
|
628
673
|
cases.push(['api.health', 'Check health/version/readiness endpoints when available.'], ['api.auth', 'Check anonymous, authenticated, expired, and wrong-role access.'], ['api.contract', 'Check status codes, response shape, headers, content type, and error format.'], ['api.validation', 'Check missing, malformed, boundary, duplicate, and over-limit payloads.'], ['api.listing', 'Check pagination, sorting, filters, search, and empty results.'], ['api.mutation', 'Check allowed seeded create/change and forbid deployed destructive flows.'], ['api.idempotency', 'Check retry/idempotency behavior for safe operations.'], ['api.concurrency', 'Check stale change, conflict, and double-submit behavior.'], ['api.failure', 'Check timeout, upstream error, rate-limit, and rollback-visible failure paths.'], ['api.security', 'Check CORS, auth headers, PII redaction, and permission boundaries.']);
|
|
629
674
|
cases.push(['report.evidence', 'Record pass/fail/blocked/skipped with evidence.'], ['report.corrective_loop', 'Record fixes, rechecks, unresolved findings, deferred blockers.'], ['report.honest', 'Run Honest Mode.']);
|
|
@@ -675,6 +720,8 @@ async function missingQaLoopVisualEvidence(dir, gate = {}) {
|
|
|
675
720
|
const visual = await readJson(path.join(dir, QA_LOOP_VISUAL_EVIDENCE_ARTIFACT), null);
|
|
676
721
|
const reasons = [];
|
|
677
722
|
const uiRequired = gate.ui_e2e_required === true;
|
|
723
|
+
const selectedSurface = gate.ui_selected_surface || gate.qa_surface_selected || (gate.ui_chrome_extension_evidence === true ? 'codex_chrome_extension' : null);
|
|
724
|
+
const expectedSource = evidenceSourceForSurface(selectedSurface) || CODEX_WEB_VERIFICATION_EVIDENCE_SOURCE;
|
|
678
725
|
if (uiRequired) {
|
|
679
726
|
const screenshot = visual?.chrome_extension_screenshot || {};
|
|
680
727
|
if (gate.ui_chrome_extension_screenshot_captured !== true && !positiveVisualStatus(screenshot.status, ['captured', 'attached', 'verified']))
|
|
@@ -690,8 +737,8 @@ async function missingQaLoopVisualEvidence(dir, gate = {}) {
|
|
|
690
737
|
else
|
|
691
738
|
reasons.push(...await imageEvidenceFileReasons(dir, screenshotPath, screenshotSha, 'ui_chrome_extension_screenshot', screenshotDims));
|
|
692
739
|
const screenshotSource = firstNonEmpty(gate.ui_chrome_extension_screenshot_source, screenshot.evidence_source, gate.ui_evidence_source);
|
|
693
|
-
if (screenshotSource !==
|
|
694
|
-
reasons.push(
|
|
740
|
+
if (screenshotSource !== expectedSource)
|
|
741
|
+
reasons.push(`ui_chrome_extension_screenshot_source_not_${expectedSource}`);
|
|
695
742
|
}
|
|
696
743
|
const review = visual?.gpt_image_2_annotated_review || {};
|
|
697
744
|
const gptImage2ReviewRequired = gate.gpt_image_2_annotated_review_required === true || review.required === true;
|
|
@@ -786,4 +833,14 @@ function positiveCount(value) {
|
|
|
786
833
|
const n = Number(value || 0);
|
|
787
834
|
return Number.isFinite(n) && n > 0;
|
|
788
835
|
}
|
|
836
|
+
function evidenceSourceForSurface(surface) {
|
|
837
|
+
const value = String(surface || '').trim();
|
|
838
|
+
if (value === 'codex_in_app_browser')
|
|
839
|
+
return CODEX_IN_APP_BROWSER_EVIDENCE_SOURCE;
|
|
840
|
+
if (value === 'codex_chrome_extension')
|
|
841
|
+
return CODEX_CHROME_EXTENSION_EVIDENCE_SOURCE;
|
|
842
|
+
if (value === 'codex_computer_use')
|
|
843
|
+
return CODEX_COMPUTER_USE_EVIDENCE_SOURCE;
|
|
844
|
+
return null;
|
|
845
|
+
}
|
|
789
846
|
//# sourceMappingURL=qa-loop.js.map
|
|
@@ -2,7 +2,7 @@ import { computeTriWikiAffectedGraph } from '../triwiki/triwiki-affected-graph.j
|
|
|
2
2
|
import { buildTriWikiSlaCertificate } from '../triwiki/triwiki-sla-certificate.js';
|
|
3
3
|
import { planExtremeParallelSchedule } from './extreme-parallel-scheduler.js';
|
|
4
4
|
export const SLA_SCHEDULER_SCHEMA = 'sks.sla-scheduler.v1';
|
|
5
|
-
export function planFiveMinuteSla(root, graph = computeTriWikiAffectedGraph({ root, tier: 'affected' }), slaMs = 300_000) {
|
|
5
|
+
export function planFiveMinuteSla(root, graph = computeTriWikiAffectedGraph({ root, tier: 'affected', includeProofLookup: false }), slaMs = 300_000) {
|
|
6
6
|
const schedule = planExtremeParallelSchedule(root, graph);
|
|
7
7
|
const certificate = buildTriWikiSlaCertificate({
|
|
8
8
|
graph,
|
|
@@ -17,7 +17,7 @@ export const RELEASE_1_17_GATE_SNAPSHOT = Object.freeze([
|
|
|
17
17
|
'release:readiness'
|
|
18
18
|
]);
|
|
19
19
|
export const RELEASE_1_18_REQUIRED_GATES = Object.freeze([
|
|
20
|
-
'
|
|
20
|
+
'ultra-search:provider-interface',
|
|
21
21
|
'source-intelligence:policy',
|
|
22
22
|
'source-intelligence:all-modes',
|
|
23
23
|
'codex-web:adapter',
|
package/dist/core/routes.js
CHANGED
|
@@ -30,17 +30,32 @@ export const FROM_CHAT_IMG_CHECKLIST_ARTIFACT = 'from-chat-img-checklist.md';
|
|
|
30
30
|
export const FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT = 'from-chat-img-temp-triwiki.json';
|
|
31
31
|
export const FROM_CHAT_IMG_QA_LOOP_ARTIFACT = 'from-chat-img-qa-loop.json';
|
|
32
32
|
export const FROM_CHAT_IMG_TEMP_TRIWIKI_SESSIONS = 5;
|
|
33
|
-
export const USAGE_TOPICS = 'install|setup|bootstrap|root|deps|zellij|tmux|auto-review|team|qa-loop|ppt|image-ux-review|computer-use|goal|fast-mode|research|db|git|codex|codex-app|codex-native|hooks|features|all-features|dfix|commit|commit-and-push|design|imagegen|dollar|context7|xai|pipeline|reasoning|guard|conflicts|versioning|eval|harness|hproof|gx|wiki|wrongness|code-structure|proof-field|skill-dream|rust';
|
|
33
|
+
export const USAGE_TOPICS = 'install|setup|bootstrap|root|deps|zellij|tmux|auto-review|team|qa-loop|ppt|image-ux-review|computer-use|goal|fast-mode|research|db|git|codex|codex-app|codex-native|hooks|features|all-features|dfix|commit|commit-and-push|design|imagegen|dollar|context7|ultra-search|xai|pipeline|reasoning|guard|conflicts|versioning|eval|harness|hproof|gx|wiki|wrongness|code-structure|proof-field|skill-dream|rust';
|
|
34
34
|
export const CODEX_COMPUTER_USE_EVIDENCE_SOURCE = 'codex_computer_use';
|
|
35
|
-
export const
|
|
35
|
+
export const CODEX_IN_APP_BROWSER_EVIDENCE_SOURCE = 'codex_in_app_browser';
|
|
36
|
+
export const CODEX_CHROME_EXTENSION_EVIDENCE_SOURCE = 'codex_chrome_extension';
|
|
37
|
+
export const CODEX_WEB_VERIFICATION_EVIDENCE_SOURCE = CODEX_IN_APP_BROWSER_EVIDENCE_SOURCE;
|
|
36
38
|
export const CODEX_IMAGEGEN_EVIDENCE_SOURCE = 'codex_app_imagegen_gpt_image_2';
|
|
39
|
+
export const CODEX_IN_APP_BROWSER_DOC_URL = 'https://developers.openai.com/codex/app/browser';
|
|
37
40
|
export const CODEX_CHROME_EXTENSION_DOC_URL = 'https://developers.openai.com/codex/app/chrome-extension';
|
|
41
|
+
export const CODEX_COMPUTER_USE_DOC_URL = 'https://developers.openai.com/codex/app/computer-use';
|
|
42
|
+
export const CODEX_RECORD_REPLAY_DOC_URL = 'https://developers.openai.com/codex/record-and-replay';
|
|
43
|
+
export const CODEX_APP_SERVER_DOC_URL = 'https://developers.openai.com/codex/app-server';
|
|
38
44
|
export const CODEX_APP_IMAGE_GENERATION_DOC_URL = 'https://developers.openai.com/codex/app/features#image-generation';
|
|
39
45
|
export const OPENAI_IMAGE_GENERATION_DOC_URL = 'https://developers.openai.com/api/docs/guides/image-generation';
|
|
40
46
|
export const OPENAI_CHATGPT_IMAGES_2_DOC_URL = 'https://openai.com/index/introducing-chatgpt-images-2-0/';
|
|
41
47
|
export const OPENAI_GPT_IMAGE_2_MODEL_DOC_URL = 'https://developers.openai.com/api/docs/models/gpt-image-2';
|
|
42
|
-
export const
|
|
43
|
-
|
|
48
|
+
export const QA_INTERACTION_SURFACES = Object.freeze([
|
|
49
|
+
'codex_in_app_browser',
|
|
50
|
+
'codex_chrome_extension',
|
|
51
|
+
'codex_computer_use',
|
|
52
|
+
'codex_app_plugin',
|
|
53
|
+
'structured_mcp',
|
|
54
|
+
'shell_or_api_diagnostic'
|
|
55
|
+
]);
|
|
56
|
+
export const CODEX_QA_SURFACE_ROUTING_POLICY = `Codex QA surface routing follows the official Codex App split: use @Browser / in-app Browser (${CODEX_IN_APP_BROWSER_DOC_URL}) first for localhost, local development servers, file-backed previews, and public pages that do not require sign-in; use @Chrome / Codex Chrome Extension (${CODEX_CHROME_EXTENSION_DOC_URL}) for signed-in websites, cookies, browser profiles, extensions, existing tabs, or internal tools; use @Computer or @AppName (${CODEX_COMPUTER_USE_DOC_URL}) for native macOS/Windows apps, OS settings, cross-app workflows, and GUI-only bugs. Prefer structured Plugins/MCPs for repeatable data operations, then verify rendered user-visible results with Browser, Chrome, or Computer Use. Playwright, Selenium, Puppeteer, Chrome MCP, static screenshots, plugin cache, and final-agent prose are not Codex App live action proof. App Server evidence (${CODEX_APP_SERVER_DOC_URL}) must correlate thread, turn, item/tool events, approvals, diffs, actions, observations, findings, fixes, and same-flow replay before a real QA pass is claimed.`;
|
|
57
|
+
export const CODEX_WEB_VERIFICATION_POLICY = CODEX_QA_SURFACE_ROUTING_POLICY;
|
|
58
|
+
export const CODEX_COMPUTER_USE_ONLY_POLICY = `Codex Computer Use is a live GUI surface for supported macOS and Windows environments, invoked with @Computer or @AppName for native apps, OS settings, browser contexts that truly require GUI-level operation, and cross-app workflows. Do not replace @Browser localhost/public-page checks or @Chrome signed-in checks with Computer Use unless the surface router records a specific GUI-only/cross-app reason. If live Computer Use tools, permissions, or app access are unavailable, mark the affected native/GUI evidence blocked or unverified instead of fabricating screenshots or actions. Codex App readiness/config checks are capability evidence only, not target interaction proof.`;
|
|
44
59
|
export const IMAGEGEN_SOCIAL_SOURCE_POLICY = 'Use public X/social/community reports only as prompt-quality and workflow-sentiment hints after official OpenAI/Codex docs. Social posts are not capability specs, evidence of tool availability, or proof that a generated asset was created.';
|
|
45
60
|
export const CODEX_IMAGEGEN_REQUIRED_POLICY = 'Pipeline image generation, raster asset creation/editing, and generated image-review evidence must use real Codex App imagegen/$imagegen with gpt-image-2 when that evidence is required for full verification. For newest-model image requests, prompt explicitly for "ChatGPT Images 2.0 / GPT Image 2.0 with gpt-image-2" instead of relying on generic image-generation wording. Do not substitute placeholder SVG/HTML/CSS, prose-only critique, stock-like stand-ins, manually fabricated files, or missing-output ledgers for requested/generated raster assets or required generated review images. If imagegen/gpt-image-2 is unavailable or generated annotated images cannot be created/linked, record the blocker and cap any closeout at verified_partial/reference-only instead of claiming generated-image evidence or full route verification; that partial closeout requires source screenshots plus hashes, docs evidence, source Image Voxel anchors, and Honest Mode evidence. In Codex App prompts, invoke $imagegen when live image generation is needed; SKS hooks and skills can require the policy but cannot attach missing host image-generation tools to an already-started turn. Official OpenAI/Codex docs are authoritative for capabilities, surfaces, limits, and evidence rules; X/social/community reports may inform prompt style only.';
|
|
46
61
|
export const DEFAULT_CODEX_APP_PLUGINS = Object.freeze([
|
|
@@ -56,7 +71,7 @@ export const RESERVED_CODEX_PLUGIN_SKILL_NAMES = Object.freeze([
|
|
|
56
71
|
'browser-use',
|
|
57
72
|
...DEFAULT_CODEX_APP_PLUGINS.map(([name]) => name)
|
|
58
73
|
].sort());
|
|
59
|
-
export const FORBIDDEN_BROWSER_AUTOMATION_RE = /\b(playwright|chrome\s+mcp|
|
|
74
|
+
export const FORBIDDEN_BROWSER_AUTOMATION_RE = /\b(playwright|chrome\s+mcp|selenium|puppeteer)\b/i;
|
|
60
75
|
export function evidenceMentionsForbiddenBrowserAutomation(value, seen = new Set()) {
|
|
61
76
|
if (value == null)
|
|
62
77
|
return false;
|
|
@@ -673,7 +688,8 @@ export const COMMAND_CATALOG = [
|
|
|
673
688
|
{ name: 'image-ux-review', usage: 'sks ux-review run --image <path> --fix --json | sks image-ux-review status <mission-id|latest> [--json]', description: 'Run or inspect $Image-UX-Review gpt-image-2/imagegen annotated UI/UX review artifacts, issue ledgers, safe fix loops, recapture, and proof gates.' },
|
|
674
689
|
{ name: 'computer-use', usage: 'sks computer-use import|status|smoke|require ... [--json]', description: 'Record native Mac/non-web Computer Use visual evidence while keeping web verification on the Chrome Extension path.' },
|
|
675
690
|
{ name: 'context7', usage: 'sks context7 check|setup|tools|resolve|docs|evidence ...', description: 'Check, configure, and call the local Context7 MCP requirement.' },
|
|
676
|
-
{ name: '
|
|
691
|
+
{ name: 'ultra-search', usage: 'sks ultra-search doctor|run|x|fetch|status|inspect|sources|claims|cache|bench|migrate-xai', description: 'Run provider-independent UltraSearch source intelligence.' },
|
|
692
|
+
{ name: 'xai', usage: 'sks xai check|status|docs', description: 'Deprecated compatibility notice; use sks ultra-search.' },
|
|
677
693
|
{ name: 'recallpulse', usage: 'sks recallpulse run|status|eval|governance|checklist <mission-id|latest>', description: 'Run report-only RecallPulse active recall, durable status, proof capsule, evidence envelope, and governance checks.' },
|
|
678
694
|
{ name: 'pipeline', usage: 'sks pipeline status|resume|plan|answer ...', description: 'Inspect the active skill-first route, materialized execution plan, ambiguity gates, and completion gates.' },
|
|
679
695
|
{ name: 'guard', usage: 'sks guard check [--json]', description: 'Check SKS harness self-protection lock, fingerprints, and source-repo exception state.' },
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { nowIso, writeJsonAtomic } from '../fsx.js';
|
|
3
|
-
export const SOURCE_INTELLIGENCE_POLICY_SCHEMA = 'sks.source-intelligence-policy.
|
|
3
|
+
export const SOURCE_INTELLIGENCE_POLICY_SCHEMA = 'sks.source-intelligence-policy.v2';
|
|
4
4
|
export function buildSourceIntelligencePolicy(input = {}) {
|
|
5
5
|
const route = input.route || 'unknown';
|
|
6
6
|
const offline = input.offline === true;
|
|
7
|
+
const query = input.query || '';
|
|
8
|
+
const docsIntent = /\b(package|npm|SDK|API|MCP|framework|library|docs?|문서|React|Next\.js|Prisma|Tailwind)\b/i.test(query);
|
|
9
|
+
const xIntent = /\b(?:x\.com|twitter\.com|X\/Twitter|트위터|엑스|site:x\.com|site:twitter\.com)\b/i.test(query);
|
|
10
|
+
const urlIntent = /https?:\/\/[^\s)"']+/i.test(query);
|
|
7
11
|
const context7Available = input.context7Available !== false;
|
|
8
12
|
const codex = input.codexWebCapability || {
|
|
9
13
|
schema: 'sks.codex-web-search-capability.v1',
|
|
@@ -11,43 +15,65 @@ export function buildSourceIntelligencePolicy(input = {}) {
|
|
|
11
15
|
status: 'degraded_unverified',
|
|
12
16
|
reason: 'capability_not_checked'
|
|
13
17
|
};
|
|
14
|
-
const xai = input.xaiDetection;
|
|
15
|
-
const xaiSearchCapable = xai?.search_capable === true;
|
|
16
|
-
const xaiConfigured = xai?.configured === true;
|
|
17
18
|
const blockers = [];
|
|
18
19
|
const warnings = [];
|
|
19
20
|
const wrongnessKinds = [];
|
|
20
|
-
if (!context7Available) {
|
|
21
|
+
if (docsIntent && !context7Available) {
|
|
21
22
|
blockers.push('docs_context_missing');
|
|
22
23
|
wrongnessKinds.push('context7_missing');
|
|
23
24
|
}
|
|
24
25
|
if (!offline && codex.status === 'unavailable') {
|
|
25
|
-
warnings.push('
|
|
26
|
+
warnings.push('codex_web_search_unavailable_degraded_to_ultra_cache_or_docs');
|
|
26
27
|
wrongnessKinds.push('codex_web_search_missing');
|
|
27
28
|
}
|
|
28
|
-
if (
|
|
29
|
-
warnings.push('
|
|
30
|
-
|
|
31
|
-
warnings.push('xai_mcp_configured_but_search_capability_unverified');
|
|
32
|
-
const mode = !context7Available
|
|
29
|
+
if (input.xaiDetection)
|
|
30
|
+
warnings.push('xai_detection_input_ignored_by_source_intelligence_v2');
|
|
31
|
+
const mode = input.mode || (!context7Available && docsIntent
|
|
33
32
|
? 'blocked'
|
|
34
33
|
: offline
|
|
35
|
-
? '
|
|
36
|
-
:
|
|
37
|
-
? '
|
|
38
|
-
:
|
|
39
|
-
? '
|
|
40
|
-
:
|
|
34
|
+
? 'offline_cache'
|
|
35
|
+
: urlIntent
|
|
36
|
+
? 'url_acquisition'
|
|
37
|
+
: xIntent
|
|
38
|
+
? 'x_search'
|
|
39
|
+
: /deep|exhaustive|가능한 전부|누락 없이|완벽하게 조사/i.test(query)
|
|
40
|
+
? 'ultra_deep'
|
|
41
|
+
: 'ultra_balanced');
|
|
42
|
+
const selected = new Set();
|
|
43
|
+
if (docsIntent && context7Available)
|
|
44
|
+
selected.add('context7');
|
|
45
|
+
if (!offline && codex.status !== 'unavailable')
|
|
46
|
+
selected.add('codex_web');
|
|
47
|
+
if (xIntent || mode === 'x_search')
|
|
48
|
+
selected.add('x_public');
|
|
49
|
+
if (offline)
|
|
50
|
+
selected.add('offline_cache');
|
|
41
51
|
return {
|
|
42
52
|
schema: SOURCE_INTELLIGENCE_POLICY_SCHEMA,
|
|
43
53
|
generated_at: nowIso(),
|
|
44
54
|
ok: blockers.length === 0,
|
|
45
55
|
route,
|
|
46
56
|
mode,
|
|
57
|
+
requirements: {
|
|
58
|
+
official_sources: docsIntent,
|
|
59
|
+
full_content: mode !== 'ultra_fast',
|
|
60
|
+
counter_search: mode === 'ultra_deep' || mode === 'ultra_exhaustive',
|
|
61
|
+
claim_ledger: true,
|
|
62
|
+
social_recency: xIntent || mode === 'x_search',
|
|
63
|
+
code_execution_verification: /\b(code|implementation|test|runtime|구현)\b/i.test(query)
|
|
64
|
+
},
|
|
65
|
+
capabilities: {
|
|
66
|
+
docs: context7Available ? ['context7', 'official_web'] : ['official_web'],
|
|
67
|
+
web_search: !offline ? ['codex_web'] : [],
|
|
68
|
+
repo_search: ['github'],
|
|
69
|
+
social: xIntent || mode === 'x_search' ? ['x_public', 'authenticated_chrome_optional', 'official_x_api_optional'] : [],
|
|
70
|
+
browser: ['codex_browser_optional', 'codex_chrome_optional']
|
|
71
|
+
},
|
|
72
|
+
selected_providers: [...selected],
|
|
47
73
|
context7: {
|
|
48
|
-
required:
|
|
74
|
+
required: docsIntent,
|
|
49
75
|
available: context7Available,
|
|
50
|
-
status: context7Available ? (offline ? 'offline_only' : 'available') : 'missing'
|
|
76
|
+
status: docsIntent ? (context7Available ? (offline ? 'offline_only' : 'available') : 'missing') : 'not_required'
|
|
51
77
|
},
|
|
52
78
|
codex_web_search: {
|
|
53
79
|
required: !offline,
|
|
@@ -55,13 +81,6 @@ export function buildSourceIntelligencePolicy(input = {}) {
|
|
|
55
81
|
status: codex.status,
|
|
56
82
|
reason: codex.reason
|
|
57
83
|
},
|
|
58
|
-
xai_mcp: {
|
|
59
|
-
required: xaiSearchCapable,
|
|
60
|
-
configured: xaiConfigured,
|
|
61
|
-
search_capable: xaiSearchCapable,
|
|
62
|
-
configured_but_unverified: xai?.configured_but_unverified === true,
|
|
63
|
-
status: xai?.status || 'not_checked'
|
|
64
|
-
},
|
|
65
84
|
wrongness_kinds: wrongnessKinds,
|
|
66
85
|
blockers,
|
|
67
86
|
warnings
|
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
export const SOURCE_INTELLIGENCE_PROOF_SCHEMA = 'sks.source-intelligence-proof.
|
|
1
|
+
export const SOURCE_INTELLIGENCE_PROOF_SCHEMA = 'sks.source-intelligence-proof.v2';
|
|
2
2
|
export function buildSourceIntelligenceProof(policy, evidence) {
|
|
3
3
|
const blockers = [...policy.blockers];
|
|
4
4
|
const wrongnessKinds = [...policy.wrongness_kinds];
|
|
5
|
-
const context7Ok = evidence.context7?.ok === true;
|
|
6
|
-
const
|
|
7
|
-
const xaiOk = policy.xai_mcp.required ? evidence.xai_search?.ok === true : true;
|
|
8
|
-
const xaiMissingIsBlocker = policy.xai_mcp.required && !xaiOk;
|
|
5
|
+
const context7Ok = policy.context7.required ? evidence.context7?.ok === true : true;
|
|
6
|
+
const ultraOk = evidence.ultra_search?.proof.provider_independent === true && evidence.ultra_search?.proof.xai_runtime_dependency === false;
|
|
9
7
|
const appshotsRequired = evidence.appshots?.capability.visual_required === true;
|
|
10
8
|
const appshotsOk = appshotsRequired ? evidence.appshots?.ok === true : true;
|
|
11
9
|
if (policy.context7.required && !context7Ok) {
|
|
12
10
|
blockers.push('context7_missing');
|
|
13
11
|
wrongnessKinds.push('context7_missing');
|
|
14
12
|
}
|
|
15
|
-
if (
|
|
16
|
-
blockers.push('
|
|
17
|
-
wrongnessKinds.push('
|
|
18
|
-
}
|
|
19
|
-
if (policy.xai_mcp.required && !xaiOk) {
|
|
20
|
-
blockers.push('xai_available_not_used');
|
|
21
|
-
wrongnessKinds.push('xai_available_not_used');
|
|
13
|
+
if (!ultraOk) {
|
|
14
|
+
blockers.push('ultra_search_provider_independent_proof_missing');
|
|
15
|
+
wrongnessKinds.push('ultra_search_provider_independent_proof_missing');
|
|
22
16
|
}
|
|
17
|
+
if (evidence.ultra_search?.proof.blockers.length)
|
|
18
|
+
blockers.push(...evidence.ultra_search.proof.blockers);
|
|
23
19
|
if (appshotsRequired && !appshotsOk) {
|
|
24
20
|
blockers.push('appshots_operator_action_missing');
|
|
25
21
|
wrongnessKinds.push('appshots_operator_action_missing');
|
|
@@ -32,10 +28,8 @@ export function buildSourceIntelligenceProof(policy, evidence) {
|
|
|
32
28
|
context7_required: policy.context7.required,
|
|
33
29
|
context7_ok: context7Ok,
|
|
34
30
|
codex_web_required: policy.codex_web_search.required,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
xai_ok: xaiOk,
|
|
38
|
-
xai_missing_is_blocker: xaiMissingIsBlocker,
|
|
31
|
+
ultra_search_ok: ultraOk,
|
|
32
|
+
provider_independent: evidence.ultra_search?.proof.provider_independent === true,
|
|
39
33
|
appshots_required: appshotsRequired,
|
|
40
34
|
appshots_ok: appshotsOk
|
|
41
35
|
},
|