sneakoscope 7.3.0 → 7.5.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 +117 -5
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/cli/codex-app-command.js +1 -1
- package/dist/cli/command-manifest-lite.js +2 -1
- package/dist/cli/install-helpers-codex-lb-selftest.js +2 -1
- package/dist/cli/install-helpers-install-support.js +6 -16
- package/dist/cli/install-helpers.js +59 -50
- package/dist/cli/router.js +9 -1
- package/dist/config/skills-manifest.json +50 -71
- package/dist/core/codex-app.js +5 -5
- package/dist/core/codex-native/core-skill-manifest.js +9 -6
- package/dist/core/commands/image-ux-review-command.js +243 -50
- package/dist/core/commands/naruto-command.js +245 -8
- package/dist/core/commands/ppt-command.js +2 -2
- package/dist/core/commands/telegram-command.js +123 -10
- package/dist/core/commands/triwiki-command.js +11 -1
- package/dist/core/commands/triwiki-graph-command.js +160 -0
- package/dist/core/commands/wiki-command.js +100 -20
- package/dist/core/errors/message.js +3 -0
- package/dist/core/feature-registry.js +2 -2
- package/dist/core/fsx.js +7 -3
- package/dist/core/hooks-runtime/codex-commit-hooks-selftest.js +82 -0
- package/dist/core/hooks-runtime/context-graph-freshness-preflight.js +113 -0
- package/dist/core/hooks-runtime/official-subagent-lifecycle.js +1 -1
- package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
- package/dist/core/hooks-runtime.js +28 -86
- package/dist/core/image-ux-review/callout-extraction.js +6 -0
- package/dist/core/image-ux-review/imagegen-adapter.js +54 -18
- package/dist/core/image-ux-review/real-callout-extractor.js +1 -0
- package/dist/core/image-ux-review.js +182 -7
- package/dist/core/imagegen/codex-lb-imagegen-target.js +22 -7
- package/dist/core/imagegen/imagegen-capability.js +11 -4
- package/dist/core/imagegen/require-imagegen.js +29 -5
- package/dist/core/init/skills.js +22 -10
- package/dist/core/install/installed-package-smoke.js +157 -4
- package/dist/core/managed-path-safety.js +8 -10
- package/dist/core/mcp-config/backup.js +2 -4
- package/dist/core/mcp-config/config-reader.js +2 -4
- package/dist/core/mcp-config/scope.js +3 -5
- package/dist/core/naruto/context-graph-advisor-scope.js +242 -0
- package/dist/core/naruto/context-graph-advisor.js +0 -0
- package/dist/core/pipeline-internals/runtime-core.js +44 -0
- package/dist/core/policy/latest-version-guidance.js +113 -0
- package/dist/core/ppt.js +8 -8
- package/dist/core/release/gate-manifest.js +32 -1
- package/dist/core/release/npm-stage-contract.js +21 -0
- package/dist/core/release/package-size-budget.js +2 -2
- package/dist/core/release/release-gate-contract.js +5 -0
- package/dist/core/release/stage-publish.js +27 -0
- package/dist/core/responses-stream.js +65 -19
- package/dist/core/routes/design-policy.js +7 -2
- package/dist/core/routes/dollar-manifest-lite.js +0 -4
- package/dist/core/routes/evidence.js +1 -1
- package/dist/core/routes.js +12 -8
- package/dist/core/safety/command-contract/contracts.js +2 -0
- package/dist/core/safety/command-contract/types.js +1 -1
- package/dist/core/search/context-graph-seeds.js +205 -0
- package/dist/core/search/context.js +0 -0
- package/dist/core/search/provider.js +2 -2
- package/dist/core/subagents/naruto-help-contract.js +2 -1
- package/dist/core/subagents/naruto-host-credentials.js +161 -0
- package/dist/core/subagents/official-subagent-preparation.js +4 -1
- package/dist/core/subagents/official-subagent-prompt.js +44 -2
- package/dist/core/subagents/official-subagent-runner.js +26 -8
- package/dist/core/subagents/triwiki-attention.js +135 -123
- package/dist/core/telegram/bot-api.js +59 -4
- package/dist/core/telegram/config.js +3 -2
- package/dist/core/telegram/hub.js +3 -2
- package/dist/core/telegram/owner-lock.js +4 -6
- package/dist/core/telegram/setup.js +223 -73
- package/dist/core/triwiki/code-pack.js +12 -120
- package/dist/core/triwiki/context-graph/compiler/cache-key.js +277 -0
- package/dist/core/triwiki/context-graph/compiler/extract.js +104 -0
- package/dist/core/triwiki/context-graph/compiler/freshness.js +108 -0
- package/dist/core/triwiki/context-graph/compiler/index.js +237 -0
- package/dist/core/triwiki/context-graph/compiler/merge.js +0 -0
- package/dist/core/triwiki/context-graph/compiler/serialize.js +115 -0
- package/dist/core/triwiki/context-graph/contracts.js +236 -0
- package/dist/core/triwiki/context-graph/extractors/code/builders.js +150 -0
- package/dist/core/triwiki/context-graph/extractors/code/declarations.js +161 -0
- package/dist/core/triwiki/context-graph/extractors/code/index.js +265 -0
- package/dist/core/triwiki/context-graph/extractors/code/inventory.js +237 -0
- package/dist/core/triwiki/context-graph/extractors/code/module-graph.js +252 -0
- package/dist/core/triwiki/context-graph/extractors/code/modules.js +79 -0
- package/dist/core/triwiki/context-graph/extractors/code/references.js +184 -0
- package/dist/core/triwiki/context-graph/extractors/code/selection.js +100 -0
- package/dist/core/triwiki/context-graph/extractors/code/ts-config.js +161 -0
- package/dist/core/triwiki/context-graph/extractors/code/types.js +18 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/claims.js +289 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/index.js +54 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/proof-index.js +213 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/proofs.js +266 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/redaction.js +177 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/shared.js +0 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/sources.js +154 -0
- package/dist/core/triwiki/context-graph/extractors/index.js +7 -0
- package/dist/core/triwiki/context-graph/extractors/topology/commands.js +207 -0
- package/dist/core/triwiki/context-graph/extractors/topology/gate-edges.js +201 -0
- package/dist/core/triwiki/context-graph/extractors/topology/gates.js +182 -0
- package/dist/core/triwiki/context-graph/extractors/topology/globs.js +124 -0
- package/dist/core/triwiki/context-graph/extractors/topology/index.js +92 -0
- package/dist/core/triwiki/context-graph/extractors/topology/routes.js +135 -0
- package/dist/core/triwiki/context-graph/extractors/topology/shared.js +215 -0
- package/dist/core/triwiki/context-graph/graph-index.js +143 -0
- package/dist/core/triwiki/context-graph/ids.js +0 -0
- package/dist/core/triwiki/context-graph/lint/index.js +0 -0
- package/dist/core/triwiki/context-graph/lint/rules.js +232 -0
- package/dist/core/triwiki/context-graph/lint/warnings.js +93 -0
- package/dist/core/triwiki/context-graph/paths.js +116 -0
- package/dist/core/triwiki/context-graph/profiles.js +78 -0
- package/dist/core/triwiki/context-graph/projections/anchors.js +91 -0
- package/dist/core/triwiki/context-graph/projections/attention.js +58 -0
- package/dist/core/triwiki/context-graph/projections/code-pack-workspace.js +62 -0
- package/dist/core/triwiki/context-graph/projections/code-pack.js +144 -0
- package/dist/core/triwiki/context-graph/projections/index.js +7 -0
- package/dist/core/triwiki/context-graph/projections/module-view.js +140 -0
- package/dist/core/triwiki/context-graph/projections/node-summary.js +118 -0
- package/dist/core/triwiki/context-graph/projections/pack-contract.js +6 -0
- package/dist/core/triwiki/context-graph/query/explain.js +0 -0
- package/dist/core/triwiki/context-graph/query/index.js +178 -0
- package/dist/core/triwiki/context-graph/query/load.js +116 -0
- package/dist/core/triwiki/context-graph/query/pack.js +117 -0
- package/dist/core/triwiki/context-graph/query/rank.js +142 -0
- package/dist/core/triwiki/context-graph/query/ranking-config.js +64 -0
- package/dist/core/triwiki/context-graph/query/seeds.js +241 -0
- package/dist/core/triwiki/context-graph/query/snapshot-cache.js +72 -0
- package/dist/core/triwiki/context-graph/query/traverse.js +154 -0
- package/dist/core/triwiki/context-graph/query-types.js +29 -0
- package/dist/core/triwiki/context-graph/store/compile-lock.js +21 -0
- package/dist/core/triwiki/context-graph/store/event-log.js +48 -0
- package/dist/core/triwiki/context-graph/store/fragment-cache.js +85 -0
- package/dist/core/triwiki/context-graph/store/graph-status.js +85 -0
- package/dist/core/triwiki/context-graph/store/snapshot-store.js +155 -0
- package/dist/core/triwiki/triwiki-proof-bank-index-repair.js +115 -0
- package/dist/core/triwiki/triwiki-proof-bank-index-store.js +290 -0
- package/dist/core/triwiki/triwiki-proof-bank-index.js +126 -0
- package/dist/core/triwiki/triwiki-proof-bank.js +7 -1
- package/dist/core/verification/context-graph-affected.js +271 -0
- package/dist/core/version.js +1 -1
- package/dist/scripts/context-graph-check.js +191 -0
- package/dist/scripts/helper-dedup-check.js +0 -1
- package/dist/scripts/installed-package-smoke-check.js +4 -1
- package/dist/scripts/latest-version-guidance-check.js +74 -0
- package/dist/scripts/release-metadata-check.js +20 -3
- package/dist/scripts/ux-review-imagegen-blackbox-check.js +25 -1
- package/dist/scripts/ux-review-run-wires-imagegen-check.js +9 -1
- package/package.json +5 -3
- package/release-gates.v2.json +174 -0
- package/schemas/triwiki/context-graph.schema.json +119 -0
- package/dist/core/triwiki/code-index-scanner.js +0 -309
|
@@ -12,7 +12,7 @@ import { buildIssueLedgerFromGeneratedCallouts } from './image-ux-review/callout
|
|
|
12
12
|
import { planImageUxFixTasks } from './image-ux-review/fix-task-planner.js';
|
|
13
13
|
import { runImageUxFixLoop } from './image-ux-review/fix-loop.js';
|
|
14
14
|
import { buildRecapturePlan } from './image-ux-review/recapture.js';
|
|
15
|
-
import { addVisualAnchor, ingestImage } from './wiki-image/image-voxel-ledger.js';
|
|
15
|
+
import { addImageRelation, addVisualAnchor, ingestImage } from './wiki-image/image-voxel-ledger.js';
|
|
16
16
|
import { validateFinalHonestModeReport } from './artifact-schemas.js';
|
|
17
17
|
import { imagegenEvidenceClassBlockers, isFullImagegenOutputSource } from './imagegen/imagegen-evidence.js';
|
|
18
18
|
export const IMAGE_UX_REVIEW_GATE_ARTIFACT = 'image-ux-review-gate.json';
|
|
@@ -69,6 +69,35 @@ export function imageUxReviewGateAllowsReferenceCloseout(gate = {}) {
|
|
|
69
69
|
&& gate?.verified_level === 'verified_partial'
|
|
70
70
|
&& gate?.full_review_passed !== true;
|
|
71
71
|
}
|
|
72
|
+
export function imageUxReviewCommandOutcome(gate = {}, proofOk = false, opts = {}) {
|
|
73
|
+
const reviewReportCompleted = gate?.review_report_completed === true;
|
|
74
|
+
const reviewOnlyCompletionAllowed = opts.allowReviewOnlyCompletion === true;
|
|
75
|
+
const reviewOnlyCompleted = reviewOnlyCompletionAllowed && reviewReportCompleted;
|
|
76
|
+
const gateAndProofPassed = gate?.passed === true && proofOk === true;
|
|
77
|
+
const fullReviewPassed = gate?.full_review_passed === true && gateAndProofPassed;
|
|
78
|
+
return {
|
|
79
|
+
ok: gateAndProofPassed || reviewOnlyCompleted,
|
|
80
|
+
status: fullReviewPassed
|
|
81
|
+
? 'passed'
|
|
82
|
+
: reviewOnlyCompleted
|
|
83
|
+
? 'review_completed'
|
|
84
|
+
: gateAndProofPassed
|
|
85
|
+
? gate?.status || 'passed'
|
|
86
|
+
: 'blocked',
|
|
87
|
+
completion_scope: fullReviewPassed
|
|
88
|
+
? 'full_review_and_optional_fix_verification'
|
|
89
|
+
: reviewOnlyCompleted
|
|
90
|
+
? 'capture_imagegen_ocr_and_ux_report'
|
|
91
|
+
: null,
|
|
92
|
+
review_report_completed: reviewReportCompleted,
|
|
93
|
+
review_only_completion_allowed: reviewOnlyCompletionAllowed,
|
|
94
|
+
full_review_passed: gate?.full_review_passed === true,
|
|
95
|
+
requires_human_review: gate?.requires_human_review === true,
|
|
96
|
+
unresolved_p0_p1_count: Number(gate?.unresolved_p0_p1_count || 0),
|
|
97
|
+
safety_blockers: Array.isArray(gate?.blockers) ? gate.blockers : [],
|
|
98
|
+
proof_ok: proofOk === true
|
|
99
|
+
};
|
|
100
|
+
}
|
|
72
101
|
function cleanText(value, fallback = '') {
|
|
73
102
|
const text = String(value ?? '').replace(/\s+/g, ' ').trim();
|
|
74
103
|
return text || fallback;
|
|
@@ -340,6 +369,17 @@ export function buildImageUxIssueLedger(contract = {}, generatedReviewLedger = b
|
|
|
340
369
|
};
|
|
341
370
|
}
|
|
342
371
|
export function buildImageUxIterationReport(contract = {}, policy = buildImageUxReviewPolicy(contract), generatedReviewLedger = buildImageUxGeneratedReviewLedger(contract), issueLedger = buildImageUxIssueLedger(contract, generatedReviewLedger), fixTaskPlan = planImageUxFixTasks(issueLedger), fixLoop = runImageUxFixLoop(issueLedger, fixTaskPlan), recapturePlan = buildRecapturePlan(fixLoop)) {
|
|
372
|
+
const generatedImage = (generatedReviewLedger.generated_review_images || [])[0] || null;
|
|
373
|
+
const issues = Array.isArray(issueLedger.issues) ? issueLedger.issues : [];
|
|
374
|
+
const basedOnGeneratedImage = issueLedger.extracted_from_generated_callout === true
|
|
375
|
+
&& issues.length > 0
|
|
376
|
+
&& issues.every((issue) => issue.extracted_from_generated_image === true
|
|
377
|
+
&& issue.generated_image_sha256 === generatedImage?.sha256);
|
|
378
|
+
const requiresHumanReview = (fixTaskPlan.tasks || []).some((task) => task.requires_human_review === true);
|
|
379
|
+
const severityCounts = Object.fromEntries(['P0', 'P1', 'P2', 'P3'].map((severity) => [
|
|
380
|
+
severity,
|
|
381
|
+
issues.filter((issue) => issue.severity === severity).length
|
|
382
|
+
]));
|
|
343
383
|
const passed = generatedReviewLedger.passed === true
|
|
344
384
|
&& issueLedger.passed === true
|
|
345
385
|
&& fixLoop.passed === true
|
|
@@ -351,6 +391,43 @@ export function buildImageUxIterationReport(contract = {}, policy = buildImageUx
|
|
|
351
391
|
schema_version: 2,
|
|
352
392
|
created_at: nowIso(),
|
|
353
393
|
contract_hash: contract.sealed_hash || null,
|
|
394
|
+
report_type: 'ux_ui_change_report',
|
|
395
|
+
review_report_completed: generatedReviewLedger.passed === true
|
|
396
|
+
&& issueLedger.validation?.ok === true
|
|
397
|
+
&& basedOnGeneratedImage,
|
|
398
|
+
full_review_passed: passed,
|
|
399
|
+
requires_human_review: requiresHumanReview,
|
|
400
|
+
unresolved_p0_p1_count: Number(issueLedger.blocking_issue_count || 0),
|
|
401
|
+
analysis_basis: {
|
|
402
|
+
primary_evidence: 'generated_annotated_review_image',
|
|
403
|
+
generated_image_path: generatedImage?.path || null,
|
|
404
|
+
generated_image_sha256: generatedImage?.sha256 || null,
|
|
405
|
+
generated_image_id: generatedImage?.id || null,
|
|
406
|
+
source_screen_id: generatedImage?.source_screen_id || 'screen-1',
|
|
407
|
+
issue_extraction_source: issueLedger.extraction_source || IMAGE_UX_REVIEW_GENERATED_REVIEW_LEDGER_ARTIFACT,
|
|
408
|
+
based_on_generated_image: basedOnGeneratedImage
|
|
409
|
+
},
|
|
410
|
+
executive_summary: {
|
|
411
|
+
issue_count: issues.length,
|
|
412
|
+
severity_counts: severityCounts,
|
|
413
|
+
highest_priority: issues.find((issue) => ['P0', 'P1'].includes(issue.severity))?.severity
|
|
414
|
+
|| issues[0]?.severity
|
|
415
|
+
|| null
|
|
416
|
+
},
|
|
417
|
+
recommendations: issues.map((issue) => ({
|
|
418
|
+
issue_id: issue.id,
|
|
419
|
+
callout_id: issue.callout_id,
|
|
420
|
+
severity: issue.severity,
|
|
421
|
+
title: issue.title,
|
|
422
|
+
observed_problem: issue.detail,
|
|
423
|
+
likely_cause: issue.likely_cause,
|
|
424
|
+
recommended_ux_ui_change: issue.fix_action,
|
|
425
|
+
target_surface: issue.target_surface,
|
|
426
|
+
generated_image_bbox: issue.bbox,
|
|
427
|
+
generated_image_sha256: issue.generated_image_sha256,
|
|
428
|
+
confidence: issue.confidence,
|
|
429
|
+
verification_status: issue.fix_verification_status
|
|
430
|
+
})),
|
|
354
431
|
loop_policy: {
|
|
355
432
|
max_full_surface_passes: policy.max_full_surface_passes,
|
|
356
433
|
max_screen_retries: policy.max_screen_retries,
|
|
@@ -416,6 +493,15 @@ export function defaultImageUxReviewGate(contract = {}, parts = {}) {
|
|
|
416
493
|
const wrongnessChecked = parts.wrongnessChecked === true || generatedReviewLedger.blockers?.length === 0;
|
|
417
494
|
const honestModeEvidence = parts.honestModeEvidence || null;
|
|
418
495
|
const honestModeComplete = parts.honestModeComplete === true && (honestModeEvidence?.ok === true || parts.honestModeEvidenceRequired !== true);
|
|
496
|
+
const requiresHumanReview = (fixTaskPlan.tasks || []).some((task) => task.requires_human_review === true);
|
|
497
|
+
const reviewReportCompleted = realSourceScreenshotPresent
|
|
498
|
+
&& officialOrUserScreenshotSource
|
|
499
|
+
&& generatedReviewLedger.passed === true
|
|
500
|
+
&& realGeneratedCount > 0
|
|
501
|
+
&& calloutExtractionSchemaValid
|
|
502
|
+
&& issueLedger.extracted_from_generated_callout === true
|
|
503
|
+
&& iterationReport.review_report_completed === true
|
|
504
|
+
&& iterationReport.analysis_basis?.based_on_generated_image === true;
|
|
419
505
|
const referenceCloseoutPassed = generatedImageUnavailable
|
|
420
506
|
&& realSourceScreenshotPresent
|
|
421
507
|
&& officialOrUserScreenshotSource
|
|
@@ -436,6 +522,10 @@ export function defaultImageUxReviewGate(contract = {}, parts = {}) {
|
|
|
436
522
|
status: 'blocked',
|
|
437
523
|
verified_level: 'blocked',
|
|
438
524
|
full_review_passed: false,
|
|
525
|
+
review_report_completed: reviewReportCompleted,
|
|
526
|
+
completion_scope: reviewReportCompleted ? 'capture_imagegen_ocr_and_ux_report' : null,
|
|
527
|
+
requires_human_review: requiresHumanReview,
|
|
528
|
+
unresolved_p0_p1_count: Number(issueLedger.blocking_issue_count || 0),
|
|
439
529
|
reference_only: false,
|
|
440
530
|
real_source_screenshot_present: realSourceScreenshotPresent,
|
|
441
531
|
computer_use_or_user_screenshot_source: officialOrUserScreenshotSource,
|
|
@@ -448,7 +538,8 @@ export function defaultImageUxReviewGate(contract = {}, parts = {}) {
|
|
|
448
538
|
fix_loop_executed_or_not_needed: fixLoopExecutedOrNotNeeded,
|
|
449
539
|
changed_screens_rechecked: changedScreensRechecked,
|
|
450
540
|
image_voxel_reference_anchor_created: imageVoxelReferenceAnchorCreated,
|
|
451
|
-
image_voxel_relations_created: parts.imageVoxelRelationsCreated === true
|
|
541
|
+
image_voxel_relations_created: parts.imageVoxelRelationsCreated === true,
|
|
542
|
+
image_voxel_relation_evidence: parts.imageVoxelRelationEvidence || null,
|
|
452
543
|
wrongness_checked: wrongnessChecked,
|
|
453
544
|
honest_mode_complete: honestModeComplete,
|
|
454
545
|
required_artifacts: [
|
|
@@ -497,8 +588,18 @@ export function defaultImageUxReviewGate(contract = {}, parts = {}) {
|
|
|
497
588
|
return {
|
|
498
589
|
...gate,
|
|
499
590
|
passed: fullPassed || referenceCloseoutPassed,
|
|
500
|
-
status: fullPassed
|
|
501
|
-
|
|
591
|
+
status: fullPassed
|
|
592
|
+
? 'passed'
|
|
593
|
+
: referenceCloseoutPassed
|
|
594
|
+
? 'verified_partial_reference'
|
|
595
|
+
: reviewReportCompleted
|
|
596
|
+
? 'review_completed'
|
|
597
|
+
: 'blocked',
|
|
598
|
+
verified_level: fullPassed
|
|
599
|
+
? 'verified'
|
|
600
|
+
: referenceCloseoutPassed || reviewReportCompleted
|
|
601
|
+
? 'verified_partial'
|
|
602
|
+
: 'blocked',
|
|
502
603
|
full_review_passed: fullPassed,
|
|
503
604
|
reference_only: referenceCloseoutPassed
|
|
504
605
|
};
|
|
@@ -515,6 +616,7 @@ export async function writeImageUxReviewRouteArtifacts(dir, contract = {}, opts
|
|
|
515
616
|
const existingImagegenResponse = await readExistingJson(dir, IMAGE_UX_REVIEW_GPT_IMAGE_2_RESPONSE_ARTIFACT);
|
|
516
617
|
const generatedReviewLedger = buildImageUxGeneratedReviewLedger(contract, inventory, existingGenerated, { root });
|
|
517
618
|
const sourceReferenceEvidence = await ensureImageUxSourceReferenceEvidence(root, dir, inventory);
|
|
619
|
+
const imageVoxelRelationEvidence = await ensureImageUxGeneratedRelationEvidence(root, dir, inventory, generatedReviewLedger, sourceReferenceEvidence);
|
|
518
620
|
const issueLedger = buildImageUxIssueLedger(contract, generatedReviewLedger, existingIssues);
|
|
519
621
|
const fixTaskPlan = planImageUxFixTasks(issueLedger);
|
|
520
622
|
const fixLoop = runImageUxFixLoop(issueLedger, fixTaskPlan, opts.fixLoop || {});
|
|
@@ -540,7 +642,8 @@ export async function writeImageUxReviewRouteArtifacts(dir, contract = {}, opts
|
|
|
540
642
|
recapturePlan,
|
|
541
643
|
iterationReport,
|
|
542
644
|
imageVoxelReferenceAnchorCreated: sourceReferenceEvidence.ok === true,
|
|
543
|
-
imageVoxelRelationsCreated: opts.imageVoxelRelationsCreated === true,
|
|
645
|
+
imageVoxelRelationsCreated: opts.imageVoxelRelationsCreated === true || imageVoxelRelationEvidence.ok === true,
|
|
646
|
+
imageVoxelRelationEvidence,
|
|
544
647
|
wrongnessChecked: opts.wrongnessChecked === true,
|
|
545
648
|
honestModeComplete: honestModeEvidence.ok === true,
|
|
546
649
|
honestModeEvidenceRequired: true,
|
|
@@ -599,7 +702,9 @@ export function imageUxReviewProofEvidence(gate = {}, artifacts = {}) {
|
|
|
599
702
|
open_p0_p1_count: issueLedger.blocking_issue_count || 0,
|
|
600
703
|
fixed_p0_p1_count: (issueLedger.issues || []).filter((issue) => ['P0', 'P1'].includes(issue.severity) && issue.status === 'fixed').length,
|
|
601
704
|
recapture_re_review_status: artifacts.recapture_plan?.changed_screens_rechecked_or_not_applicable ? 'complete_or_not_applicable' : 'blocked',
|
|
602
|
-
image_voxel_relation_count: referenceOnly
|
|
705
|
+
image_voxel_relation_count: referenceOnly
|
|
706
|
+
? 0
|
|
707
|
+
: gate.image_voxel_relations_created === true ? realGeneratedImages.length : 0,
|
|
603
708
|
computer_use_evidence_mode: artifacts.inventory?.source_screens?.some((screen) => screen.capture_source === 'codex_native_computer_use_screenshot' || screen.capture_source === 'codex_computer_use_screenshot') ? 'native_computer_use_source_screenshot' : artifacts.inventory?.source_screens?.some((screen) => screen.capture_source === 'codex_chrome_extension_screenshot') ? 'chrome_extension_source_screenshot' : 'user_or_static_screenshot',
|
|
604
709
|
claims: {
|
|
605
710
|
ux_review_source_screenshot_verified: artifacts.inventory?.passed === true,
|
|
@@ -609,7 +714,7 @@ export function imageUxReviewProofEvidence(gate = {}, artifacts = {}) {
|
|
|
609
714
|
ux_review_changed_screens_rechecked: artifacts.recapture_plan?.changed_screens_rechecked_or_not_applicable === true,
|
|
610
715
|
ux_review_image_voxel_relations_verified: referenceOnly
|
|
611
716
|
? gate.source_reference_evidence?.ok === true
|
|
612
|
-
:
|
|
717
|
+
: gate.image_voxel_relations_created === true
|
|
613
718
|
},
|
|
614
719
|
full_verification_blockers: gate.full_verification_blockers || gate.blockers || [],
|
|
615
720
|
blockers: gate.blockers || []
|
|
@@ -668,6 +773,72 @@ async function ensureImageUxSourceReferenceEvidence(root, dir, inventory = {}) {
|
|
|
668
773
|
issues
|
|
669
774
|
};
|
|
670
775
|
}
|
|
776
|
+
async function ensureImageUxGeneratedRelationEvidence(root, dir, inventory = {}, generatedReviewLedger = {}, sourceReferenceEvidence = {}) {
|
|
777
|
+
const missionId = path.basename(String(dir));
|
|
778
|
+
const sourceScreen = (inventory.source_screens || []).find((screen) => screen.status === 'captured' && screen.source);
|
|
779
|
+
const generatedImages = (generatedReviewLedger.generated_review_images || [])
|
|
780
|
+
.filter((image) => image.real_generated === true && image.mock !== true && image.path);
|
|
781
|
+
if (!missionId || !sourceScreen || !generatedImages.length || sourceReferenceEvidence.ok !== true) {
|
|
782
|
+
return {
|
|
783
|
+
schema: 'sks.image-ux-generated-relation-evidence.v1',
|
|
784
|
+
ok: false,
|
|
785
|
+
reason: !missionId
|
|
786
|
+
? 'mission_id_missing'
|
|
787
|
+
: !sourceScreen
|
|
788
|
+
? 'captured_source_screenshot_missing'
|
|
789
|
+
: !generatedImages.length
|
|
790
|
+
? 'real_generated_image_missing'
|
|
791
|
+
: 'source_reference_anchor_missing',
|
|
792
|
+
relations: 0,
|
|
793
|
+
issues: []
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
const sourceImageId = `${missionId}-${sourceScreen.id}-source`;
|
|
797
|
+
const anchorIds = Array.isArray(sourceReferenceEvidence.anchor_ids) ? sourceReferenceEvidence.anchor_ids : [];
|
|
798
|
+
const relationIds = [];
|
|
799
|
+
const issues = [];
|
|
800
|
+
for (const image of generatedImages) {
|
|
801
|
+
const generatedImageId = `${missionId}-${image.id}`;
|
|
802
|
+
try {
|
|
803
|
+
const ingested = await ingestImage(root, image.path, {
|
|
804
|
+
missionId,
|
|
805
|
+
source: 'image-ux-review:gpt-image-2-generated-callout',
|
|
806
|
+
id: generatedImageId
|
|
807
|
+
});
|
|
808
|
+
if (!ingested.ok) {
|
|
809
|
+
issues.push(...(ingested.validation?.issues || [`generated_image_ingest_failed:${image.id}`]));
|
|
810
|
+
continue;
|
|
811
|
+
}
|
|
812
|
+
const relation = await addImageRelation(root, {
|
|
813
|
+
missionId,
|
|
814
|
+
route: '$Image-UX-Review',
|
|
815
|
+
type: 'generated_callout_review_of',
|
|
816
|
+
beforeImageId: sourceImageId,
|
|
817
|
+
afterImageId: generatedImageId,
|
|
818
|
+
sourceImageId,
|
|
819
|
+
generatedImageId,
|
|
820
|
+
anchors: anchorIds,
|
|
821
|
+
status: 'verified_partial',
|
|
822
|
+
verification: 'gpt-image-2-generated-callout-bound-to-source'
|
|
823
|
+
});
|
|
824
|
+
if (relation.ok)
|
|
825
|
+
relationIds.push(`${sourceImageId}->${generatedImageId}`);
|
|
826
|
+
else
|
|
827
|
+
issues.push(...(relation.validation?.issues || [`generated_image_relation_failed:${image.id}`]));
|
|
828
|
+
}
|
|
829
|
+
catch (err) {
|
|
830
|
+
issues.push(err instanceof Error ? err.message : String(err));
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
return {
|
|
834
|
+
schema: 'sks.image-ux-generated-relation-evidence.v1',
|
|
835
|
+
ok: relationIds.length === generatedImages.length && issues.length === 0,
|
|
836
|
+
relations: relationIds.length,
|
|
837
|
+
relation_ids: relationIds,
|
|
838
|
+
anchor_ids: anchorIds,
|
|
839
|
+
issues
|
|
840
|
+
};
|
|
841
|
+
}
|
|
671
842
|
async function ensureImageUxHonestModeEvidence(dir, parts = {}, opts = {}) {
|
|
672
843
|
const missionId = path.basename(String(dir));
|
|
673
844
|
const existing = await readExistingJson(dir, IMAGE_UX_REVIEW_HONEST_MODE_ARTIFACT);
|
|
@@ -744,6 +915,10 @@ export async function buildImageUxCalloutExtractionReport(root, extraction = {},
|
|
|
744
915
|
schema: 'sks.image-ux-callout-extraction-report.v1',
|
|
745
916
|
created_at: nowIso(),
|
|
746
917
|
provider: extraction.provider || opts.provider || 'unknown',
|
|
918
|
+
analysis_input: 'generated_annotated_review_image',
|
|
919
|
+
generated_image_is_primary_evidence: true,
|
|
920
|
+
source_screenshot_used_for_extraction: false,
|
|
921
|
+
generated_image_id: opts.generatedImageId || ledger.generated_image_id || issues[0]?.generated_review_image_id || null,
|
|
747
922
|
generated_image_path: generatedPath,
|
|
748
923
|
generated_image_sha256: generatedSha,
|
|
749
924
|
source_screenshot_sha256: sourceSha,
|
|
@@ -6,13 +6,20 @@ export const CODEX_LB_IMAGEGEN_TARGET_SCHEMA = 'sks.codex-lb-imagegen-target.v1'
|
|
|
6
6
|
export async function resolveCodexLbImagegenTarget(opts = {}) {
|
|
7
7
|
const env = opts.env || process.env;
|
|
8
8
|
const home = opts.home || env.HOME || os.homedir();
|
|
9
|
+
const codexHome = opts.codexHome || env.CODEX_HOME || path.join(home, '.codex');
|
|
9
10
|
const configText = typeof opts.configText === 'string'
|
|
10
11
|
? opts.configText
|
|
11
|
-
: await readText(path.join(
|
|
12
|
+
: await readText(path.join(codexHome, 'config.toml'), '').catch(() => '');
|
|
12
13
|
const selected = topLevelTomlString(configText, 'model_provider') === 'codex-lb';
|
|
13
|
-
const loaded = await loadCodexLbEnv({
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const loaded = await loadCodexLbEnv({
|
|
15
|
+
home,
|
|
16
|
+
processEnv: env,
|
|
17
|
+
envPath: path.join(codexHome, 'sks-codex-lb.env'),
|
|
18
|
+
legacyEnvPath: path.join(codexHome, 'sks.env'),
|
|
19
|
+
metadataPath: path.join(codexHome, 'sks-codex-lb.json')
|
|
20
|
+
}).catch(() => null);
|
|
21
|
+
const catalogModels = await readCatalogModels(configText, home, codexHome);
|
|
22
|
+
const explicit = String(opts.explicitModel || env.SKS_IMAGEGEN_RESPONSES_MODEL || '').trim();
|
|
16
23
|
const configuredModel = topLevelTomlString(configText, 'model');
|
|
17
24
|
const { model, model_source } = explicit
|
|
18
25
|
? { model: explicit, model_source: 'explicit' }
|
|
@@ -46,16 +53,17 @@ function codexLbImagegenBlocker(state) {
|
|
|
46
53
|
return 'codex_lb_imagegen_model_unresolved';
|
|
47
54
|
return null;
|
|
48
55
|
}
|
|
49
|
-
async function readCatalogModels(configText, home) {
|
|
56
|
+
async function readCatalogModels(configText, home, codexHome) {
|
|
50
57
|
const configured = topLevelTomlString(configText, 'model_catalog_json');
|
|
51
58
|
const candidates = [
|
|
52
|
-
configured ?
|
|
53
|
-
path.join(
|
|
59
|
+
configured ? resolveCatalogPath(configured, home, codexHome) : '',
|
|
60
|
+
path.join(codexHome, 'sks-codex-lb-tool-catalog.json')
|
|
54
61
|
].filter(Boolean);
|
|
55
62
|
for (const file of candidates) {
|
|
56
63
|
const payload = await readJson(file, null).catch(() => null);
|
|
57
64
|
const rows = Array.isArray(payload?.models) ? payload.models : Array.isArray(payload?.data) ? payload.data : [];
|
|
58
65
|
const slugs = rows
|
|
66
|
+
.filter((row) => row?.supported_in_api !== false && !hiddenCatalogRow(row))
|
|
59
67
|
.map((row) => String(row?.slug || row?.id || row?.model || '').trim())
|
|
60
68
|
.filter(Boolean);
|
|
61
69
|
if (slugs.length)
|
|
@@ -63,6 +71,13 @@ async function readCatalogModels(configText, home) {
|
|
|
63
71
|
}
|
|
64
72
|
return [];
|
|
65
73
|
}
|
|
74
|
+
function resolveCatalogPath(configured, home, codexHome) {
|
|
75
|
+
const expanded = configured.replace(/^~(?=\/|$)/, home);
|
|
76
|
+
return path.isAbsolute(expanded) ? expanded : path.resolve(codexHome, expanded);
|
|
77
|
+
}
|
|
78
|
+
function hiddenCatalogRow(row) {
|
|
79
|
+
return ['hide', 'hidden', 'internal', 'none', 'unavailable'].includes(String(row?.visibility || '').trim().toLowerCase());
|
|
80
|
+
}
|
|
66
81
|
function topLevelTomlString(text, key) {
|
|
67
82
|
const topLevel = String(text || '').split(/\n\s*\[/)[0] || '';
|
|
68
83
|
const re = new RegExp(`(^|\\n)\\s*${key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*=\\s*"([^"]*)"\\s*(?:#.*)?(?=\\n|$)`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import os from 'node:os';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { loadCodexLbEnv, parseShellEnvValue } from '../codex-lb/codex-lb-env.js';
|
|
4
4
|
import { nowIso, readText, runProcess, which } from '../fsx.js';
|
|
5
5
|
import { redactSecrets, redactString } from '../secret-redaction.js';
|
|
6
6
|
import { evaluateImagegenAuthReadiness } from './imagegen-auth-readiness.js';
|
|
@@ -97,7 +97,8 @@ export async function detectImagegenCapability(opts = {}) {
|
|
|
97
97
|
}
|
|
98
98
|
async function detectCodexLbImagegenAuth(opts = {}, env = process.env) {
|
|
99
99
|
const home = opts.home || env.HOME || process.env.HOME || os.homedir();
|
|
100
|
-
const
|
|
100
|
+
const codexHome = opts.codexHome || env.CODEX_HOME || path.join(home, '.codex');
|
|
101
|
+
const configPath = opts.configPath || path.join(codexHome, 'config.toml');
|
|
101
102
|
const configText = typeof opts.configText === 'string'
|
|
102
103
|
? opts.configText
|
|
103
104
|
: await readText(configPath, '').catch(() => '');
|
|
@@ -107,11 +108,17 @@ async function detectCodexLbImagegenAuth(opts = {}, env = process.env) {
|
|
|
107
108
|
const requiresOpenAiAuth = tomlBoolean(block, 'requires_openai_auth');
|
|
108
109
|
const envKey = tomlString(block, 'env_key');
|
|
109
110
|
const baseUrl = tomlString(block, 'base_url') || String(env.CODEX_LB_BASE_URL || '').trim();
|
|
110
|
-
const envPath = opts.codexLbEnvPath ||
|
|
111
|
+
const envPath = opts.codexLbEnvPath || path.join(codexHome, 'sks-codex-lb.env');
|
|
111
112
|
const injectedEnvText = typeof opts.codexLbEnvText === 'string' ? opts.codexLbEnvText : null;
|
|
112
113
|
const keyFromInjectedFile = injectedEnvText !== null && envKey ? parseShellEnvValue(injectedEnvText, envKey) : '';
|
|
113
114
|
const loaded = injectedEnvText === null
|
|
114
|
-
? await loadCodexLbEnv({
|
|
115
|
+
? await loadCodexLbEnv({
|
|
116
|
+
home,
|
|
117
|
+
processEnv: env,
|
|
118
|
+
envPath,
|
|
119
|
+
legacyEnvPath: path.join(codexHome, 'sks.env'),
|
|
120
|
+
metadataPath: path.join(codexHome, 'sks-codex-lb.json')
|
|
121
|
+
}).catch(() => null)
|
|
115
122
|
: null;
|
|
116
123
|
const apiKeyPresent = Boolean(opts.codexLbApiKey || keyFromInjectedFile || loaded?.secret_api_key);
|
|
117
124
|
const apiKeySource = opts.codexLbApiKey
|
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import { detectImagegenCapability } from './imagegen-capability.js';
|
|
2
2
|
import { repairCodexImagegen } from '../doctor/imagegen-repair.js';
|
|
3
3
|
export async function requireCodexImagegen(root, opts = {}) {
|
|
4
|
-
const
|
|
5
|
-
codexBin: opts.codexBin || undefined,
|
|
4
|
+
const capabilityOpts = {
|
|
6
5
|
timeoutMs: opts.timeoutMs || 5000
|
|
7
|
-
}
|
|
6
|
+
};
|
|
7
|
+
if (opts.codexBin !== undefined && opts.codexBin !== null)
|
|
8
|
+
capabilityOpts.codexBin = opts.codexBin;
|
|
9
|
+
if (opts.home !== undefined)
|
|
10
|
+
capabilityOpts.home = opts.home;
|
|
11
|
+
if (opts.codexHome !== undefined)
|
|
12
|
+
capabilityOpts.codexHome = opts.codexHome;
|
|
13
|
+
if (opts.env !== undefined)
|
|
14
|
+
capabilityOpts.env = opts.env;
|
|
15
|
+
if (opts.configText !== undefined)
|
|
16
|
+
capabilityOpts.configText = opts.configText;
|
|
17
|
+
if (opts.codexLbEnvText !== undefined)
|
|
18
|
+
capabilityOpts.codexLbEnvText = opts.codexLbEnvText;
|
|
19
|
+
const capability = await detectImagegenCapability(capabilityOpts).catch((err) => ({
|
|
8
20
|
ok: false,
|
|
9
21
|
core_ready: false,
|
|
10
22
|
blockers: [err instanceof Error ? err.message : String(err)]
|
|
11
23
|
}));
|
|
12
|
-
const capabilityReadyBeforeRepair = capability
|
|
24
|
+
const capabilityReadyBeforeRepair = imagegenPreflightReady(capability);
|
|
13
25
|
const repair = opts.autoRepair === true && !capabilityReadyBeforeRepair
|
|
14
26
|
? await repairCodexImagegen({
|
|
15
27
|
root,
|
|
@@ -25,7 +37,10 @@ export async function requireCodexImagegen(root, opts = {}) {
|
|
|
25
37
|
const finalCapability = repair
|
|
26
38
|
? repair.after || capability
|
|
27
39
|
: capability;
|
|
28
|
-
const capabilityReady = finalCapability
|
|
40
|
+
const capabilityReady = imagegenPreflightReady(finalCapability) || repair?.capability_ready === true;
|
|
41
|
+
const preflightProvider = finalCapability.core_ready === true
|
|
42
|
+
? 'codex_app_builtin'
|
|
43
|
+
: codexLbImagegenReady(finalCapability) ? 'codex_lb' : null;
|
|
29
44
|
const currentTaskToolManifestVerified = repair?.current_task_tool_manifest_verified === true;
|
|
30
45
|
const generatedOutputVerified = finalCapability.real_output_verified_by_capability_check === true
|
|
31
46
|
|| repair?.real_generation_verified === true;
|
|
@@ -55,6 +70,7 @@ export async function requireCodexImagegen(root, opts = {}) {
|
|
|
55
70
|
preflight_ready: preflightReady,
|
|
56
71
|
preflight_only: true,
|
|
57
72
|
preflight_does_not_satisfy_generated_output_proof: true,
|
|
73
|
+
preflight_provider: preflightProvider,
|
|
58
74
|
capability_ready: capabilityReady,
|
|
59
75
|
route_ready: routeReady,
|
|
60
76
|
current_task_tool_manifest_verified: currentTaskToolManifestVerified,
|
|
@@ -80,3 +96,11 @@ export async function requireCodexImagegen(root, opts = {}) {
|
|
|
80
96
|
blockers
|
|
81
97
|
};
|
|
82
98
|
}
|
|
99
|
+
function imagegenPreflightReady(capability) {
|
|
100
|
+
return capability?.core_ready === true || codexLbImagegenReady(capability);
|
|
101
|
+
}
|
|
102
|
+
function codexLbImagegenReady(capability) {
|
|
103
|
+
return capability?.codex_lb?.selected === true
|
|
104
|
+
&& capability?.codex_lb?.available === true
|
|
105
|
+
&& capability?.codex_lb?.blocker == null;
|
|
106
|
+
}
|
package/dist/core/init/skills.js
CHANGED
|
@@ -12,7 +12,7 @@ import { reconcileRetiredAgentRoleResidue } from '../agents/agent-role-config.js
|
|
|
12
12
|
import { ensureConfinedDirectory, inspectConfinedPath, moveConfinedPath, publicPathError, removeConfinedDirectoryIfEmpty, removeManagedPathVerified, uniqueConfinedPath } from '../managed-path-safety.js';
|
|
13
13
|
import { collectNestedProjectRoots } from '../doctor/current-project-guidance-nested.js';
|
|
14
14
|
import { coreEngineeringDirectiveReferenceText, engineeringSanityPolicyText } from '../lean-engineering-policy.js';
|
|
15
|
-
import { AWESOME_DESIGN_MD_REFERENCE, CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_ONLY_POLICY, CODEX_IMAGEGEN_EVIDENCE_SOURCE, CODEX_IMAGEGEN_REQUIRED_POLICY, CODEX_WEB_VERIFICATION_POLICY, DEFAULT_CODEX_APP_PLUGINS, DESIGN_SYSTEM_SSOT, DOLLAR_COMMANDS, DOLLAR_SKILL_NAMES, FROM_CHAT_IMG_CHECKLIST_ARTIFACT, FROM_CHAT_IMG_COVERAGE_ARTIFACT, FROM_CHAT_IMG_QA_LOOP_ARTIFACT, FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT, FROM_CHAT_IMG_TEMP_TRIWIKI_SESSIONS, GETDESIGN_REFERENCE, IMAGEGEN_SOCIAL_SOURCE_POLICY, LEGACY_DOLLAR_SKILL_NAMES, OPENAI_CHATGPT_IMAGES_2_DOC_URL, OPENAI_GPT_IMAGE_2_MODEL_DOC_URL, OPENAI_IMAGE_GENERATION_DOC_URL, PPT_CONDITIONAL_SKILL_ALLOWLIST, PPT_PIPELINE_MCP_ALLOWLIST, PPT_PIPELINE_SKILL_ALLOWLIST, RECOMMENDED_SKILLS, RESERVED_CODEX_PLUGIN_SKILL_NAMES, SOLUTION_SCOUT_SKILL_NAME, chatCaptureIntakeText, context7ConfigToml, getdesignReferencePolicyText,
|
|
15
|
+
import { AWESOME_DESIGN_MD_REFERENCE, CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_ONLY_POLICY, CODEX_IMAGEGEN_EVIDENCE_SOURCE, CODEX_IMAGEGEN_REQUIRED_POLICY, CODEX_WEB_VERIFICATION_POLICY, DEFAULT_CODEX_APP_PLUGINS, DESIGN_SYSTEM_SSOT, DOLLAR_COMMANDS, DOLLAR_SKILL_NAMES, FROM_CHAT_IMG_CHECKLIST_ARTIFACT, FROM_CHAT_IMG_COVERAGE_ARTIFACT, FROM_CHAT_IMG_QA_LOOP_ARTIFACT, FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT, FROM_CHAT_IMG_TEMP_TRIWIKI_SESSIONS, GETDESIGN_REFERENCE, IMAGEGEN_SOCIAL_SOURCE_POLICY, LEGACY_DOLLAR_SKILL_NAMES, OPENAI_CHATGPT_IMAGES_2_DOC_URL, OPENAI_GPT_IMAGE_2_MODEL_DOC_URL, OPENAI_IMAGE_GENERATION_DOC_URL, PPT_CONDITIONAL_SKILL_ALLOWLIST, PPT_PIPELINE_MCP_ALLOWLIST, PPT_PIPELINE_SKILL_ALLOWLIST, RECOMMENDED_SKILLS, RESERVED_CODEX_PLUGIN_SKILL_NAMES, SOLUTION_SCOUT_SKILL_NAME, chatCaptureIntakeText, context7ConfigToml, getdesignReferencePolicyText, outcomeRubricPolicyText, pptPipelineAllowlistPolicyText, productDesignPluginPolicyText, speedLanePolicyText, stackCurrentDocsPolicyText, triwikiContextTrackingText, triwikiStagePolicyText } from '../routes.js';
|
|
16
16
|
import { prefixKnownSksDollarReferences, sksPrefixedSkillName } from '../routes/dollar-prefix.js';
|
|
17
17
|
import { escapeRegExp } from '../text/regex.js';
|
|
18
18
|
const SKS_SKILL_MANIFEST_FILE = '.sks-generated.json';
|
|
@@ -21,6 +21,12 @@ const GENERATED_PRUNE_POLICY = 'remove_previous_sks_generated_paths_absent_from_
|
|
|
21
21
|
const REFLECTION_MEMORY_PATH = '.sneakoscope/memory/q2_facts/post-route-reflection.md';
|
|
22
22
|
const MANAGED_SKILL_MARKER_RE = /BEGIN SKS (?:IMMUTABLE CORE|MANAGED) SKILL/;
|
|
23
23
|
const FORGE_SKILL_MARKER_RE = /BEGIN SKS FORGE SKILL/;
|
|
24
|
+
const RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIASES = [
|
|
25
|
+
'sks-ux-review',
|
|
26
|
+
'sks-visual-review',
|
|
27
|
+
'sks-ui-ux-review'
|
|
28
|
+
];
|
|
29
|
+
const RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIAS_SET = new Set(RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIASES);
|
|
24
30
|
export const REMOVED_SKS_SKILL_NAMES = [
|
|
25
31
|
'old-workflow',
|
|
26
32
|
'team-legacy',
|
|
@@ -85,7 +91,6 @@ function reflectionInstructionText(commandPrefix = 'sks') {
|
|
|
85
91
|
async function installOfficialSkills(root) {
|
|
86
92
|
const quarantinedUserCollisions = [];
|
|
87
93
|
const quarantinedManifestCollisions = await prepareReservedSkillManifestsForWrite(root);
|
|
88
|
-
const imageUxReviewSkill = (name) => `---\nname: ${name}\ndescription: $Image-UX-Review/$UX-Review imagegen/gpt-image-2 annotated UI/UX review loop.\n---\n\nUse only for $Image-UX-Review, $UX-Review, $visual-review, or $ui-ux-review UI/UX review requests. ${imageUxReviewPipelinePolicyText()} Route start must check Codex App imagegen capability and run the SKS imagegen repair loop once; if $imagegen/gpt-image-2 is still unavailable, stop with codex_imagegen_unavailable instead of doing text-only review or direct API substitution. Core loop: capture or attach source UI screenshots, then invoke Codex App $imagegen with gpt-image-2 to create a new generated annotated review image from each source screenshot, then analyze the generated review image with vision/OCR into image-ux-issue-ledger.json, then apply only requested safe fixes and recheck changed screens. Text-only screenshot critique cannot satisfy full verification; missing generated annotated review images keep full image-ux-review-gate.json verification blocked, but may close verified_partial/reference-only when source screenshots plus hashes, docs evidence, source Image Voxel anchors, and Honest Mode evidence exist. For live web/browser/webapp capture use Codex Chrome Extension first and halt if it is not installed/enabled; use Codex Computer Use only for native Mac/non-web app screens. Required artifacts: image-ux-review-policy.json, image-ux-screen-inventory.json, image-ux-generated-review-ledger.json, image-ux-issue-ledger.json, image-ux-iteration-report.json, image-ux-review-gate.json. Finish with reflection and Honest Mode.\n`;
|
|
89
94
|
const canonicalMadSksSqlPlanePolicy = madSksSqlPlanePolicyText()
|
|
90
95
|
.replace(/^---[\s\S]*?---\s*/, '')
|
|
91
96
|
.trim();
|
|
@@ -136,10 +141,6 @@ async function installOfficialSkills(root) {
|
|
|
136
141
|
'gx-visual-validate': `---\nname: gx-visual-validate\ndescription: Validate render metadata against vgraph.json and beta.json.\n---\n\nRun sks gx validate and drift; fail stale or incomplete hashes, nodes, edges, invariants, or anchors.\n`,
|
|
137
142
|
'turbo-context-pack': `---\nname: turbo-context-pack\ndescription: Build ultra-low-token context packet with Q4 bits, Q3 tags, top-K claims, and minimal evidence.\n---\n\nDefault to Q4/Q3 plus TriWiki RGBA anchors and attention.use_first. Add Q2/Q1 only when needed or when attention.hydrate_first says source hydration is required. Keep id, hash, path, and coordinate tuple for hydration.\n`,
|
|
138
143
|
'performance-evaluator': `---\nname: performance-evaluator\ndescription: Evaluate SKS performance, evidence-backed token usage, serialized-size proxies, accuracy-proxy, context-compression, or workflow improvements.\n---\n\nUse sks eval run/compare before claims. Treat serialized_size_bytes as a deterministic non-token proxy. Claim token savings only when actual baseline and candidate token counts include an evidence source; otherwise report token savings as not measured. Report accuracy_delta/proxy, required_recall, support, and meaningful_improvement without substituting proxy size for token evidence.\n`,
|
|
139
|
-
'image-ux-review': imageUxReviewSkill('image-ux-review'),
|
|
140
|
-
'ux-review': imageUxReviewSkill('ux-review'),
|
|
141
|
-
'visual-review': imageUxReviewSkill('visual-review'),
|
|
142
|
-
'ui-ux-review': imageUxReviewSkill('ui-ux-review'),
|
|
143
144
|
'imagegen': `---\nname: imagegen\ndescription: Required bridge to Codex App built-in image generation for logos, image assets, raster visuals, and image edits.\n---\n\nUse for generated or edited image assets: logo, product image, illustration, sprite, mockup, texture, cutout, or bitmap. Prefer the official Codex App built-in image generation feature documented at ${CODEX_APP_IMAGE_GENERATION_DOC_URL}: ask naturally or invoke \`$imagegen\`. SKS route code checks capability before image-dependent routes, attempts doctor imagegen repair once, and reports codex_imagegen_unavailable if Codex App $imagegen still is not ready. For newest-model requests, make the prompt explicit: "Use ChatGPT Images 2.0 / GPT Image 2.0 with gpt-image-2." Useful official references are ${OPENAI_CHATGPT_IMAGES_2_DOC_URL}, ${OPENAI_GPT_IMAGE_2_MODEL_DOC_URL}, and ${OPENAI_IMAGE_GENERATION_DOC_URL}. Codex App image generation counts against Codex usage limits. Capability detection is not output proof; full SKS evidence requires a real selected raster output path or generated review image artifact. Direct OpenAI API fallback is non-Codex evidence and does not satisfy SKS route evidence unless a separate non-Codex API task is explicitly requested. ${IMAGEGEN_SOCIAL_SOURCE_POLICY} ${CODEX_IMAGEGEN_REQUIRED_POLICY} Do not substitute placeholder SVG/HTML/CSS for requested raster assets; follow design.md when relevant.\n`,
|
|
144
145
|
'imagegen-source-scout': `---\nname: imagegen-source-scout\ndescription: Source scout for current GPT Image 2.0/gpt-image-2 prompt guidance, official docs, and X/social workflow signals.\n---\n\nUse when the user asks for the latest imagegen docs, ChatGPT Images 2.0 / GPT Image 2.0 / gpt-image-2 behavior, X/social reactions, prompt examples, or community workflow hints before creating an image prompt or SKS imagegen policy. Source order: official OpenAI announcement (${OPENAI_CHATGPT_IMAGES_2_DOC_URL}), Codex App image generation docs (${CODEX_APP_IMAGE_GENERATION_DOC_URL}), gpt-image-2 model docs (${OPENAI_GPT_IMAGE_2_MODEL_DOC_URL}), OpenAI Image Generation API docs (${OPENAI_IMAGE_GENERATION_DOC_URL}), then public X/social/community search for prompt-quality heuristics only. ${IMAGEGEN_SOCIAL_SOURCE_POLICY} If social or web search is unavailable, record that social coverage is unverified and continue from official docs. Output a compact evidence split: official capability/evidence rules, prompt heuristics, social/workflow signals, and blockers. Do not generate images itself; pair this with the imagegen skill for actual raster output.\n`,
|
|
145
146
|
'getdesign-reference': `---\nname: getdesign-reference\ndescription: Use getdesign.md official design reference as an input to the design.md SSOT for UI/UX, presentation, and HTML/PDF systems.\n---\n\nUse when creating or improving design.md, UI/UX design systems, deck-like HTML artifacts, presentation PDFs, or brand-inspired visual systems. design.md is the only design decision SSOT; reference ${GETDESIGN_REFERENCE.url}, ${GETDESIGN_REFERENCE.docs_url}, and ${AWESOME_DESIGN_MD_REFERENCE.url} only as source inputs to synthesize or update that SSOT or a route-local style-token artifact. Prefer the official Codex skill if available with \`${GETDESIGN_REFERENCE.codex_skill_install}\`. If the skill CLI is unavailable, use this generated skill plus official docs/API/CLI/SDK references and curated DESIGN.md examples as inputs. Do not claim getdesign MCP is configured unless a current official MCP surface is actually installed.\n`,
|
|
@@ -907,7 +908,9 @@ function buildFallbackSkillsManifest() {
|
|
|
907
908
|
...RECOMMENDED_SKILLS.map((name) => canonicalSkillNameFromValue(name)),
|
|
908
909
|
...DOLLAR_COMMANDS.map((command) => canonicalSkillNameFromValue(String(command.command || '').replace(/^\$/, ''))),
|
|
909
910
|
...buildSksCoreSkillManifest().skills.map((skill) => skill.canonical_name)
|
|
910
|
-
].filter((name) => Boolean(name)
|
|
911
|
+
].filter((name) => Boolean(name)
|
|
912
|
+
&& !REMOVED_SKS_SKILL_NAME_SET.has(String(name))
|
|
913
|
+
&& !RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIAS_SET.has(String(name))));
|
|
911
914
|
return {
|
|
912
915
|
schema: PACKAGED_SKILLS_MANIFEST_SCHEMA,
|
|
913
916
|
package_version: PACKAGE_VERSION,
|
|
@@ -1161,7 +1164,7 @@ function isGeneratedSksPluginCollisionSkill(text, name) {
|
|
|
1161
1164
|
return /Maximum-speed \$Computer-Use\/\$CU lane|Codex App pipeline activation:|Sneakoscope generated|Dollar-command route generated by SKS/i.test(s);
|
|
1162
1165
|
}
|
|
1163
1166
|
function enrichSkillContent(name, content) {
|
|
1164
|
-
if (!['sks', 'answer', 'wiki', 'qa-loop', 'ppt', 'image-ux-review', '
|
|
1167
|
+
if (!['sks', 'answer', 'wiki', 'qa-loop', 'ppt', 'image-ux-review', 'computer-use-fast', 'cu', 'goal', 'research', 'autoresearch', 'db', 'gx', 'reflection', 'prompt-pipeline', 'pipeline-runner', 'context7-docs', 'turbo-context-pack', 'hproof-evidence-bind'].includes(name))
|
|
1165
1168
|
return content;
|
|
1166
1169
|
const text = String(content || '').trimEnd();
|
|
1167
1170
|
const activation = pipelineActivationText(name);
|
|
@@ -1179,7 +1182,7 @@ Context tracking:
|
|
|
1179
1182
|
`;
|
|
1180
1183
|
}
|
|
1181
1184
|
function pipelineActivationText(name) {
|
|
1182
|
-
const stateful = new Set(['sks', 'qa-loop', 'ppt', 'image-ux-review', '
|
|
1185
|
+
const stateful = new Set(['sks', 'qa-loop', 'ppt', 'image-ux-review', 'computer-use-fast', 'cu', 'goal', 'research', 'autoresearch', 'db', 'gx', 'prompt-pipeline', 'pipeline-runner']);
|
|
1183
1186
|
if (!stateful.has(name))
|
|
1184
1187
|
return '';
|
|
1185
1188
|
return `Codex App pipeline activation:
|
|
@@ -1229,6 +1232,7 @@ async function removeGeneratedAgentSkillAliases(root, skillNames) {
|
|
|
1229
1232
|
const current = new Set(skillNames);
|
|
1230
1233
|
const obsolete = [
|
|
1231
1234
|
...SKS_SKILL_NAMES_TO_CLEAN_UP,
|
|
1235
|
+
...RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIASES,
|
|
1232
1236
|
'qaloop',
|
|
1233
1237
|
'wiki-refresh',
|
|
1234
1238
|
'wikirefresh',
|
|
@@ -1242,7 +1246,7 @@ async function removeGeneratedAgentSkillAliases(root, skillNames) {
|
|
|
1242
1246
|
if (current.has(name))
|
|
1243
1247
|
continue;
|
|
1244
1248
|
const dir = path.join(root, '.agents', 'skills', name);
|
|
1245
|
-
const action = await cleanupGeneratedSkillResidue(root, dir, name, (text) => isGeneratedSksAgentSkill(text, name), 'generated-agent-skill-user-content-collision');
|
|
1249
|
+
const action = await cleanupGeneratedSkillResidue(root, dir, name, (text) => isGeneratedSksAgentSkill(text, name) || isRetiredGeneratedImageUxReviewAlias(text, name), 'generated-agent-skill-user-content-collision');
|
|
1246
1250
|
if (action === 'removed')
|
|
1247
1251
|
removed.push(path.relative(root, dir));
|
|
1248
1252
|
if (action === 'quarantined')
|
|
@@ -1282,6 +1286,14 @@ function isGeneratedSksAgentSkill(text, name) {
|
|
|
1282
1286
|
return false;
|
|
1283
1287
|
return /Sneakoscope generated|Fallback Codex App picker alias|Codex App picker alias for|Dollar-command route generated by SKS/i.test(s);
|
|
1284
1288
|
}
|
|
1289
|
+
function isRetiredGeneratedImageUxReviewAlias(text, name) {
|
|
1290
|
+
if (!RETIRED_PUBLIC_IMAGE_UX_REVIEW_SKILL_ALIAS_SET.has(String(name)))
|
|
1291
|
+
return false;
|
|
1292
|
+
const s = String(text || '');
|
|
1293
|
+
return MANAGED_SKILL_MARKER_RE.test(s)
|
|
1294
|
+
&& new RegExp(`^name:\\s*${escapeRegExp(name)}\\s*$`, 'm').test(s)
|
|
1295
|
+
&& /imagegen\/gpt-image-2 annotated UI\/UX review loop/i.test(s);
|
|
1296
|
+
}
|
|
1285
1297
|
function isGeneratedSksLegacySkill(text, name) {
|
|
1286
1298
|
if (typeof text !== 'string')
|
|
1287
1299
|
return false;
|