sneakoscope 4.2.1 → 4.3.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.
Files changed (102) hide show
  1. package/README.md +34 -7
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/crates/sks-core/src/main.rs +1 -1
  5. package/dist/bin/sks.js +1 -1
  6. package/dist/cli/command-registry.js +3 -1
  7. package/dist/cli/ultra-search-command.js +163 -0
  8. package/dist/cli/xai-command.js +28 -168
  9. package/dist/core/agents/agent-codex-cockpit.js +3 -3
  10. package/dist/core/agents/agent-runner-ollama.js +2 -0
  11. package/dist/core/agents/agent-wrongness.js +1 -1
  12. package/dist/core/agents/native-worker-backend-router.js +3 -0
  13. package/dist/core/bench.js +115 -0
  14. package/dist/core/code-structure.js +399 -11
  15. package/dist/core/codex-control/codex-fake-sdk-adapter.js +67 -9
  16. package/dist/core/codex-control/gpt-final-arbiter.js +4 -1
  17. package/dist/core/codex-control/gpt-final-review-schema.js +58 -0
  18. package/dist/core/codex-native/core-skill-manifest.js +23 -0
  19. package/dist/core/commands/bench-command.js +11 -2
  20. package/dist/core/commands/code-structure-command.js +34 -2
  21. package/dist/core/commands/run-command.js +92 -2
  22. package/dist/core/commands/seo-command.js +130 -0
  23. package/dist/core/feature-fixtures.js +6 -0
  24. package/dist/core/feature-registry.js +3 -1
  25. package/dist/core/fsx.js +1 -1
  26. package/dist/core/hooks-runtime.js +8 -0
  27. package/dist/core/init.js +8 -6
  28. package/dist/core/lean-engineering-policy.js +159 -0
  29. package/dist/core/pipeline-internals/runtime-core.js +15 -5
  30. package/dist/core/proof/auto-finalize.js +3 -2
  31. package/dist/core/proof/proof-schema.js +2 -1
  32. package/dist/core/proof/proof-writer.js +1 -0
  33. package/dist/core/proof/route-adapter.js +4 -2
  34. package/dist/core/proof/route-finalizer.js +35 -3
  35. package/dist/core/release-parallel-full-coverage.js +1 -1
  36. package/dist/core/routes.js +77 -10
  37. package/dist/core/search-visibility/adapter-registry.js +26 -0
  38. package/dist/core/search-visibility/adapters/next-app.js +6 -0
  39. package/dist/core/search-visibility/adapters/next-pages.js +6 -0
  40. package/dist/core/search-visibility/adapters/static-site.js +6 -0
  41. package/dist/core/search-visibility/analyzers.js +377 -0
  42. package/dist/core/search-visibility/artifacts.js +183 -0
  43. package/dist/core/search-visibility/discovery.js +347 -0
  44. package/dist/core/search-visibility/index.js +199 -0
  45. package/dist/core/search-visibility/mission.js +67 -0
  46. package/dist/core/search-visibility/mutation.js +314 -0
  47. package/dist/core/search-visibility/types.js +2 -0
  48. package/dist/core/search-visibility/verifier.js +60 -0
  49. package/dist/core/source-intelligence/source-intelligence-policy.js +45 -26
  50. package/dist/core/source-intelligence/source-intelligence-proof.js +10 -16
  51. package/dist/core/source-intelligence/source-intelligence-runner.js +56 -42
  52. package/dist/core/trust-kernel/trust-report.js +3 -5
  53. package/dist/core/ultra-search/index.js +3 -0
  54. package/dist/core/ultra-search/runtime.js +502 -0
  55. package/dist/core/ultra-search/types.js +3 -0
  56. package/dist/core/version.js +1 -1
  57. package/dist/scripts/agent-visual-consistency-check.js +1 -1
  58. package/dist/scripts/check-architecture.js +40 -7
  59. package/dist/scripts/check-command-module-budget.js +43 -5
  60. package/dist/scripts/check-pipeline-budget.js +17 -30
  61. package/dist/scripts/check-publish-tag.js +33 -6
  62. package/dist/scripts/check-route-modularity.js +25 -33
  63. package/dist/scripts/check-runtime-schemas.js +22 -0
  64. package/dist/scripts/core-skill-immutable-sync-check.js +3 -2
  65. package/dist/scripts/core-skill-integrity-blackbox.js +3 -2
  66. package/dist/scripts/core-skill-manifest-check.js +7 -2
  67. package/dist/scripts/geo-claim-evidence-check.js +18 -0
  68. package/dist/scripts/geo-cli-blackbox-check.js +18 -0
  69. package/dist/scripts/geo-crawler-policy-check.js +16 -0
  70. package/dist/scripts/geo-llms-txt-optional-check.js +19 -0
  71. package/dist/scripts/gpt-final-arbiter-check.js +4 -1
  72. package/dist/scripts/release-metadata-1-19-check.js +2 -2
  73. package/dist/scripts/release-parallel-check.js +17 -2
  74. package/dist/scripts/release-parallel-full-coverage-check.js +1 -1
  75. package/dist/scripts/release-readiness-report.js +6 -6
  76. package/dist/scripts/release-registry-check.js +33 -14
  77. package/dist/scripts/search-visibility-gate-lib.js +124 -0
  78. package/dist/scripts/seo-audit-fixture-check.js +16 -0
  79. package/dist/scripts/seo-canonical-locale-check.js +19 -0
  80. package/dist/scripts/seo-cli-blackbox-check.js +18 -0
  81. package/dist/scripts/seo-geo-feature-fixture-quality-check.js +18 -0
  82. package/dist/scripts/seo-geo-geo-disambiguation-check.js +12 -0
  83. package/dist/scripts/seo-geo-no-unsupported-ranking-claims-check.js +18 -0
  84. package/dist/scripts/seo-geo-route-identity-check.js +12 -0
  85. package/dist/scripts/seo-geo-skill-rich-content-check.js +22 -0
  86. package/dist/scripts/seo-mutation-rollback-check.js +23 -0
  87. package/dist/scripts/seo-no-mutation-by-default-check.js +17 -0
  88. package/dist/scripts/seo-structured-data-visible-content-check.js +19 -0
  89. package/dist/scripts/sks-1-18-gate-lib.js +2 -2
  90. package/dist/scripts/sks-3-1-5-directive-check-lib.js +10 -1
  91. package/dist/scripts/source-intelligence-all-modes-check.js +9 -19
  92. package/dist/scripts/source-intelligence-policy-check.js +6 -6
  93. package/dist/scripts/ultra-search-provider-interface-check.js +27 -0
  94. package/package.json +21 -3
  95. package/schemas/search-visibility/finding-ledger.schema.json +36 -0
  96. package/schemas/search-visibility/gate.schema.json +22 -0
  97. package/schemas/search-visibility/mutation-plan.schema.json +27 -0
  98. package/schemas/search-visibility/site-inventory.schema.json +21 -0
  99. package/schemas/search-visibility/verification-report.schema.json +23 -0
  100. package/dist/core/mcp/xai-mcp-detector.js +0 -157
  101. package/dist/core/mcp/xai-search-adapter.js +0 -100
  102. package/dist/scripts/xai-mcp-capability-check.js +0 -14
@@ -27,22 +27,44 @@ export async function runFakeCodexSdkTask(input) {
27
27
  }
28
28
  function fakeStructuredOutput(input) {
29
29
  if (input.outputSchemaId === GPT_FINAL_ARBITER_RESULT_SCHEMA_ID) {
30
- const unsafe = /\b(truncate|delete all|drop table|credential)\b/i.test(input.prompt || '');
30
+ const prompt = String(input.prompt || '');
31
+ const leanEnabled = /\b(Lean review|Lean Engineering Policy|sks\.lean-engineering-policy)\b/i.test(prompt);
32
+ const unsafe = /\b(truncate|delete all|drop table|credential|delete validation|validation removed|path traversal|sql injection|secret leak)\b/i.test(prompt);
33
+ const overbuild = leanEnabled ? classifyLeanOverbuild(prompt) : null;
34
+ const status = unsafe ? 'rejected' : overbuild ? 'needs_more_work' : 'approved';
35
+ const leanStatus = unsafe ? 'rejected' : overbuild ? 'needs_more_work' : 'pass';
36
+ const blockers = unsafe ? ['unsafe_candidate_patch'] : overbuild?.blockers || [];
37
+ const findings = unsafe
38
+ ? [{ id: 'unsafe-candidate', severity: 'high', summary: 'unsafe candidate rejected' }]
39
+ : overbuild ? overbuild.findings : [];
31
40
  return {
32
41
  schema: GPT_FINAL_ARBITER_RESULT_SCHEMA_ID,
33
- status: unsafe ? 'rejected' : 'approved',
42
+ status,
34
43
  summary: unsafe
35
44
  ? 'Fake Codex SDK GPT final arbiter rejected an unsafe candidate for hermetic verification.'
36
- : 'Fake Codex SDK GPT final arbiter approved the candidate for hermetic verification.',
37
- gpt_review_findings: unsafe ? [{ id: 'unsafe-candidate', severity: 'high', summary: 'unsafe candidate rejected' }] : [],
38
- accepted_patch_envelopes: unsafe ? [] : [],
45
+ : overbuild
46
+ ? 'Fake Codex SDK GPT final arbiter requested a leaner candidate for hermetic verification.'
47
+ : 'Fake Codex SDK GPT final arbiter approved the candidate for hermetic verification.',
48
+ gpt_review_findings: findings,
49
+ accepted_patch_envelopes: status === 'approved' ? [] : [],
39
50
  modified_patch_envelopes: [],
40
- rejected_patch_envelopes: unsafe ? [{ id: 'unsafe-candidate', summary: 'unsafe candidate', patch_envelope_json: '{}' }] : [],
41
- required_followup_work: unsafe ? [{ id: 'unsafe_candidate_patch', severity: 'high', summary: 'unsafe_candidate_patch' }] : [],
51
+ rejected_patch_envelopes: status === 'rejected' ? [{ id: blockers[0] || 'rejected-candidate', summary: blockers[0] || 'rejected candidate', patch_envelope_json: '{}' }] : [],
52
+ required_followup_work: blockers.map((blocker) => ({ id: blocker, severity: unsafe ? 'high' : 'medium', summary: blocker })),
42
53
  verification_plan: ['schema validation', 'local collaboration final gate'],
43
54
  rollback_notes: [],
44
- blockers: unsafe ? ['unsafe_candidate_patch'] : [],
45
- confidence: unsafe ? 'medium' : 'high'
55
+ blockers,
56
+ lean_review: {
57
+ status: leanStatus,
58
+ selected_rung: unsafe ? 'unknown' : overbuild?.selected_rung || 'minimal-custom',
59
+ unnecessary_files: [],
60
+ unnecessary_dependencies: overbuild?.unnecessary_dependencies || [],
61
+ unnecessary_abstractions: overbuild?.unnecessary_abstractions || [],
62
+ fallback_findings: unsafe ? ['unsafe_candidate_patch'] : overbuild?.fallback_findings || [],
63
+ root_cause_review: overbuild?.root_cause_review || [],
64
+ verification_minimum_present: !unsafe && !/\b(missing runnable check|no runnable check)\b/i.test(prompt),
65
+ net_lines: null
66
+ },
67
+ confidence: unsafe || overbuild ? 'medium' : 'high'
46
68
  };
47
69
  }
48
70
  return {
@@ -56,4 +78,40 @@ function fakeStructuredOutput(input) {
56
78
  blockers: []
57
79
  };
58
80
  }
81
+ function classifyLeanOverbuild(prompt) {
82
+ if (/\b(existing helper reimplementation|same helper reimplementation|reimplement existing helper)\b/i.test(prompt)) {
83
+ return leanFinding('reuse_existing_helper', 'reuse-existing', 'Candidate reimplements an existing helper instead of reusing the repository authority.', {
84
+ root_cause_review: ['reuse existing helper or fix the common helper once']
85
+ });
86
+ }
87
+ if (/\b(new dependency|dependency bloat|native platform instead of dependency)\b/i.test(prompt)) {
88
+ return leanFinding('unnecessary_dependency', 'stdlib', 'Candidate adds a dependency where stdlib or platform support is sufficient.', {
89
+ unnecessary_dependencies: ['unjustified dependency']
90
+ });
91
+ }
92
+ if (/\b(one implementation factory|single implementation factory|one implementation interface)\b/i.test(prompt)) {
93
+ return leanFinding('single_impl_abstraction', 'minimal-custom', 'Candidate adds an abstraction without a second implementation or real variation axis.', {
94
+ unnecessary_abstractions: ['single implementation factory/interface']
95
+ });
96
+ }
97
+ if (/\b(hidden mock fallback|silent mock fallback|fixture fallback)\b/i.test(prompt)) {
98
+ return leanFinding('hidden_fallback', 'minimal-custom', 'Candidate hides a production failure behind a mock or fixture fallback.', {
99
+ fallback_findings: ['hidden mock fallback']
100
+ });
101
+ }
102
+ if (/\b(caller duplicate guard|duplicate caller guard|symptom patch)\b/i.test(prompt)) {
103
+ return leanFinding('root_cause_missing', 'minimal-custom', 'Candidate patches a caller symptom instead of the shared root cause.', {
104
+ root_cause_review: ['move duplicated guard to the shared root-cause helper']
105
+ });
106
+ }
107
+ return null;
108
+ }
109
+ function leanFinding(id, selectedRung, summary, extra = {}) {
110
+ return {
111
+ selected_rung: selectedRung,
112
+ blockers: [id],
113
+ findings: [{ id, severity: 'medium', summary }],
114
+ ...extra
115
+ };
116
+ }
59
117
  //# sourceMappingURL=codex-fake-sdk-adapter.js.map
@@ -5,6 +5,7 @@ import { evaluateLocalCollaborationFinalGate, resolveLocalCollaborationPolicy }
5
5
  import { runCodexTask } from './codex-control-plane.js';
6
6
  import { GPT_FINAL_ARBITER_INPUT_SCHEMA, GPT_FINAL_ARBITER_RESULT_SCHEMA_ID, gptFinalArbiterResultSchema, normalizeGptFinalArbiterResult } from './gpt-final-review-schema.js';
7
7
  import { compressGptFinalContext } from './gpt-final-context-compressor.js';
8
+ import { leanEngineeringCompactText } from '../lean-engineering-policy.js';
8
9
  export const GPT_FINAL_ARBITER_RUN_SCHEMA = 'sks.gpt-final-arbiter-run.v1';
9
10
  export async function runGptFinalArbiter(input, opts = {}) {
10
11
  const started = Date.now();
@@ -145,7 +146,9 @@ function buildArbiterPrompt(input, compressed) {
145
146
  return [
146
147
  'You are the GPT Final Arbiter for an SKS local collaboration run.',
147
148
  'Local model outputs are drafts only. Review the proof pack, candidate diff, patch envelopes, verification results, side effects, mutation ledger, and rollback plan.',
148
- 'Approve or modify only when the candidate is safe and supported. Reject unsafe local patches. Return only the requested structured JSON schema.',
149
+ leanEngineeringCompactText(),
150
+ 'Lean review: check for reused helpers before reimplementation, unjustified dependencies, one-implementation factories/interfaces, hidden mock or provider fallbacks, duplicated caller guards instead of root-cause fixes, forwarding-only files, missing runnable checks for non-trivial logic, and safety/validation removal disguised as simplification.',
151
+ 'Approve or modify only when the candidate is safe, supported, and no more complex than the request requires. Reject unsafe local patches. Return only the requested structured JSON schema.',
149
152
  JSON.stringify({
150
153
  route: input.route,
151
154
  mission_id: input.mission_id,
@@ -1,3 +1,4 @@
1
+ import { LEAN_SOLUTION_RUNGS } from '../lean-engineering-policy.js';
1
2
  export const GPT_FINAL_ARBITER_RESULT_SCHEMA_ID = 'sks.gpt-final-arbiter-result.v1';
2
3
  export const GPT_FINAL_ARBITER_INPUT_SCHEMA = 'sks.gpt-final-arbiter-input.v1';
3
4
  const reviewItemSchema = {
@@ -20,6 +21,32 @@ const patchDecisionSchema = {
20
21
  },
21
22
  additionalProperties: false
22
23
  };
24
+ const leanReviewSchema = {
25
+ type: 'object',
26
+ required: [
27
+ 'status',
28
+ 'selected_rung',
29
+ 'unnecessary_files',
30
+ 'unnecessary_dependencies',
31
+ 'unnecessary_abstractions',
32
+ 'fallback_findings',
33
+ 'root_cause_review',
34
+ 'verification_minimum_present',
35
+ 'net_lines'
36
+ ],
37
+ properties: {
38
+ status: { enum: ['pass', 'modified', 'rejected', 'needs_more_work'] },
39
+ selected_rung: { enum: [...LEAN_SOLUTION_RUNGS, 'unknown'] },
40
+ unnecessary_files: { type: 'array', items: { type: 'string' } },
41
+ unnecessary_dependencies: { type: 'array', items: { type: 'string' } },
42
+ unnecessary_abstractions: { type: 'array', items: { type: 'string' } },
43
+ fallback_findings: { type: 'array', items: { type: 'string' } },
44
+ root_cause_review: { type: 'array', items: { type: 'string' } },
45
+ verification_minimum_present: { type: 'boolean' },
46
+ net_lines: { type: ['number', 'null'] }
47
+ },
48
+ additionalProperties: false
49
+ };
23
50
  export const gptFinalArbiterResultSchema = {
24
51
  type: 'object',
25
52
  required: [
@@ -34,6 +61,7 @@ export const gptFinalArbiterResultSchema = {
34
61
  'verification_plan',
35
62
  'rollback_notes',
36
63
  'blockers',
64
+ 'lean_review',
37
65
  'confidence'
38
66
  ],
39
67
  properties: {
@@ -48,6 +76,7 @@ export const gptFinalArbiterResultSchema = {
48
76
  verification_plan: { type: 'array', items: { type: 'string' } },
49
77
  rollback_notes: { type: 'array', items: { type: 'string' } },
50
78
  blockers: { type: 'array', items: { type: 'string' } },
79
+ lean_review: leanReviewSchema,
51
80
  confidence: { enum: ['low', 'medium', 'high'] }
52
81
  },
53
82
  additionalProperties: false
@@ -66,6 +95,7 @@ export function normalizeGptFinalArbiterResult(value) {
66
95
  verification_plan: stringArray(value?.verification_plan),
67
96
  rollback_notes: stringArray(value?.rollback_notes),
68
97
  blockers: stringArray(value?.blockers),
98
+ lean_review: normalizeLeanReview(value?.lean_review, status),
69
99
  confidence: normalizeConfidence(value?.confidence)
70
100
  };
71
101
  }
@@ -107,6 +137,34 @@ function patchDecisionItems(value) {
107
137
  function stringArray(value) {
108
138
  return Array.isArray(value) ? value.map((entry) => String(entry || '').trim()).filter(Boolean) : [];
109
139
  }
140
+ function normalizeLeanReview(value, arbiterStatus) {
141
+ const raw = typeof value === 'object' && value !== null ? value : {};
142
+ return {
143
+ status: normalizeLeanReviewStatus(raw.status, arbiterStatus),
144
+ selected_rung: normalizeLeanRung(raw.selected_rung),
145
+ unnecessary_files: stringArray(raw.unnecessary_files),
146
+ unnecessary_dependencies: stringArray(raw.unnecessary_dependencies),
147
+ unnecessary_abstractions: stringArray(raw.unnecessary_abstractions),
148
+ fallback_findings: stringArray(raw.fallback_findings),
149
+ root_cause_review: stringArray(raw.root_cause_review),
150
+ verification_minimum_present: typeof raw.verification_minimum_present === 'boolean' ? raw.verification_minimum_present : arbiterStatus === 'approved' || arbiterStatus === 'modified',
151
+ net_lines: Number.isFinite(Number(raw.net_lines)) ? Number(raw.net_lines) : null
152
+ };
153
+ }
154
+ function normalizeLeanReviewStatus(value, arbiterStatus) {
155
+ if (value === 'pass' || value === 'modified' || value === 'rejected' || value === 'needs_more_work')
156
+ return value;
157
+ if (arbiterStatus === 'approved')
158
+ return 'pass';
159
+ if (arbiterStatus === 'modified')
160
+ return 'modified';
161
+ if (arbiterStatus === 'rejected')
162
+ return 'rejected';
163
+ return 'needs_more_work';
164
+ }
165
+ function normalizeLeanRung(value) {
166
+ return typeof value === 'string' && [...LEAN_SOLUTION_RUNGS, 'unknown'].includes(value) ? value : 'unknown';
167
+ }
110
168
  function normalizeSeverity(value) {
111
169
  return value === 'low' || value === 'medium' || value === 'high' ? value : 'medium';
112
170
  }
@@ -1,4 +1,5 @@
1
1
  import { PACKAGE_VERSION, nowIso, sha256 } from '../fsx.js';
2
+ import { leanPolicyReference } from '../lean-engineering-policy.js';
2
3
  import { canonicalSkillName } from './skill-name-canonicalizer.js';
3
4
  export const CORE_SKILL_TEMPLATE_VERSION = 'sks-core-skill-template.v1';
4
5
  export const CORE_SKILL_MANAGED_BEGIN = '<!-- BEGIN SKS IMMUTABLE CORE SKILL -->';
@@ -83,6 +84,26 @@ const CORE_SKILL_DEFINITIONS = [
83
84
  when: 'Use when deeper local context or directory-specific recall is required.',
84
85
  evidence: '.sneakoscope/context/AGENTS.generated.md and managed memory artifacts.',
85
86
  fallback: 'Preserve user content and skip directories that cannot be safely updated.'
87
+ },
88
+ {
89
+ id: 'sks-core-search-visibility-core',
90
+ canonical_name: 'search-visibility-core',
91
+ display_name: 'search-visibility-core',
92
+ route: '$SEO-GEO-OPTIMIZER',
93
+ purpose: 'provide the shared search-visibility kernel for SEO and GEO audit, plan, explicit apply, verify, rollback, and Completion Proof without ranking, traffic, or citation guarantees.',
94
+ when: 'Use when $SEO-GEO-OPTIMIZER or sks seo-geo-optimizer needs typed mode-specific evidence, gates, artifacts, or safe mutation planning.',
95
+ evidence: 'search-visibility artifacts, seo-gate.json or geo-gate.json, mutation-plan.json, rollback-manifest.json, verification-report.json, and completion-proof.json.',
96
+ fallback: 'Keep unsupported frameworks plan-only, record unverified production/browser/Search Console/AI citation outcomes, and never invent guarantee evidence.'
97
+ },
98
+ {
99
+ id: 'sks-core-seo-geo-optimizer',
100
+ canonical_name: 'seo-geo-optimizer',
101
+ display_name: 'seo-geo-optimizer',
102
+ route: '$SEO-GEO-OPTIMIZER',
103
+ purpose: 'run the unified SEO/GEO optimizer route for Search Engine Optimization and Generative Engine Optimization, not geolocation or GeoIP, with no ranking, traffic, indexing, rich-result, answer inclusion, or AI citation guarantee.',
104
+ when: 'Use the CLI entrypoint: sks seo-geo-optimizer doctor|audit|plan|apply|verify|status|rollback|fixture --mode seo|geo for SEO and GEO visibility work.',
105
+ evidence: 'site inventory, route graph, seo-findings.json or geo-findings.json, claim-evidence-ledger.json, ai-crawler-policy.json, llms-txt-plan.json, verification report, route gate, and Completion Proof.',
106
+ fallback: 'Do not auto-allow training crawlers or fabricate AI answer visibility; mark missing live outcomes unverified and keep recovery on the unified optimizer route.'
86
107
  }
87
108
  ];
88
109
  export function coreSkillDefinitions() {
@@ -97,6 +118,7 @@ export function renderCoreSkillTemplate(name) {
97
118
  const skill = CORE_SKILL_DEFINITIONS.find((entry) => entry.canonical_name === canonical);
98
119
  if (!skill)
99
120
  throw new Error(`Unknown SKS core skill: ${name}`);
121
+ const lean = leanPolicyReference();
100
122
  return [
101
123
  '---',
102
124
  `name: ${skill.display_name}`,
@@ -117,6 +139,7 @@ export function renderCoreSkillTemplate(name) {
117
139
  `Command: ${skill.route}`,
118
140
  `Purpose: ${skill.purpose}`,
119
141
  `Use when: ${skill.when}`,
142
+ `Lean policy: ${lean.policy_id}/${lean.policy_hash}`,
120
143
  `Proof paths: ${skill.evidence}`,
121
144
  'Safety rules: preserve user-authored skills, keep route state bounded, and stop on hard blockers instead of fabricating fallback behavior.',
122
145
  `Failure recovery: ${skill.fallback}`,
@@ -1,4 +1,4 @@
1
- import { TRUST_VALIDATE_BENCH_COMMAND, benchRoot, runCoreBench } from '../bench.js';
1
+ import { TRUST_VALIDATE_BENCH_COMMAND, benchRoot, runCoreBench, runLeanPolicyBench } from '../bench.js';
2
2
  import { runProcess } from '../fsx.js';
3
3
  import { flag, readFlagValue } from './command-utils.js';
4
4
  export async function benchCommand(args = []) {
@@ -18,9 +18,18 @@ export async function benchCommand(args = []) {
18
18
  }
19
19
  if (action === 'route-fixtures')
20
20
  return commandBench('sks.route-fixture-bench.v1', ['all-features', 'selftest', '--mock', '--execute-fixtures', '--strict-artifacts', '--json'], args);
21
+ if (action === 'lean-policy') {
22
+ const report = await runLeanPolicyBench(root);
23
+ if (!report.ok)
24
+ process.exitCode = 1;
25
+ if (flag(args, '--json'))
26
+ return console.log(JSON.stringify(report, null, 2));
27
+ console.log(`lean-policy: ${report.ok ? 'pass' : 'blocked'}`);
28
+ return report;
29
+ }
21
30
  if (action === 'blackbox')
22
31
  return commandBench('sks.blackbox-bench.v1', ['blackbox-matrix-placeholder'], args);
23
- console.error('Usage: sks bench core|route-fixtures|blackbox|trust-kernel [--json] [--iterations N]');
32
+ console.error('Usage: sks bench core|route-fixtures|lean-policy|blackbox|trust-kernel [--json] [--iterations N]');
24
33
  process.exitCode = 2;
25
34
  }
26
35
  async function commandBench(schema, commandArgs, args = []) {
@@ -4,18 +4,50 @@ import { flag } from './command-utils.js';
4
4
  export async function codeStructureCommand(sub, args = []) {
5
5
  const action = sub || 'scan';
6
6
  if (action !== 'scan') {
7
- console.error('Usage: sks code-structure scan [--json]');
7
+ console.error('Usage: sks code-structure scan [--json] [--all] [--changed [ref|file[,file]]] [--changed-since <ref>]');
8
8
  process.exitCode = 1;
9
9
  return;
10
10
  }
11
11
  const root = await sksRoot();
12
- const report = await scanCodeStructure(root, { includeOk: flag(args, '--all') });
12
+ const changedArg = valueAfter(args, '--changed');
13
+ const changedSince = valueAfter(args, '--changed-since');
14
+ const changedArgLooksLikeFiles = Boolean(changedArg && (changedArg.includes(',')
15
+ || changedArg.includes('/')
16
+ || changedArg.includes('\\')
17
+ || /\.(js|ts|tsx|jsx|mjs|cjs|json|md|rs|toml)$/i.test(changedArg)));
18
+ const changedFiles = changedArg && changedArgLooksLikeFiles
19
+ ? changedArg.split(',').map((file) => file.trim()).filter(Boolean)
20
+ : [];
21
+ const report = await scanCodeStructure(root, {
22
+ includeOk: flag(args, '--all'),
23
+ changed: flag(args, '--changed') ? (changedFiles.length ? true : changedArg || true) : false,
24
+ changedSince,
25
+ changedFiles
26
+ });
13
27
  if (flag(args, '--json'))
14
28
  return console.log(JSON.stringify(report, null, 2));
15
29
  console.log('SKS Code Structure');
30
+ if (report.changed_scope?.mode !== 'full') {
31
+ console.log(`Changed scope: ${report.changed_scope.changed_files.length} files, ${report.changed_scope.net_lines} net lines`);
32
+ console.log(`Lean semantic review: ${report.semantic_review?.status || 'unknown'}`);
33
+ }
16
34
  for (const file of report.files.slice(0, 20))
17
35
  console.log(`${file.status} ${file.line_count} ${file.path}`);
18
36
  if (report.remaining_risks.length)
19
37
  console.log(`Risks: ${report.remaining_risks.join(', ')}`);
38
+ if (report.semantic_review?.findings?.length) {
39
+ for (const finding of report.semantic_review.findings.slice(0, 8)) {
40
+ console.log(`Lean ${finding.severity}: ${finding.file ? `${finding.file}: ` : ''}${finding.summary}`);
41
+ }
42
+ }
43
+ }
44
+ function valueAfter(args, name) {
45
+ const index = args.indexOf(name);
46
+ if (index === -1)
47
+ return null;
48
+ const value = args[index + 1];
49
+ if (!value || String(value).startsWith('--'))
50
+ return null;
51
+ return String(value);
20
52
  }
21
53
  //# sourceMappingURL=code-structure-command.js.map
@@ -4,6 +4,7 @@ import { createMission, missionDir, setCurrent } from '../mission.js';
4
4
  import { maybeFinalizeRoute } from '../proof/auto-finalize.js';
5
5
  import { routePrompt } from '../routes.js';
6
6
  import { latestTrustReport } from '../trust-kernel/trust-report.js';
7
+ import { normalizeTrustStatus, TRUST_REPORT_SCHEMA, trustKernelMetadata } from '../trust-kernel/trust-kernel-schema.js';
7
8
  import { flag, positionalArgs } from './command-utils.js';
8
9
  export async function runCommand(args = []) {
9
10
  const root = await projectRoot();
@@ -135,8 +136,11 @@ async function executeRunRoute(root, context) {
135
136
  blockers: execution.ok ? [] : execution.blockers,
136
137
  unverified: execution.unverified,
137
138
  command: { cmd: execution.command || `sks run "${prompt}" --execute`, status: execution.exit_code ?? (execution.ok ? 0 : 2) },
139
+ lightweightEvidence: execution.execution_kind === 'safe_deterministic',
138
140
  });
139
- const trust = await loadTrustReport(root, id);
141
+ const trust = execution.execution_kind === 'safe_deterministic'
142
+ ? await writeLightweightTrustReport(root, id, route.command, statusHint, proof.ok)
143
+ : await loadTrustReport(root, id);
140
144
  const autoVerification = auto ? await runAutoVerification(root, id) : null;
141
145
  const autoOk = autoVerification?.ok ?? true;
142
146
  await setCurrent(root, {
@@ -231,7 +235,7 @@ async function executeRouteCommand(root, route, prompt, { auto = false } = {}) {
231
235
  return routeExecutionResult(route, ['sks', ...commandArgs].join(' '), result, {
232
236
  okStatus: 'completed',
233
237
  trustStatus: 'verified_partial',
234
- executionKind: route.command === '$DB' || route.command === '$Wiki' || route.command === '$Fast-Mode' || route.command === '$with-local-llm-on' || route.command === '$Commit' || route.command === '$Commit-And-Push' ? 'safe_deterministic' : 'mock_safe',
238
+ executionKind: route.command === '$DB' || route.command === '$Wiki' || route.command === '$Fast-Mode' || route.command === '$with-local-llm-on' || route.command === '$Commit' || route.command === '$Commit-And-Push' || route.command === '$Ultra-Search' || route.command === '$SEO-GEO-OPTIMIZER' ? 'safe_deterministic' : 'mock_safe',
235
239
  });
236
240
  }
237
241
  async function runAutoVerification(root, missionId) {
@@ -342,6 +346,10 @@ function runNextAction(route, id, args) {
342
346
  function safeRouteExecutionArgs(route, prompt, { auto = false } = {}) {
343
347
  if (route.command === '$DB')
344
348
  return ['db', 'check', '--sql', 'SELECT 1', '--json'];
349
+ if (route.command === '$Ultra-Search')
350
+ return ultraSearchExecutionArgs(prompt);
351
+ if (route.command === '$SEO-GEO-OPTIMIZER')
352
+ return ['seo-geo-optimizer', searchVisibilityActionFromPrompt(prompt), '--mode', searchVisibilityModeFromPrompt(prompt), '--target', searchVisibilityTargetFromPrompt(prompt), '--offline', '--json'];
345
353
  if (route.command === '$Wiki')
346
354
  return ['wiki', 'refresh', '--json'];
347
355
  if (route.command === '$Fast-Mode')
@@ -354,6 +362,58 @@ function safeRouteExecutionArgs(route, prompt, { auto = false } = {}) {
354
362
  return ['commit-and-push', '--json'];
355
363
  return ['team', prompt, '--mock', '--json', ...(auto ? ['--no-open-zellij'] : [])];
356
364
  }
365
+ function ultraSearchExecutionArgs(prompt = '') {
366
+ const stripped = stripUltraSearchPrompt(prompt);
367
+ const lower = stripped.toLowerCase();
368
+ if (!stripped || /^(?:doctor|check|status)\b/.test(lower))
369
+ return ['ultra-search', 'doctor', '--json'];
370
+ if (/^(?:x|x-search|x_search)\b/.test(lower)) {
371
+ const query = stripped.replace(/^(?:x|x-search|x_search)\b[:\s-]*/i, '').trim() || 'source intelligence fixture';
372
+ return ['ultra-search', 'x', query, '--json'];
373
+ }
374
+ const url = stripped.match(/\bhttps?:\/\/\S+/)?.[0];
375
+ if (/^(?:fetch|url)\b/.test(lower) || url)
376
+ return ['ultra-search', 'fetch', url || stripped.replace(/^(?:fetch|url)\b[:\s-]*/i, '').trim() || 'https://example.com', '--json'];
377
+ const query = stripped.replace(/^run\b[:\s-]*/i, '').trim() || 'source intelligence fixture';
378
+ return ['ultra-search', 'run', query, '--mode', 'balanced', '--json'];
379
+ }
380
+ function stripUltraSearchPrompt(prompt = '') {
381
+ return String(prompt || '')
382
+ .trim()
383
+ .replace(/^\[\$Ultra-Search\]\([^)]+\)(?:\s|:)?\s*/i, '')
384
+ .replace(/^\[\$UltraSearch\]\([^)]+\)(?:\s|:)?\s*/i, '')
385
+ .replace(/^\$Ultra-Search(?:\s|:)?\s*/i, '')
386
+ .replace(/^\$UltraSearch(?:\s|:)?\s*/i, '')
387
+ .trim();
388
+ }
389
+ function searchVisibilityActionFromPrompt(prompt = '') {
390
+ const text = String(prompt || '').toLowerCase();
391
+ if (/\bdoctor\b|진단/.test(text))
392
+ return 'doctor';
393
+ if (/\bverify\b|검증/.test(text))
394
+ return 'fixture';
395
+ if (/\bplan\b|계획/.test(text))
396
+ return 'audit';
397
+ if (/\bapply\b|--apply\b|적용/.test(text))
398
+ return 'audit';
399
+ return 'audit';
400
+ }
401
+ function searchVisibilityTargetFromPrompt(prompt = '') {
402
+ const text = String(prompt || '').toLowerCase();
403
+ if (/\bpackage\b|npm|readme|github/.test(text))
404
+ return 'package';
405
+ if (/\bdocs?\b|documentation/.test(text))
406
+ return 'docs';
407
+ if (/\bwebsite\b|site\b|페이지|사이트/.test(text))
408
+ return 'website';
409
+ return 'auto';
410
+ }
411
+ function searchVisibilityModeFromPrompt(prompt = '') {
412
+ const text = String(prompt || '');
413
+ if (/generative\s+engine\s+optimization|AI\s+(?:answer|search)\s+(?:visibility|discoverability)|LLM\s+(?:citation|answer|visibility|discoverability)|answerability|entity\s+(?:facts?|clarity)|claim\s+evidence|crawler\s+policy|OAI-SearchBot|GPTBot|ChatGPT-User|Claude-SearchBot|ClaudeBot|Claude-User|llms\.txt|AI\s*검색\s*가시성|AI\s*답변\s*가시성|생성형\s*엔진\s*최적화/i.test(text))
414
+ return 'geo';
415
+ return 'seo';
416
+ }
357
417
  function fastModeActionFromPrompt(prompt = '') {
358
418
  const text = String(prompt || '');
359
419
  const lower = text.toLowerCase();
@@ -468,4 +528,34 @@ async function loadTrustReport(root, missionId) {
468
528
  return report;
469
529
  return { status: 'not_verified', ok: false, issues: ['trust_report_invalid'] };
470
530
  }
531
+ async function writeLightweightTrustReport(root, missionId, route, statusHint, proofOk) {
532
+ const status = normalizeTrustStatus(statusHint);
533
+ const issues = proofOk ? [] : ['completion_proof_not_ok'];
534
+ const report = {
535
+ schema: TRUST_REPORT_SCHEMA,
536
+ ...trustKernelMetadata(),
537
+ ok: proofOk && !['blocked', 'failed', 'not_verified'].includes(status),
538
+ mission_id: missionId,
539
+ route,
540
+ status,
541
+ proof_status: status,
542
+ evidence_status: 'verified_partial',
543
+ route_contract_status: 'verified_partial',
544
+ issues,
545
+ route_state_machine: {
546
+ state: 'trust_report',
547
+ lightweight: true,
548
+ reason: 'safe_deterministic_run_wrapper'
549
+ },
550
+ evidence: {
551
+ completion_proof: `.sneakoscope/missions/${missionId}/completion-proof.json`,
552
+ route_contract: null,
553
+ evidence_index: null,
554
+ evidence_records: 0,
555
+ lightweight: true
556
+ }
557
+ };
558
+ await writeJsonAtomic(path.join(missionDir(root, missionId), 'trust-report.json'), report);
559
+ return report;
560
+ }
471
561
  //# sourceMappingURL=run-command.js.map
@@ -0,0 +1,130 @@
1
+ import path from 'node:path';
2
+ import { printJson } from '../../cli/output.js';
3
+ import { projectRoot } from '../fsx.js';
4
+ import { flag, readOption } from './command-utils.js';
5
+ import { runSearchVisibilityApply, runSearchVisibilityAudit, runSearchVisibilityDoctor, runSearchVisibilityFixture, runSearchVisibilityPlan, runSearchVisibilityRollback, runSearchVisibilityStatus, runSearchVisibilityVerify, } from '../search-visibility/index.js';
6
+ export async function seoCommand(args = []) {
7
+ return runSearchVisibilityCommand('seo', args, 'seo');
8
+ }
9
+ export async function seoGeoOptimizerCommand(args = []) {
10
+ const normalized = normalizeOptimizerArgs(args);
11
+ return runSearchVisibilityCommand(normalized.mode, normalized.args, 'seo-geo-optimizer');
12
+ }
13
+ export async function runSearchVisibilityCommand(mode, args = [], displayCommand = mode) {
14
+ const action = args[0] || 'doctor';
15
+ const rest = args.slice(1);
16
+ const options = await parseOptions(rest);
17
+ let result;
18
+ if (action === 'doctor')
19
+ result = await runSearchVisibilityDoctor(mode, options);
20
+ else if (action === 'audit')
21
+ result = await runSearchVisibilityAudit(mode, options);
22
+ else if (action === 'plan')
23
+ result = await runSearchVisibilityPlan(mode, firstPositional(rest) || 'latest', options);
24
+ else if (action === 'apply')
25
+ result = await runSearchVisibilityApply(mode, firstPositional(rest) || 'latest', options);
26
+ else if (action === 'verify')
27
+ result = await runSearchVisibilityVerify(mode, firstPositional(rest) || 'latest', options);
28
+ else if (action === 'status')
29
+ result = await runSearchVisibilityStatus(mode, firstPositional(rest) || 'latest', options);
30
+ else if (action === 'rollback')
31
+ result = await runSearchVisibilityRollback(mode, firstPositional(rest) || 'latest', options);
32
+ else if (action === 'fixture')
33
+ result = await runSearchVisibilityFixture(mode, options);
34
+ else
35
+ return usage(mode, 2, displayCommand);
36
+ if (isBlocked(result))
37
+ process.exitCode = 1;
38
+ if (options.json) {
39
+ printJson(result);
40
+ return result;
41
+ }
42
+ printHuman(mode, action, result);
43
+ return result;
44
+ }
45
+ function normalizeOptimizerArgs(args) {
46
+ const out = [...args];
47
+ const first = String(out[0] || '').toLowerCase();
48
+ if (first === 'seo' || first === 'geo')
49
+ return { mode: first, args: out.slice(1) };
50
+ const modeIndex = out.findIndex((item) => item === '--mode');
51
+ if (modeIndex >= 0) {
52
+ const value = String(out[modeIndex + 1] || '').toLowerCase();
53
+ out.splice(modeIndex, value ? 2 : 1);
54
+ return { mode: value === 'geo' ? 'geo' : 'seo', args: out };
55
+ }
56
+ if (out.includes('--include-llms-txt') || out.includes('--observe-queries') || out.includes('--query-file'))
57
+ return { mode: 'geo', args: out };
58
+ return { mode: 'seo', args: out };
59
+ }
60
+ async function parseOptions(args) {
61
+ const root = path.resolve(readOption(args, '--root', await projectRoot()));
62
+ return {
63
+ root,
64
+ url: readOption(args, '--url', null),
65
+ target: targetOption(readOption(args, '--target', 'auto')),
66
+ framework: frameworkOption(readOption(args, '--framework', 'auto')),
67
+ offline: flag(args, '--offline'),
68
+ strict: flag(args, '--strict'),
69
+ json: flag(args, '--json'),
70
+ apply: flag(args, '--apply'),
71
+ yes: flag(args, '--yes'),
72
+ allowDirtyTouched: flag(args, '--allow-dirty-touched'),
73
+ browser: flag(args, '--browser'),
74
+ includeLlmsTxt: flag(args, '--include-llms-txt'),
75
+ observeQueries: flag(args, '--observe-queries'),
76
+ queryFile: readOption(args, '--query-file', null),
77
+ scope: String(readOption(args, '--scope', '') || '').split(',').map((item) => item.trim()).filter(Boolean),
78
+ };
79
+ }
80
+ function targetOption(value) {
81
+ return ['auto', 'website', 'docs', 'package'].includes(value) ? value : 'auto';
82
+ }
83
+ function frameworkOption(value) {
84
+ return ['auto', 'next-app', 'next-pages', 'static', 'package', 'unsupported'].includes(value) ? value : 'auto';
85
+ }
86
+ function firstPositional(args) {
87
+ const valueFlags = new Set(['--root', '--url', '--target', '--framework', '--scope', '--query-file']);
88
+ for (let i = 0; i < args.length; i += 1) {
89
+ const value = args[i] || '';
90
+ if (valueFlags.has(value)) {
91
+ i += 1;
92
+ continue;
93
+ }
94
+ if (!value.startsWith('--'))
95
+ return value;
96
+ }
97
+ return null;
98
+ }
99
+ function usage(mode, exitCode, displayCommand = mode) {
100
+ if (displayCommand === 'seo-geo-optimizer') {
101
+ console.error('Usage: sks seo-geo-optimizer [seo|geo] doctor|audit|plan|apply|verify|status|rollback|fixture [mission|latest] [--mode seo|geo] [--root <path>] [--url <origin>] [--target auto|website|docs|package] [--framework auto|next-app|next-pages|static] [--offline] [--strict] [--json]');
102
+ console.error(' sks seo-geo-optimizer apply <mission|latest> --mode seo|geo --apply [--include-llms-txt] [--scope <rule-or-path,...>] [--yes] [--json]');
103
+ console.error(' sks seo-geo-optimizer rollback <mission|latest> --mode seo|geo --apply [--yes] [--json]');
104
+ process.exitCode = exitCode;
105
+ return { schema: 'sks.search-visibility.usage.v1', ok: false, status: 'blocked', mode, command: displayCommand, reason: 'invalid_subcommand' };
106
+ }
107
+ const applyFlag = mode === 'geo' ? ' [--include-llms-txt]' : '';
108
+ console.error(`Usage: sks ${mode} doctor|audit|plan|apply|verify|status|rollback|fixture [mission|latest] [--root <path>] [--url <origin>] [--target auto|website|docs|package] [--framework auto|next-app|next-pages|static] [--offline] [--strict] [--json]`);
109
+ console.error(` sks ${mode} apply <mission|latest> --apply${applyFlag} [--scope <rule-or-path,...>] [--yes] [--json]`);
110
+ console.error(` sks ${mode} rollback <mission|latest> --apply [--yes] [--json]`);
111
+ process.exitCode = exitCode;
112
+ return { schema: 'sks.search-visibility.usage.v1', ok: false, status: 'blocked', mode, reason: 'invalid_subcommand' };
113
+ }
114
+ function isBlocked(value) {
115
+ if (!value || typeof value !== 'object')
116
+ return false;
117
+ const rec = value;
118
+ return rec.ok === false || rec.status === 'blocked';
119
+ }
120
+ function printHuman(mode, action, value) {
121
+ const rec = value && typeof value === 'object' ? value : {};
122
+ console.log(`SKS ${mode.toUpperCase()} ${action}: ${rec.status || (rec.ok === false ? 'blocked' : 'ok')}`);
123
+ if (rec.mission_id)
124
+ console.log(`Mission: ${rec.mission_id}`);
125
+ if (rec.artifacts_dir)
126
+ console.log(`Artifacts: ${rec.artifacts_dir}`);
127
+ if (Array.isArray(rec.blockers) && rec.blockers.length)
128
+ console.log(`Blockers: ${rec.blockers.join(', ')}`);
129
+ }
130
+ //# sourceMappingURL=seo-command.js.map
@@ -36,6 +36,7 @@ const FIXTURES = Object.freeze({
36
36
  'cli-selftest': fixture('execute', 'sks selftest --mock', [], 'pass'),
37
37
  'cli-git': fixture('execute', 'sks git policy --json', [], 'pass'),
38
38
  'cli-goal': fixture('mock', 'sks goal status latest --json', ['goal-workflow.json'], 'pass'),
39
+ 'cli-seo-geo-optimizer': fixture('execute_and_validate_artifacts', 'sks seo-geo-optimizer fixture --mode seo --json', ['search-visibility/site-inventory.json', 'search-visibility/seo-findings.json', 'search-visibility/verification-report.json', 'seo-gate.json', 'completion-proof.json'], 'pass'),
39
40
  'cli-research': fixture('mock', 'sks research status latest --json', ['research-gate.json', 'completion-proof.json'], 'pass'),
40
41
  'cli-qa-loop': fixture('mock', 'sks qa-loop status latest --json', ['qa-loop-proof.json', 'completion-proof.json'], 'pass'),
41
42
  'cli-ppt': fixture('mock', 'sks ppt fixture --mock --json', ['ppt-imagegen-review-gate.json', 'completion-proof.json'], 'pass'),
@@ -75,6 +76,7 @@ const FIXTURES = Object.freeze({
75
76
  'cli-commit': fixture('mock', 'sks commit --dry-run', [], 'pass'),
76
77
  'cli-commit-and-push': fixture('mock', 'sks commit-and-push --dry-run', [], 'pass'),
77
78
  'cli-context7': fixture('real_optional', 'sks context7 check --json', [], 'pass'),
79
+ 'cli-ultra-search': fixture('execute', 'sks ultra-search doctor --json', [], 'pass'),
78
80
  'cli-xai': fixture('real_optional', 'sks xai check --json', [], 'pass'),
79
81
  'cli-all-features': fixture('mock', 'sks all-features complete --json', [`.sneakoscope/reports/all-feature-completion-${PACKAGE_VERSION}.json`], 'pass'),
80
82
  'cli-init': fixture('mock', 'sks init --local-only --dry-run', [], 'pass'),
@@ -88,6 +90,7 @@ const FIXTURES = Object.freeze({
88
90
  'skill-imagegen': fixture('mock', 'sks image-ux-review fixture --mock --json', ['image-ux-generated-review-ledger.json', 'image-voxel-ledger.json'], 'pass'),
89
91
  'skill-gx-visual-validate': fixture('mock', 'sks gx validate fixture --mock --json', ['gx-validation.json'], 'pass'),
90
92
  'skill-context7-docs': fixture('real_optional', 'sks context7 check --json', [], 'pass'),
93
+ 'skill-seo-geo-optimizer': fixture('mock', 'sks seo-geo-optimizer fixture --mode geo --json', ['search-visibility/site-inventory.json', 'search-visibility/geo-findings.json', 'geo-gate.json', 'completion-proof.json'], 'pass'),
91
94
  'cli-proof': fixture('execute_and_validate_artifacts', 'sks proof smoke --json', ['.sneakoscope/proof/latest.json'], 'pass'),
92
95
  'cli-trust': fixture('execute_and_validate_artifacts', 'sks trust report latest --json', ['trust-report.json'], 'pass'),
93
96
  'cli-wrongness': fixture('execute_and_validate_artifacts', 'sks wrongness add --kind missing_evidence --claim "fixture wrongness" --json', ['.sneakoscope/wiki/wrongness-ledger.json'], 'pass'),
@@ -104,6 +107,9 @@ const FIXTURES = Object.freeze({
104
107
  'route-dfix': fixture('execute_and_validate_artifacts', 'sks dfix fixture --json', ['completion-proof.json', 'dfix-gate.json', 'dfix-verification.json'], 'pass'),
105
108
  'route-answer': fixture('mock', '$Answer answer-only route policy', [], 'pass'),
106
109
  'route-goal': fixture('mock', '$Goal bridge route', ['goal-workflow.json', 'completion-proof.json'], 'pass'),
110
+ 'route-ultra-search': fixture('execute', 'sks run "$Ultra-Search source intelligence fixture" --execute --json', [], 'pass'),
111
+ 'route-ultrasearch': fixture('execute', 'sks run "$UltraSearch source intelligence fixture" --execute --json', [], 'pass'),
112
+ 'route-seo-geo-optimizer': fixture('execute_and_validate_artifacts', 'sks seo-geo-optimizer fixture --mode geo --json', ['search-visibility/site-inventory.json', 'search-visibility/geo-findings.json', 'search-visibility/verification-report.json', 'geo-gate.json', 'completion-proof.json'], 'pass'),
107
113
  'route-autoresearch': fixture('mock', '$AutoResearch fixture route', ['research-gate.json', 'completion-proof.json'], 'pass'),
108
114
  'route-mad-sks': fixture('mock', '$MAD-SKS permission gate route', ['mad-sks-gate.json', 'completion-proof.json'], 'pass'),
109
115
  'route-from-chat-img': fixture('mock', '$From-Chat-IMG visual work order route', ['from-chat-img-work-order.md', 'image-voxel-ledger.json', 'completion-proof.json'], 'pass'),