sneakoscope 4.2.0 → 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 (126) hide show
  1. package/README.md +35 -8
  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-app-server-v2-client.js +86 -2
  16. package/dist/core/codex-control/codex-fake-sdk-adapter.js +67 -9
  17. package/dist/core/codex-control/codex-reliability-shield.js +26 -5
  18. package/dist/core/codex-control/codex-task-runner.js +7 -1
  19. package/dist/core/codex-control/gpt-final-arbiter.js +4 -1
  20. package/dist/core/codex-control/gpt-final-review-schema.js +58 -0
  21. package/dist/core/codex-control/model-call-concurrency.js +1 -1
  22. package/dist/core/codex-native/core-skill-manifest.js +23 -0
  23. package/dist/core/commands/bench-command.js +11 -2
  24. package/dist/core/commands/code-structure-command.js +34 -2
  25. package/dist/core/commands/qa-loop-command.js +23 -7
  26. package/dist/core/commands/run-command.js +92 -2
  27. package/dist/core/commands/seo-command.js +130 -0
  28. package/dist/core/feature-fixtures.js +6 -0
  29. package/dist/core/feature-registry.js +3 -1
  30. package/dist/core/fsx.js +1 -1
  31. package/dist/core/hooks-runtime.js +9 -1
  32. package/dist/core/init.js +8 -6
  33. package/dist/core/lean-engineering-policy.js +159 -0
  34. package/dist/core/pipeline-internals/runtime-core.js +15 -5
  35. package/dist/core/proof/auto-finalize.js +3 -2
  36. package/dist/core/proof/proof-schema.js +2 -1
  37. package/dist/core/proof/proof-writer.js +1 -0
  38. package/dist/core/proof/route-adapter.js +4 -2
  39. package/dist/core/proof/route-finalizer.js +35 -3
  40. package/dist/core/qa-loop/qa-app-server-driver.js +134 -0
  41. package/dist/core/qa-loop/qa-contract-v2.js +231 -0
  42. package/dist/core/qa-loop/qa-gate-v2.js +132 -0
  43. package/dist/core/qa-loop/qa-runtime-artifacts.js +53 -0
  44. package/dist/core/qa-loop/qa-surface-router.js +114 -0
  45. package/dist/core/qa-loop/qa-types.js +18 -0
  46. package/dist/core/qa-loop.js +83 -26
  47. package/dist/core/release/gate-manifest.js +1 -0
  48. package/dist/core/release/sla-scheduler.js +1 -1
  49. package/dist/core/release-parallel-full-coverage.js +1 -1
  50. package/dist/core/routes.js +96 -14
  51. package/dist/core/search-visibility/adapter-registry.js +26 -0
  52. package/dist/core/search-visibility/adapters/next-app.js +6 -0
  53. package/dist/core/search-visibility/adapters/next-pages.js +6 -0
  54. package/dist/core/search-visibility/adapters/static-site.js +6 -0
  55. package/dist/core/search-visibility/analyzers.js +377 -0
  56. package/dist/core/search-visibility/artifacts.js +183 -0
  57. package/dist/core/search-visibility/discovery.js +347 -0
  58. package/dist/core/search-visibility/index.js +199 -0
  59. package/dist/core/search-visibility/mission.js +67 -0
  60. package/dist/core/search-visibility/mutation.js +314 -0
  61. package/dist/core/search-visibility/types.js +2 -0
  62. package/dist/core/search-visibility/verifier.js +60 -0
  63. package/dist/core/source-intelligence/source-intelligence-policy.js +45 -26
  64. package/dist/core/source-intelligence/source-intelligence-proof.js +10 -16
  65. package/dist/core/source-intelligence/source-intelligence-runner.js +56 -42
  66. package/dist/core/triwiki/triwiki-affected-graph.js +3 -2
  67. package/dist/core/trust-kernel/trust-report.js +3 -5
  68. package/dist/core/ultra-search/index.js +3 -0
  69. package/dist/core/ultra-search/runtime.js +502 -0
  70. package/dist/core/ultra-search/types.js +3 -0
  71. package/dist/core/version.js +1 -1
  72. package/dist/scripts/agent-visual-consistency-check.js +1 -1
  73. package/dist/scripts/check-architecture.js +40 -7
  74. package/dist/scripts/check-command-module-budget.js +43 -5
  75. package/dist/scripts/check-pipeline-budget.js +17 -30
  76. package/dist/scripts/check-publish-tag.js +33 -6
  77. package/dist/scripts/check-route-modularity.js +25 -33
  78. package/dist/scripts/check-runtime-schemas.js +22 -0
  79. package/dist/scripts/codex-control-all-pipelines-check.js +1 -0
  80. package/dist/scripts/codex-control-model-capacity-fallback-check.js +53 -0
  81. package/dist/scripts/config-managed-merge-callsite-coverage-check.js +7 -1
  82. package/dist/scripts/core-skill-immutable-sync-check.js +3 -2
  83. package/dist/scripts/core-skill-integrity-blackbox.js +3 -2
  84. package/dist/scripts/core-skill-manifest-check.js +7 -2
  85. package/dist/scripts/geo-claim-evidence-check.js +18 -0
  86. package/dist/scripts/geo-cli-blackbox-check.js +18 -0
  87. package/dist/scripts/geo-crawler-policy-check.js +16 -0
  88. package/dist/scripts/geo-llms-txt-optional-check.js +19 -0
  89. package/dist/scripts/gpt-final-arbiter-check.js +4 -1
  90. package/dist/scripts/loop-directive-check-lib.js +78 -1
  91. package/dist/scripts/qa-loop-app-server-driver-check.js +74 -0
  92. package/dist/scripts/qa-loop-surface-router-check.js +49 -0
  93. package/dist/scripts/release-check-dynamic-execute.js +1 -1
  94. package/dist/scripts/release-metadata-1-19-check.js +2 -2
  95. package/dist/scripts/release-parallel-check.js +17 -2
  96. package/dist/scripts/release-parallel-full-coverage-check.js +1 -1
  97. package/dist/scripts/release-readiness-report.js +6 -6
  98. package/dist/scripts/release-registry-check.js +33 -14
  99. package/dist/scripts/runtime-ts-rust-boundary-check.js +1 -1
  100. package/dist/scripts/search-visibility-gate-lib.js +124 -0
  101. package/dist/scripts/seo-audit-fixture-check.js +16 -0
  102. package/dist/scripts/seo-canonical-locale-check.js +19 -0
  103. package/dist/scripts/seo-cli-blackbox-check.js +18 -0
  104. package/dist/scripts/seo-geo-feature-fixture-quality-check.js +18 -0
  105. package/dist/scripts/seo-geo-geo-disambiguation-check.js +12 -0
  106. package/dist/scripts/seo-geo-no-unsupported-ranking-claims-check.js +18 -0
  107. package/dist/scripts/seo-geo-route-identity-check.js +12 -0
  108. package/dist/scripts/seo-geo-skill-rich-content-check.js +22 -0
  109. package/dist/scripts/seo-mutation-rollback-check.js +23 -0
  110. package/dist/scripts/seo-no-mutation-by-default-check.js +17 -0
  111. package/dist/scripts/seo-structured-data-visible-content-check.js +19 -0
  112. package/dist/scripts/sks-1-18-gate-lib.js +2 -2
  113. package/dist/scripts/sks-3-1-5-directive-check-lib.js +10 -1
  114. package/dist/scripts/source-intelligence-all-modes-check.js +9 -19
  115. package/dist/scripts/source-intelligence-policy-check.js +6 -6
  116. package/dist/scripts/triwiki-affected-graph-check.js +2 -2
  117. package/dist/scripts/ultra-search-provider-interface-check.js +27 -0
  118. package/package.json +26 -5
  119. package/schemas/search-visibility/finding-ledger.schema.json +36 -0
  120. package/schemas/search-visibility/gate.schema.json +22 -0
  121. package/schemas/search-visibility/mutation-plan.schema.json +27 -0
  122. package/schemas/search-visibility/site-inventory.schema.json +21 -0
  123. package/schemas/search-visibility/verification-report.schema.json +23 -0
  124. package/dist/core/mcp/xai-mcp-detector.js +0 -157
  125. package/dist/core/mcp/xai-search-adapter.js +0 -100
  126. package/dist/scripts/xai-mcp-capability-check.js +0 -14
@@ -0,0 +1,159 @@
1
+ import { createHash } from 'node:crypto';
2
+ export const LEAN_ENGINEERING_POLICY_ID = 'sks.lean-engineering-policy.v1';
3
+ export const LEAN_DECISION_SCHEMA = 'sks.lean-decision.v1';
4
+ export const LEAN_CHANGE_EVIDENCE_SCHEMA = 'sks.lean-change-evidence.v1';
5
+ export const LEAN_SOLUTION_RUNGS = Object.freeze([
6
+ 'skip',
7
+ 'reuse-existing',
8
+ 'stdlib',
9
+ 'native-platform',
10
+ 'installed-dependency',
11
+ 'single-expression',
12
+ 'minimal-custom'
13
+ ]);
14
+ const LEAN_ENGINEERING_POLICY_CANONICAL = [
15
+ 'Understand the real flow before changing code.',
16
+ 'Stop at the highest sufficient rung: skip, reuse existing code, stdlib, native platform, installed dependency, safe single expression, minimal custom code.',
17
+ 'Do not add unrequested routes, commands, daemons, dependencies, abstractions, config flags, shims, or hidden fallbacks.',
18
+ 'Fix shared root causes instead of duplicating caller-specific symptom guards.',
19
+ 'Capability and compatibility fallbacks require one authority, proof, bounded scope, and honest verification level.',
20
+ 'Never remove trust-boundary validation, data-loss protection, security, permissions, rollback, accessibility, or explicit user requirements to shrink a diff.',
21
+ 'Non-trivial logic needs one smallest runnable check.'
22
+ ].join('\n');
23
+ export const LEAN_ENGINEERING_POLICY_HASH = createHash('sha256')
24
+ .update(LEAN_ENGINEERING_POLICY_CANONICAL)
25
+ .digest('hex')
26
+ .slice(0, 16);
27
+ export function leanPolicyReference() {
28
+ return {
29
+ policy_id: LEAN_ENGINEERING_POLICY_ID,
30
+ policy_hash: LEAN_ENGINEERING_POLICY_HASH
31
+ };
32
+ }
33
+ export function leanEngineeringCompactText() {
34
+ return [
35
+ `Lean Engineering Policy (${LEAN_ENGINEERING_POLICY_ID}/${LEAN_ENGINEERING_POLICY_HASH}):`,
36
+ 'Read the touched flow first, then stop at the highest sufficient rung: skip, reuse existing, stdlib, native platform, installed dependency, safe single expression, minimal custom.',
37
+ 'No unrequested route/command/daemon/dependency/abstraction/config flag/shim/hidden fallback; required capability/compatibility fallback needs one authority, proof, and bounded scope.',
38
+ 'Fix root cause once, preserve trust-boundary validation/security/rollback/accessibility/user requirements, and leave one runnable check for non-trivial logic.'
39
+ ].join('\n');
40
+ }
41
+ export function leanEngineeringLongText() {
42
+ return [
43
+ leanEngineeringCompactText(),
44
+ 'Forbidden fallback: silent mock/fixture success, provider contract switching without authority, catch-all empty success, unused future shims, duplicate legacy/new SSOTs, or production proof from test fakes.',
45
+ 'Allowed fallback: same contract or explicit narrower contract, capability detection, one selection authority, recorded provider/proof level, honest downgrade when used, and a bounded chain.',
46
+ 'Compatibility bridge: one canonical implementation; legacy entry only converts arguments, emits deprecation context, and has a sunset trigger.',
47
+ 'Intentional simplification marker: `sks-lean: ceiling=<known limit>; revisit_when=<measurable trigger>; upgrade=<specific path>`.'
48
+ ].join('\n');
49
+ }
50
+ export function normalizeLeanDecision(input = {}, defaults = {}) {
51
+ const value = record(input);
52
+ const defaultFallback = defaults.fallback_plan || { kind: 'none', authority: null, justification: null };
53
+ return {
54
+ schema: LEAN_DECISION_SCHEMA,
55
+ policy_id: LEAN_ENGINEERING_POLICY_ID,
56
+ policy_hash: LEAN_ENGINEERING_POLICY_HASH,
57
+ selected_rung: normalizeRung(value.selected_rung, defaults.selected_rung || 'minimal-custom'),
58
+ task_requires_change: booleanValue(value.task_requires_change, defaults.task_requires_change ?? true),
59
+ root_cause_target: nullableString(value.root_cause_target, defaults.root_cause_target ?? null),
60
+ reused_paths: stringArray(value.reused_paths, defaults.reused_paths),
61
+ stdlib_or_native_choice: nullableString(value.stdlib_or_native_choice, defaults.stdlib_or_native_choice ?? null),
62
+ new_dependency_requested: booleanValue(value.new_dependency_requested, defaults.new_dependency_requested ?? false),
63
+ new_dependency_justification: nullableString(value.new_dependency_justification, defaults.new_dependency_justification ?? null),
64
+ new_abstraction_requested: booleanValue(value.new_abstraction_requested, defaults.new_abstraction_requested ?? false),
65
+ new_abstraction_justification: nullableString(value.new_abstraction_justification, defaults.new_abstraction_justification ?? null),
66
+ fallback_plan: normalizeFallbackPlan(value.fallback_plan, defaultFallback),
67
+ expected_changed_paths: stringArray(value.expected_changed_paths, defaults.expected_changed_paths),
68
+ verification_minimum: stringArray(value.verification_minimum, defaults.verification_minimum)
69
+ };
70
+ }
71
+ export function validateLeanDecision(input) {
72
+ const value = record(input);
73
+ const issues = [];
74
+ if (value.schema !== LEAN_DECISION_SCHEMA)
75
+ issues.push('schema');
76
+ if (value.policy_id !== LEAN_ENGINEERING_POLICY_ID)
77
+ issues.push('policy_id');
78
+ if (value.policy_hash !== LEAN_ENGINEERING_POLICY_HASH)
79
+ issues.push('policy_hash');
80
+ if (!isLeanSolutionRung(value.selected_rung))
81
+ issues.push('selected_rung');
82
+ if (typeof value.task_requires_change !== 'boolean')
83
+ issues.push('task_requires_change');
84
+ if (!Array.isArray(value.reused_paths))
85
+ issues.push('reused_paths');
86
+ if (!Array.isArray(value.expected_changed_paths))
87
+ issues.push('expected_changed_paths');
88
+ if (!Array.isArray(value.verification_minimum))
89
+ issues.push('verification_minimum');
90
+ const fallback = record(value.fallback_plan);
91
+ if (!isFallbackKind(fallback.kind))
92
+ issues.push('fallback_plan.kind');
93
+ if (fallback.kind !== 'none' && (!fallback.authority || !fallback.justification))
94
+ issues.push('fallback_plan.evidence');
95
+ if (value.new_dependency_requested === true && !value.new_dependency_justification)
96
+ issues.push('new_dependency_justification');
97
+ if (value.new_abstraction_requested === true && !value.new_abstraction_justification)
98
+ issues.push('new_abstraction_justification');
99
+ if (value.selected_rung === 'skip' && value.task_requires_change === true)
100
+ issues.push('skip_requires_no_change');
101
+ if (value.task_requires_change === true && !value.verification_minimum?.length)
102
+ issues.push('verification_minimum_required');
103
+ return { ok: issues.length === 0, issues };
104
+ }
105
+ export function parseLeanSimplificationMarkerLine(text, file = '', line = 0) {
106
+ const match = /^\s*(?:(?:\/\/|#)\s*)sks-lean:\s*(.+)$/i.exec(text);
107
+ if (!match)
108
+ return null;
109
+ const fields = Object.fromEntries((match[1] || '').split(';').map((part) => {
110
+ const [key, ...rest] = part.split('=');
111
+ return [String(key || '').trim(), rest.join('=').trim()];
112
+ }));
113
+ const ceiling = fields.ceiling || null;
114
+ const revisit = fields.revisit_when || null;
115
+ const upgrade = fields.upgrade || null;
116
+ return {
117
+ file,
118
+ line,
119
+ ceiling,
120
+ revisit_when: revisit,
121
+ upgrade,
122
+ status: !revisit ? 'missing-trigger' : !upgrade ? 'missing-upgrade' : 'complete'
123
+ };
124
+ }
125
+ function normalizeFallbackPlan(input, defaults) {
126
+ const value = record(input);
127
+ const kind = isFallbackKind(value.kind) ? value.kind : defaults.kind;
128
+ return {
129
+ kind,
130
+ authority: nullableString(value.authority, defaults.authority),
131
+ justification: nullableString(value.justification, defaults.justification)
132
+ };
133
+ }
134
+ function normalizeRung(value, fallback) {
135
+ return isLeanSolutionRung(value) ? value : fallback;
136
+ }
137
+ function isLeanSolutionRung(value) {
138
+ return typeof value === 'string' && LEAN_SOLUTION_RUNGS.includes(value);
139
+ }
140
+ function isFallbackKind(value) {
141
+ return value === 'none' || value === 'capability' || value === 'compatibility' || value === 'fail-closed';
142
+ }
143
+ function stringArray(value, fallback = []) {
144
+ const source = Array.isArray(value) ? value : Array.isArray(fallback) ? fallback : [];
145
+ return source.map((item) => String(item || '').trim()).filter(Boolean);
146
+ }
147
+ function nullableString(value, fallback = null) {
148
+ const text = String(value ?? '').trim();
149
+ if (text)
150
+ return text;
151
+ return fallback;
152
+ }
153
+ function booleanValue(value, fallback) {
154
+ return typeof value === 'boolean' ? value : fallback;
155
+ }
156
+ function record(value) {
157
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
158
+ }
159
+ //# sourceMappingURL=lean-engineering-policy.js.map
@@ -26,7 +26,8 @@ import { prepareMadDbMission } from '../mad-db/mad-db-coordinator.js';
26
26
  import { AGENT_INTAKE_STAGE_ID, AGENT_COUNT } from '../agents/agent-schema.js';
27
27
  import { normalizeAgentPolicy, routeRequiresAgentIntake, agentPipelineStage } from '../agents/agent-plan.js';
28
28
  import { readAgentGateStatus } from '../agents/agent-gate.js';
29
- import { CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_EVIDENCE_SOURCE, CODEX_COMPUTER_USE_ONLY_POLICY, CODEX_IMAGEGEN_REQUIRED_POLICY, CODEX_WEB_VERIFICATION_POLICY, 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, SOLUTION_SCOUT_STAGE_ID, chatCaptureIntakeText, context7RequirementText, dollarCommand, evidenceMentionsForbiddenBrowserAutomation, getdesignReferencePolicyText, hasFromChatImgSignal, hasMadSksSignal, imageUxReviewPipelinePolicyText, looksLikeProblemSolvingRequest, noUnrequestedFallbackCodePolicyText, outcomeRubricPolicyText, pptPipelineAllowlistPolicyText, reflectionRequiredForRoute, reasoningInstruction, routeNeedsContext7, routePrompt, routeReasoning, routeRequiresSubagents, solutionScoutPolicyText, speedLanePolicyText, stripDollarCommand, stripMadSksSignal, stripVisibleDecisionAnswerBlocks, subagentExecutionPolicyText, stackCurrentDocsPolicyText, triwikiContextTracking, triwikiContextTrackingText, triwikiStagePolicyText } from '../routes.js';
29
+ import { CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_EVIDENCE_SOURCE, CODEX_COMPUTER_USE_ONLY_POLICY, CODEX_IMAGEGEN_REQUIRED_POLICY, CODEX_WEB_VERIFICATION_POLICY, 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, SOLUTION_SCOUT_STAGE_ID, chatCaptureIntakeText, context7RequirementText, dollarCommand, evidenceMentionsForbiddenBrowserAutomation, getdesignReferencePolicyText, hasFromChatImgSignal, hasMadSksSignal, imageUxReviewPipelinePolicyText, leanEngineeringCompactText, looksLikeProblemSolvingRequest, pptPipelineAllowlistPolicyText, reflectionRequiredForRoute, reasoningInstruction, routeNeedsContext7, routePrompt, routeReasoning, routeRequiresSubagents, solutionScoutPolicyText, stripDollarCommand, stripMadSksSignal, stripVisibleDecisionAnswerBlocks, subagentExecutionPolicyText, stackCurrentDocsPolicyText, triwikiContextTracking, triwikiContextTrackingText, triwikiStagePolicyText } from '../routes.js';
30
+ import { normalizeLeanDecision, validateLeanDecision } from '../lean-engineering-policy.js';
30
31
  import { TEAM_DECOMPOSITION_ARTIFACT, TEAM_GRAPH_ARTIFACT, TEAM_INBOX_DIR, TEAM_RUNTIME_TASKS_ARTIFACT, teamRuntimePlanMetadata, teamRuntimeRequiredArtifacts, validateTeamRuntimeArtifacts, writeTeamRuntimeArtifacts } from '../team-dag.js';
31
32
  import { formatAgentReasoning, formatRoleCounts, initTeamLive, parseTeamSpecText, teamReasoningPolicy } from '../team-live.js';
32
33
  import { evaluateTeamReviewPolicyGate, MIN_TEAM_REVIEWER_LANES, MIN_TEAM_REVIEW_POLICY_TEXT, teamReviewPolicy } from '../team-review-policy.js';
@@ -93,6 +94,13 @@ export function buildPipelinePlan(input = {}) {
93
94
  const skipped = stages.filter((stage) => stage.status === 'skipped').map((stage) => stage.id);
94
95
  const kept = stages.filter((stage) => stage.status !== 'skipped' && stage.status !== 'not_applicable').map((stage) => stage.id);
95
96
  const routeEconomy = routeEconomyPlan(proof);
97
+ const leanDecision = normalizeLeanDecision(input.leanDecision, {
98
+ selected_rung: ['Answer', 'Help', 'Wiki'].includes(route?.id) ? 'skip' : 'minimal-custom',
99
+ task_requires_change: !['Answer', 'Help', 'Wiki'].includes(route?.id),
100
+ root_cause_target: route?.id ? `${route.id} route selected implementation surface` : null,
101
+ expected_changed_paths: input.expectedChangedPaths || input.touchedFiles || [],
102
+ verification_minimum: verification.slice(0, 3).map((item) => String(item || '').trim()).filter(Boolean)
103
+ });
96
104
  return {
97
105
  schema_version: PIPELINE_PLAN_SCHEMA_VERSION,
98
106
  generated_at: nowIso(),
@@ -135,6 +143,7 @@ export function buildPipelinePlan(input = {}) {
135
143
  verification,
136
144
  invariants: ['no_unrequested_fallback_code', 'ssot_guard', 'listed_verification', 'triwiki_validate_before_final', 'honest_mode'],
137
145
  proof_field: proof,
146
+ lean_decision: leanDecision,
138
147
  ssot_guard: buildSsotGuard({ route: route?.id || 'SKS', mode: route?.mode || 'SKS', task }),
139
148
  route_economy: routeEconomy,
140
149
  agent_intake: agentPolicy,
@@ -193,6 +202,9 @@ export function validatePipelinePlan(plan = {}) {
193
202
  const routeEconomyLatticeIssues = validateRouteEconomyDecisionLattice(plan.route_economy, plan.proof_field);
194
203
  if (routeEconomyLatticeIssues.length)
195
204
  issues.push(...routeEconomyLatticeIssues.map((issue) => `route_economy.decision_lattice:${issue}`));
205
+ const leanDecision = validateLeanDecision(plan.lean_decision);
206
+ if (!leanDecision.ok)
207
+ issues.push(...leanDecision.issues.map((issue) => `lean_decision:${issue}`));
196
208
  if (plan.no_unrequested_fallback_code !== true || !plan.invariants?.includes('no_unrequested_fallback_code'))
197
209
  issues.push('fallback_guard');
198
210
  if (!plan.ssot_guard?.required || !plan.invariants?.includes('ssot_guard'))
@@ -427,10 +439,8 @@ export function promptPipelineContext(prompt, route = null) {
427
439
  'Stance: infer the user intent aggressively from rough wording, local context, TriWiki, and conservative defaults; do not surface prequestion sheets before work.',
428
440
  subagentExecutionPolicyText(route, cleanPrompt),
429
441
  solutionScoutPolicyText(cleanPrompt),
430
- noUnrequestedFallbackCodePolicyText(),
442
+ leanEngineeringCompactText(),
431
443
  ssotGuardPolicyText(),
432
- outcomeRubricPolicyText(),
433
- speedLanePolicyText(),
434
444
  skillDreamPolicyText(),
435
445
  route?.id === 'PPT'
436
446
  ? `${pptPipelineAllowlistPolicyText()} ${getdesignReferencePolicyText()}`
@@ -456,7 +466,7 @@ export function promptPipelineContext(prompt, route = null) {
456
466
  if (route?.id === 'ImageUXReview')
457
467
  lines.push(`Image UX Review route: ${imageUxReviewPipelinePolicyText()} Use ${IMAGE_UX_REVIEW_POLICY_ARTIFACT}, ${IMAGE_UX_REVIEW_SCREEN_INVENTORY_ARTIFACT}, ${IMAGE_UX_REVIEW_GENERATED_REVIEW_LEDGER_ARTIFACT}, ${IMAGE_UX_REVIEW_ISSUE_LEDGER_ARTIFACT}, ${IMAGE_UX_REVIEW_ITERATION_REPORT_ARTIFACT}, and ${IMAGE_UX_REVIEW_GATE_ARTIFACT} as the route evidence set. The route may suggest safe fixes only when the user requested fixing; otherwise report findings and blockers.`);
458
468
  if (route?.id === 'AutoResearch')
459
- lines.push('AutoResearch route: load autoresearch-loop plus seo-geo-optimizer when SEO/GEO, discoverability, README, npm, GitHub stars, ranking, or AI-search visibility is relevant.');
469
+ lines.push('AutoResearch route: load autoresearch-loop for experiments and benchmarking. SEO/GEO, discoverability, README, npm, GitHub search visibility, and AI-search visibility should use the first-class $SEO-GEO-OPTIMIZER parent route unless the selected route explicitly needs a child experiment.');
460
470
  if (route?.id === 'DB')
461
471
  lines.push('DB route: scan/check database risk first; destructive DB operations remain forbidden.');
462
472
  if (route?.id === 'MadDB')
@@ -13,7 +13,7 @@ const AGENT_ARTIFACTS = [
13
13
  'agents/agent-task-board.json',
14
14
  'agents/agent-concurrency-policy.json'
15
15
  ];
16
- export async function maybeFinalizeRoute(root, { missionId, route, gateFile = null, gate = null, artifacts = [], claims = [], visualEvidence = null, visual = false, fixClaim = false, requireRelation = false, mock = false, statusHint = null, reason = null, command = null, dbEvidence = null, testEvidence = null, blockers = [], unverified = [], agents = undefined, allowActiveWrongnessPartial = false, failureAnalysis = null } = {}) {
16
+ export async function maybeFinalizeRoute(root, { missionId, route, gateFile = null, gate = null, artifacts = [], claims = [], visualEvidence = null, visual = false, fixClaim = false, requireRelation = false, mock = false, statusHint = null, reason = null, command = null, dbEvidence = null, testEvidence = null, blockers = [], unverified = [], agents = undefined, allowActiveWrongnessPartial = false, failureAnalysis = null, lightweightEvidence = false } = {}) {
17
17
  if (!missionId || !route) {
18
18
  return { ok: false, skipped: true, reason: 'mission_id_or_route_missing' };
19
19
  }
@@ -62,7 +62,8 @@ export async function maybeFinalizeRoute(root, { missionId, route, gateFile = nu
62
62
  visualClaim: visual,
63
63
  agents,
64
64
  allowActiveWrongnessPartial,
65
- failureAnalysis
65
+ failureAnalysis,
66
+ lightweightEvidence
66
67
  });
67
68
  return { ...proof, auto_finalized: true, gate_passed: passed, status_hint: finalStatus };
68
69
  }
@@ -33,7 +33,8 @@ export function emptyCompletionProof(overrides = {}) {
33
33
  triwiki: null,
34
34
  wrongness: null,
35
35
  source_intelligence: null,
36
- goal_mode: null
36
+ goal_mode: null,
37
+ lean_engineering: null
37
38
  },
38
39
  claims: [],
39
40
  unverified: [],
@@ -74,6 +74,7 @@ export function renderProofMarkdown(proof = {}, validation = validateCompletionP
74
74
  `- Agents: ${proof.evidence?.agents?.agent_count ?? 0} (${proof.evidence?.agents?.status || 'not_recorded'})`,
75
75
  `- TriWiki: ${proof.evidence?.triwiki?.status || 'not_recorded'}`,
76
76
  `- Wrongness: ${proof.evidence?.wrongness?.active_count ?? 0} active (${proof.evidence?.wrongness?.high_severity_active ?? 0} high)`,
77
+ `- Lean engineering: ${proof.evidence?.lean_engineering?.semantic_review?.status || proof.evidence?.lean_engineering?.status || 'not_recorded'}`,
77
78
  `- Evidence router: ${proof.evidence?.evidence_router?.records ?? 0} record(s)`,
78
79
  `- Trust report: ${proof.evidence?.trust_report || 'not_recorded'}`,
79
80
  ''
@@ -5,8 +5,8 @@ import { normalizeProofRoute, routeRequiresImageVoxelAnchors } from './route-pro
5
5
  import { linkProofClaimsToEvidence, proofEvidenceSummary } from '../evidence/evidence-proof-linker.js';
6
6
  import { writeTrustArtifactsForProof } from '../trust-kernel/trust-report.js';
7
7
  import { enforceRetention } from '../retention.js';
8
- export async function writeRouteCompletionProof(root, { missionId = null, route = null, status = 'verified_partial', gate = null, summary = {}, artifacts = [], evidence = {}, claims = [], unverified = [], blockers = [], failureAnalysis = null, nextHumanActions = [] } = {}) {
9
- const collected = await collectProofEvidence(root);
8
+ export async function writeRouteCompletionProof(root, { missionId = null, route = null, status = 'verified_partial', gate = null, summary = {}, artifacts = [], evidence = {}, claims = [], unverified = [], blockers = [], failureAnalysis = null, nextHumanActions = [], lightweightEvidence = false } = {}) {
9
+ const collected = lightweightEvidence ? { files: [] } : await collectProofEvidence(root);
10
10
  const normalizedRoute = normalizeProofRoute(route);
11
11
  const mergedEvidence = {
12
12
  ...collected,
@@ -45,6 +45,8 @@ export async function writeRouteCompletionProof(root, { missionId = null, route
45
45
  status: normalizedStatus
46
46
  }
47
47
  });
48
+ if (lightweightEvidence)
49
+ return { ...written, trust: null, retention: null };
48
50
  if (!missionId)
49
51
  return written;
50
52
  const firstTrust = await writeTrustArtifactsForProof(root, written.proof);
@@ -6,7 +6,8 @@ import { readAgentProofEvidence } from '../agents/agent-proof-evidence.js';
6
6
  import { wrongnessProofEvidence } from '../triwiki-wrongness/wrongness-proof-linker.js';
7
7
  import { computerUseStatusReport } from '../computer-use-status.js';
8
8
  import { readComputerUseLiveEvidence } from '../computer-use-live-evidence.js';
9
- export async function finalizeRouteWithProof(root, { missionId, route, gateFile = null, gate = null, artifacts = [], visualEvidence = null, dbEvidence = null, madSksEvidence = null, testEvidence = null, commandEvidence = null, claims = [], unverified = [], blockers = [], statusHint = 'verified_partial', strict = false, mock = false, fixClaim = false, requireRelation = false, visualClaim = undefined, agents = undefined, allowActiveWrongnessPartial = false, failureAnalysis = null } = {}) {
9
+ import { leanChangeEvidenceFromReport, scanCodeStructure } from '../code-structure.js';
10
+ export async function finalizeRouteWithProof(root, { missionId, route, gateFile = null, gate = null, artifacts = [], visualEvidence = null, dbEvidence = null, madSksEvidence = null, testEvidence = null, commandEvidence = null, claims = [], unverified = [], blockers = [], statusHint = 'verified_partial', strict = false, mock = false, fixClaim = false, requireRelation = false, visualClaim = undefined, agents = undefined, allowActiveWrongnessPartial = false, failureAnalysis = null, lightweightEvidence = false } = {}) {
10
11
  const policy = routeFinalizerPolicy(route, { strict, fixClaim, requireRelation, visualClaim });
11
12
  const localBlockers = [...blockers];
12
13
  const providedVisualEvidence = visualEvidence;
@@ -23,9 +24,14 @@ export async function finalizeRouteWithProof(root, { missionId, route, gateFile
23
24
  localBlockers.push(...(imageEvidence.issues?.length ? imageEvidence.issues : ['image_voxel_anchors_missing']));
24
25
  }
25
26
  }
26
- const collected = await collectProofEvidence(root);
27
+ const collected = lightweightEvidence ? { files: [] } : await collectProofEvidence(root);
28
+ const leanEngineeringEvidence = await collectLeanEngineeringEvidence(root, lightweightEvidence).catch((err) => ({
29
+ schema: 'sks.lean-change-evidence.v1',
30
+ status: 'not_collected',
31
+ reason: err?.message || String(err || 'unknown_error')
32
+ }));
27
33
  const agentEvidence = agents === false ? null : await readAgentProofEvidence(root, missionId).catch(() => null);
28
- const wrongnessEvidence = await wrongnessProofEvidence(root, missionId, { route: policy.route }).catch(() => null);
34
+ const wrongnessEvidence = lightweightEvidence ? null : await wrongnessProofEvidence(root, missionId, { route: policy.route }).catch(() => null);
29
35
  const requiresNativeComputerUseLiveEvidence = ['$Computer-Use', '$CU'].includes(String(policy.route || ''));
30
36
  const computerUse = requiresNativeComputerUseLiveEvidence
31
37
  ? await computerUseStatusReport().catch((err) => ({ schema: 'sks.computer-use-status.v1', status: 'unknown', ok: false, guidance: [err.message], evidence: { status: 'unknown' } }))
@@ -117,6 +123,7 @@ export async function finalizeRouteWithProof(root, { missionId, route, gateFile
117
123
  evidence: computerUse.evidence || null,
118
124
  live_evidence: computerUseLive?.evidence || null
119
125
  } } : {}),
126
+ lean_engineering: leanEngineeringEvidence,
120
127
  route_gate: gate || (gateFile ? { source: gateFile } : null)
121
128
  };
122
129
  return writeRouteCompletionProof(root, {
@@ -130,6 +137,7 @@ export async function finalizeRouteWithProof(root, { missionId, route, gateFile
130
137
  unverified: finalUnverified,
131
138
  blockers: localBlockers,
132
139
  failureAnalysis: resolvedFailureAnalysis,
140
+ lightweightEvidence,
133
141
  summary: {
134
142
  files_changed: collected.files?.length || 0,
135
143
  commands_run: evidence.commands?.length || 0,
@@ -139,6 +147,30 @@ export async function finalizeRouteWithProof(root, { missionId, route, gateFile
139
147
  }
140
148
  });
141
149
  }
150
+ async function collectLeanEngineeringEvidence(root, lightweightEvidence) {
151
+ if (lightweightEvidence) {
152
+ return leanChangeEvidenceFromReport({
153
+ changed_scope: {
154
+ mode: 'lightweight',
155
+ base: 'HEAD',
156
+ changed_files: [],
157
+ files_added: 0,
158
+ files_deleted: 0,
159
+ lines_added: 0,
160
+ lines_deleted: 0,
161
+ net_lines: 0,
162
+ source_files: [],
163
+ entries: []
164
+ },
165
+ semantic_review: {
166
+ status: 'needs-review',
167
+ findings: [{ tag: 'verify', severity: 'review', summary: 'lightweight proof skipped changed-scope code-structure scan' }]
168
+ }
169
+ });
170
+ }
171
+ const report = await scanCodeStructure(root, { changed: true });
172
+ return leanChangeEvidenceFromReport(report);
173
+ }
142
174
  function inferRouteFailureAnalysis({ missionId, route, status, blockers, unverified, wrongnessEvidence, imageEvidence, agentEvidence, computerUse, computerUseLive, visualComputerUseDowngrade } = {}) {
143
175
  if (status === 'verified' && !blockers?.length && !unverified?.length)
144
176
  return null;
@@ -0,0 +1,134 @@
1
+ import path from 'node:path';
2
+ import { appendJsonlBounded, nowIso, writeJsonAtomic } from '../fsx.js';
3
+ import { QA_ACTION_LEDGER_ARTIFACT, QA_LIVE_SESSION_ARTIFACT, QA_RUNTIME_EVENT_LEDGER_ARTIFACT } from './qa-types.js';
4
+ export async function runQaAppServerDriver(input) {
5
+ const events = [];
6
+ const dispose = input.client.onEvent?.((event) => {
7
+ events.push(event);
8
+ });
9
+ const startedAt = nowIso();
10
+ const blockers = [];
11
+ let threadId = null;
12
+ let turnId = null;
13
+ try {
14
+ await input.client.initialize?.();
15
+ const thread = await input.client.startThread({
16
+ cwd: input.cwd,
17
+ ...input.threadStartParams
18
+ });
19
+ threadId = extractThreadId(thread);
20
+ if (!threadId)
21
+ blockers.push('app_server_thread_id_missing');
22
+ if (threadId) {
23
+ const turn = await input.client.startTurn({
24
+ threadId,
25
+ cwd: input.cwd,
26
+ input: [{ type: 'text', text: input.prompt }],
27
+ ...input.turnStartParams
28
+ });
29
+ turnId = extractTurnId(turn);
30
+ if (!turnId)
31
+ blockers.push('app_server_turn_id_missing');
32
+ if (input.client.waitForTurnCompletion) {
33
+ const completed = await input.client.waitForTurnCompletion(threadId, turnId, input.timeoutMs);
34
+ events.push({ method: 'turn/completed', params: completed, received_at: nowIso() });
35
+ }
36
+ }
37
+ }
38
+ catch (err) {
39
+ blockers.push(`app_server_driver_failed:${err instanceof Error ? err.message : String(err)}`);
40
+ }
41
+ finally {
42
+ dispose?.();
43
+ }
44
+ await writeAppServerEventLedgers(input.missionDir, input.missionId, input.surfaceSelection.selected_surface, threadId, turnId, events);
45
+ const session = {
46
+ schema: 'sks.qa-loop-live-session.v2',
47
+ started_at: startedAt,
48
+ completed_at: nowIso(),
49
+ mission_id: input.missionId,
50
+ status: blockers.length ? 'blocked' : 'completed',
51
+ selected_surface: input.surfaceSelection.selected_surface,
52
+ thread_id: threadId,
53
+ turn_id: turnId,
54
+ event_count: events.length,
55
+ item_event_count: events.filter(isItemEvent).length,
56
+ action_event_count: events.filter(isActionLikeEvent).length,
57
+ observation_event_count: events.filter(isObservationLikeEvent).length,
58
+ blockers,
59
+ unverified: events.some(isActionLikeEvent) ? [] : ['app_server_action_event_unverified'],
60
+ artifacts: {
61
+ runtime_events: QA_RUNTIME_EVENT_LEDGER_ARTIFACT,
62
+ action_ledger: QA_ACTION_LEDGER_ARTIFACT
63
+ }
64
+ };
65
+ await writeJsonAtomic(path.join(input.missionDir, QA_LIVE_SESSION_ARTIFACT), session);
66
+ return session;
67
+ }
68
+ async function writeAppServerEventLedgers(missionDir, missionId, surface, threadId, turnId, events) {
69
+ for (const event of events) {
70
+ const method = String(event.method || event.type || event.params?.method || 'app_server_event');
71
+ await appendJsonlBounded(path.join(missionDir, QA_RUNTIME_EVENT_LEDGER_ARTIFACT), {
72
+ schema: 'sks.qa-loop-app-server-event.v2',
73
+ ts: nowIso(),
74
+ mission_id: missionId,
75
+ thread_id: event.params?.threadId || event.threadId || threadId,
76
+ turn_id: event.params?.turnId || event.params?.turn?.id || event.turnId || turnId,
77
+ item_id: event.params?.itemId || event.params?.item?.id || event.itemId || null,
78
+ surface,
79
+ kind: method,
80
+ status: 'observed',
81
+ data: redactEvent(event)
82
+ });
83
+ if (isActionLikeEvent(event)) {
84
+ await appendJsonlBounded(path.join(missionDir, QA_ACTION_LEDGER_ARTIFACT), {
85
+ schema: 'sks.qa-loop-action.v2',
86
+ ts: nowIso(),
87
+ mission_id: missionId,
88
+ thread_id: event.params?.threadId || event.threadId || threadId,
89
+ turn_id: event.params?.turnId || event.params?.turn?.id || event.turnId || turnId,
90
+ item_id: event.params?.itemId || event.params?.item?.id || event.itemId || null,
91
+ surface,
92
+ kind: method,
93
+ status: 'observed',
94
+ real: true,
95
+ data: redactEvent(event)
96
+ });
97
+ }
98
+ }
99
+ }
100
+ function extractThreadId(value) {
101
+ const obj = value;
102
+ return stringOrNull(obj?.thread?.id || obj?.threadId || obj?.id);
103
+ }
104
+ function extractTurnId(value) {
105
+ const obj = value;
106
+ return stringOrNull(obj?.turn?.id || obj?.turnId || obj?.id);
107
+ }
108
+ function stringOrNull(value) {
109
+ const text = String(value || '').trim();
110
+ return text || null;
111
+ }
112
+ function isItemEvent(event) {
113
+ return /^item\//.test(String(event.method || event.type || ''));
114
+ }
115
+ function isActionLikeEvent(event) {
116
+ const method = String(event.method || event.type || '');
117
+ return /^item\/.*(?:tool|action|commandExecution|computer|browser|chrome)/i.test(method)
118
+ || /(?:tool|action|click|type|scroll|navigate|screenshot|observation)/i.test(JSON.stringify(event.params || event));
119
+ }
120
+ function isObservationLikeEvent(event) {
121
+ const method = String(event.method || event.type || '');
122
+ return /observation|completed|screenshot|browser|chrome|computer/i.test(method)
123
+ || /observation|screenshot|visual|page|window/i.test(JSON.stringify(event.params || event));
124
+ }
125
+ function redactEvent(event) {
126
+ return JSON.parse(JSON.stringify(event, (key, value) => {
127
+ if (/(password|passwd|token|secret|cookie|authorization|credential)/i.test(String(key)))
128
+ return '[REDACTED]';
129
+ if (typeof value === 'string' && /(Bearer\s+[A-Za-z0-9._-]+|sk-[A-Za-z0-9_-]+)/.test(value))
130
+ return '[REDACTED]';
131
+ return value;
132
+ }));
133
+ }
134
+ //# sourceMappingURL=qa-app-server-driver.js.map