sneakoscope 0.7.13 → 0.7.18
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/package.json +1 -1
- package/src/cli/main.mjs +41 -8
- package/src/cli/maintenance-commands.mjs +5 -0
- package/src/core/fsx.mjs +1 -1
- package/src/core/init.mjs +8 -5
- package/src/core/perf-bench.mjs +9 -0
- package/src/core/pipeline.mjs +111 -3
- package/src/core/ppt.mjs +22 -0
- package/src/core/proof-field.mjs +129 -6
- package/src/core/routes.mjs +15 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "ㅅㅋㅅ",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.18",
|
|
5
5
|
"description": "Sneakoscope Codex: database-safe Codex CLI/App harness with Team, Goal, AutoResearch, TriWiki, and Honest Mode.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
|
package/src/cli/main.mjs
CHANGED
|
@@ -38,8 +38,8 @@ import {
|
|
|
38
38
|
} from '../core/ppt.mjs';
|
|
39
39
|
import { contextCapsule } from '../core/triwiki-attention.mjs';
|
|
40
40
|
import { rgbaKey, rgbaToWikiCoord, validateWikiCoordinateIndex } from '../core/wiki-coordinate.mjs';
|
|
41
|
-
import { ALLOWED_REASONING_EFFORTS, CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_EVIDENCE_SOURCE, CODEX_COMPUTER_USE_ONLY_POLICY, COMMAND_CATALOG, DOLLAR_COMMAND_ALIASES, DOLLAR_COMMANDS, DOLLAR_SKILL_NAMES, FROM_CHAT_IMG_CHECKLIST_ARTIFACT, FROM_CHAT_IMG_COVERAGE_ARTIFACT, FROM_CHAT_IMG_QA_LOOP_ARTIFACT, FROM_CHAT_IMG_SOURCE_INVENTORY_ARTIFACT, FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT, FROM_CHAT_IMG_TEMP_TRIWIKI_SESSIONS, FROM_CHAT_IMG_VISUAL_MAP_ARTIFACT, FROM_CHAT_IMG_WORK_ORDER_ARTIFACT, GETDESIGN_REFERENCE, RECOMMENDED_SKILLS, ROUTES, USAGE_TOPICS, context7ConfigToml, hasContext7ConfigText, hasFromChatImgSignal, looksLikeAnswerOnlyRequest, noUnrequestedFallbackCodePolicyText, reflectionRequiredForRoute, reasoningInstruction, routePrompt, routeReasoning, routeRequiresSubagents, speedLanePolicyText, stackCurrentDocsPolicy, triwikiContextTracking } from '../core/routes.mjs';
|
|
42
|
-
import { PIPELINE_PLAN_ARTIFACT, buildPipelinePlan, context7Evidence, evaluateStop, recordContext7Evidence, recordSubagentEvidence, validatePipelinePlan, writePipelinePlan } from '../core/pipeline.mjs';
|
|
41
|
+
import { ALLOWED_REASONING_EFFORTS, AWESOME_DESIGN_MD_REFERENCE, CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_EVIDENCE_SOURCE, CODEX_COMPUTER_USE_ONLY_POLICY, COMMAND_CATALOG, DESIGN_SYSTEM_SSOT, DOLLAR_COMMAND_ALIASES, DOLLAR_COMMANDS, DOLLAR_SKILL_NAMES, FROM_CHAT_IMG_CHECKLIST_ARTIFACT, FROM_CHAT_IMG_COVERAGE_ARTIFACT, FROM_CHAT_IMG_QA_LOOP_ARTIFACT, FROM_CHAT_IMG_SOURCE_INVENTORY_ARTIFACT, FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT, FROM_CHAT_IMG_TEMP_TRIWIKI_SESSIONS, FROM_CHAT_IMG_VISUAL_MAP_ARTIFACT, FROM_CHAT_IMG_WORK_ORDER_ARTIFACT, GETDESIGN_REFERENCE, RECOMMENDED_SKILLS, ROUTES, USAGE_TOPICS, context7ConfigToml, hasContext7ConfigText, hasFromChatImgSignal, looksLikeAnswerOnlyRequest, noUnrequestedFallbackCodePolicyText, reflectionRequiredForRoute, reasoningInstruction, routePrompt, routeReasoning, routeRequiresSubagents, speedLanePolicyText, stackCurrentDocsPolicy, triwikiContextTracking } from '../core/routes.mjs';
|
|
42
|
+
import { PIPELINE_PLAN_ARTIFACT, buildPipelinePlan, context7Evidence, evaluateStop, projectGateStatus, recordContext7Evidence, recordSubagentEvidence, validatePipelinePlan, writePipelinePlan } from '../core/pipeline.mjs';
|
|
43
43
|
import { TEAM_DECOMPOSITION_ARTIFACT, TEAM_GRAPH_ARTIFACT, TEAM_INBOX_DIR, TEAM_RUNTIME_TASKS_ARTIFACT, validateTeamRuntimeArtifacts, writeTeamRuntimeArtifacts } from '../core/team-dag.mjs';
|
|
44
44
|
import { appendTeamEvent, initTeamLive, parseTeamSpecText, readTeamDashboard, readTeamLive, readTeamTranscriptTail, renderTeamAgentLane } from '../core/team-live.mjs';
|
|
45
45
|
import { ARTIFACT_FILES, validateDogfoodReport, validateEffortDecision, validateFromChatImgVisualMap, validateSkillCandidate, validateSkillInjectionDecision, validateTeamDashboardState, validateWorkOrderLedger } from '../core/artifact-schemas.mjs';
|
|
@@ -469,11 +469,13 @@ async function pipeline(sub = 'status', args = []) {
|
|
|
469
469
|
const state = await readJson(stateFile(root), {});
|
|
470
470
|
const evidence = await context7Evidence(root, state);
|
|
471
471
|
const plan = state.mission_id ? await readJson(path.join(missionDir(root, state.mission_id), PIPELINE_PLAN_ARTIFACT), null) : null;
|
|
472
|
+
const gateProjection = await projectGateStatus(root, state);
|
|
472
473
|
const stop = await evaluateStop(root, state, { last_assistant_message: 'SKS Honest Mode verification evidence gap' }, { noQuestion: false });
|
|
473
474
|
const result = {
|
|
474
475
|
root,
|
|
475
476
|
state,
|
|
476
477
|
context7: evidence,
|
|
478
|
+
gate_projection: gateProjection,
|
|
477
479
|
plan: plan ? pipelinePlanSummary(plan, root, state.mission_id) : null,
|
|
478
480
|
stop_gate: state.stop_gate || null,
|
|
479
481
|
next_action: stop?.reason || 'No active blocking route gate detected.'
|
|
@@ -492,6 +494,7 @@ async function pipeline(sub = 'status', args = []) {
|
|
|
492
494
|
}
|
|
493
495
|
console.log(`Reasoning: ${state.reasoning_effort || 'medium'}${state.reasoning_profile ? ` (${state.reasoning_profile})` : ''}${state.reasoning_temporary ? ' temporary' : ''}`);
|
|
494
496
|
console.log(`Stop gate: ${state.stop_gate || 'none'}`);
|
|
497
|
+
console.log(`Gate projection: ${gateProjection.ok ? 'ok' : `blocked (${gateProjection.blockers.join(', ')})`}`);
|
|
495
498
|
console.log(`Context7: ${state.context7_required ? (evidence.ok ? 'ok' : 'required-missing') : 'optional'} (${evidence.count || 0} event(s))`);
|
|
496
499
|
console.log(`Next: ${result.next_action}`);
|
|
497
500
|
}
|
|
@@ -520,10 +523,11 @@ async function pipelinePlan(root, args = []) {
|
|
|
520
523
|
const changedRaw = readOption(args, '--changed', '');
|
|
521
524
|
const proofField = flag(args, '--proof-field') ? await buildProofField(root, { intent, changedFiles: changedRaw ? changedRaw.split(',') : undefined }) : null;
|
|
522
525
|
const contract = dir ? await readJson(path.join(dir, 'decision-contract.json'), {}) : {};
|
|
526
|
+
const contractSealed = contract?.status === 'sealed' || Boolean(contract?.sealed_at || contract?.sealed_hash);
|
|
523
527
|
const ambiguity = {
|
|
524
|
-
required: Boolean(routeContext.clarification_gate || state.ambiguity_gate_required),
|
|
525
|
-
passed: Boolean(state.ambiguity_gate_passed || state.clarification_passed),
|
|
526
|
-
status: state.clarification_required ? 'awaiting_answers' : (state.ambiguity_gate_passed ? 'contract_sealed' : undefined),
|
|
528
|
+
required: Boolean(routeContext.clarification_gate || state.ambiguity_gate_required || contractSealed),
|
|
529
|
+
passed: Boolean(state.ambiguity_gate_passed || state.clarification_passed || contractSealed),
|
|
530
|
+
status: state.clarification_required ? 'awaiting_answers' : ((state.ambiguity_gate_passed || contractSealed) ? 'contract_sealed' : undefined),
|
|
527
531
|
contract_hash: contract?.sealed_hash || null
|
|
528
532
|
};
|
|
529
533
|
const planInput = { missionId: id || null, route, task: intent, required: Boolean(routeContext.context7_required || state.context7_required), ambiguity, proofField };
|
|
@@ -1719,6 +1723,27 @@ async function selftest() {
|
|
|
1719
1723
|
if (trippedStop) throw new Error('selftest failed: compliance loop guard did not terminally trip');
|
|
1720
1724
|
const loopBlocker = await readJson(path.join(loopMission.dir, 'hard-blocker.json'), null);
|
|
1721
1725
|
if (loopBlocker?.reason !== 'compliance_loop_guard_tripped') throw new Error('selftest failed: compliance loop guard did not write hard blocker');
|
|
1726
|
+
const clarificationMission = await createMission(tmp, { mode: 'team', prompt: 'visible question gate selftest' });
|
|
1727
|
+
await writeTextAtomic(path.join(clarificationMission.dir, 'questions.md'), '# Questions\n\n1. GOAL_PRECISE: What should be changed?\n');
|
|
1728
|
+
await writeJsonAtomic(path.join(clarificationMission.dir, 'required-answers.schema.json'), { slots: [{ id: 'GOAL_PRECISE', question: 'What should be changed?' }] });
|
|
1729
|
+
const clarificationState = {
|
|
1730
|
+
mission_id: clarificationMission.id,
|
|
1731
|
+
mode: 'TEAM',
|
|
1732
|
+
route_command: '$Team',
|
|
1733
|
+
phase: 'TEAM_CLARIFICATION_AWAITING_ANSWERS',
|
|
1734
|
+
clarification_required: true,
|
|
1735
|
+
implementation_allowed: false,
|
|
1736
|
+
ambiguity_gate_required: true,
|
|
1737
|
+
ambiguity_gate_passed: false,
|
|
1738
|
+
stop_gate: 'clarification-gate'
|
|
1739
|
+
};
|
|
1740
|
+
for (let i = 0; i < 5; i++) {
|
|
1741
|
+
const stop = await evaluateStop(tmp, clarificationState, { last_assistant_message: 'continuing implementation without visible questions' });
|
|
1742
|
+
if (stop?.decision !== 'block' || !String(stop.reason || '').includes('waiting for mandatory ambiguity-removal answers')) throw new Error('selftest failed: clarification gate did not hard-pause without visible questions');
|
|
1743
|
+
}
|
|
1744
|
+
if (await exists(path.join(clarificationMission.dir, 'hard-blocker.json'))) throw new Error('selftest failed: clarification gate used compliance hard-blocker instead of waiting for answers');
|
|
1745
|
+
const visibleQuestionStop = await evaluateStop(tmp, clarificationState, { last_assistant_message: 'Required questions still pending:\n1. GOAL_PRECISE: What should be changed?\n\nUse sks pipeline answer latest answers.json.' });
|
|
1746
|
+
if (visibleQuestionStop?.continue !== true) throw new Error('selftest failed: visible clarification question block did not allow the question-only turn to stop');
|
|
1722
1747
|
await setCurrent(tmp, loopState);
|
|
1723
1748
|
const dfixPromptHook = await runProcess(process.execPath, [path.join(packageRoot(), 'bin', 'sks.mjs'), 'hook', 'user-prompt-submit'], {
|
|
1724
1749
|
cwd: tmp,
|
|
@@ -1807,7 +1832,9 @@ async function selftest() {
|
|
|
1807
1832
|
if (!String(postinstallSetup.stdout || '').includes('Codex App global $ skills: installed')) throw new Error('selftest failed: postinstall did not report automatic global Codex App skills');
|
|
1808
1833
|
const postinstallSetupManifest = await readJson(path.join(postinstallSetupTmp, '.sneakoscope', 'manifest.json'));
|
|
1809
1834
|
if (postinstallSetupManifest.installation?.scope !== 'global') throw new Error('selftest failed: postinstall automatic bootstrap did not use global install scope');
|
|
1835
|
+
if (postinstallSetupManifest.design_system_ssot?.authority_file !== DESIGN_SYSTEM_SSOT.authority_file || postinstallSetupManifest.design_system_ssot?.builder_prompt !== DESIGN_SYSTEM_SSOT.builder_prompt) throw new Error('selftest failed: postinstall manifest missing design SSOT policy');
|
|
1810
1836
|
if (!postinstallSetupManifest.recommended_design_references?.some((entry) => entry.id === 'getdesign' && entry.codex_skill_install === GETDESIGN_REFERENCE.codex_skill_install)) throw new Error('selftest failed: postinstall manifest missing getdesign reference');
|
|
1837
|
+
if (!postinstallSetupManifest.recommended_design_references?.some((entry) => entry.id === AWESOME_DESIGN_MD_REFERENCE.id && entry.url === AWESOME_DESIGN_MD_REFERENCE.url)) throw new Error('selftest failed: postinstall manifest missing awesome-design-md reference');
|
|
1811
1838
|
for (const rel of ['.agents/skills/team/SKILL.md', '.codex/config.toml', '.codex/hooks.json', '.sneakoscope/harness-guard.json', '.codex/SNEAKOSCOPE.md', 'AGENTS.md', '.gitignore']) {
|
|
1812
1839
|
if (!(await exists(path.join(postinstallSetupTmp, rel)))) throw new Error(`selftest failed: automatic postinstall bootstrap did not create ${rel}`);
|
|
1813
1840
|
}
|
|
@@ -1999,7 +2026,7 @@ async function selftest() {
|
|
|
1999
2026
|
const promptPipelineText = await safeReadText(path.join(tmp, '.agents', 'skills', 'prompt-pipeline', 'SKILL.md'));
|
|
2000
2027
|
if (!promptPipelineText.includes('TriWiki context-tracking SSOT')) throw new Error('selftest failed: prompt pipeline missing TriWiki context-tracking SSOT');
|
|
2001
2028
|
if (!promptPipelineText.includes('before every route stage') || !promptPipelineText.includes('sks wiki refresh')) throw new Error('selftest failed: prompt pipeline missing per-stage TriWiki policy');
|
|
2002
|
-
if (!promptPipelineText.includes('design
|
|
2029
|
+
if (!promptPipelineText.includes('single design decision authority') || !promptPipelineText.includes('imagegen') || !promptPipelineText.includes('getdesign-reference') || !promptPipelineText.includes(AWESOME_DESIGN_MD_REFERENCE.url) || !promptPipelineText.includes('not parallel authorities')) throw new Error('selftest failed: prompt pipeline missing design SSOT/source-input routing');
|
|
2003
2030
|
if (!promptPipelineText.includes(CODEX_APP_IMAGE_GENERATION_DOC_URL)) throw new Error('selftest failed: prompt pipeline missing Codex App image generation policy');
|
|
2004
2031
|
if (!promptPipelineText.includes('From-Chat-IMG') || !promptPipelineText.includes('Do not assume ordinary image prompts are chat captures')) throw new Error('selftest failed: prompt pipeline missing explicit From-Chat-IMG gating');
|
|
2005
2032
|
const fromChatImgSkillText = await safeReadText(path.join(tmp, '.agents', 'skills', 'from-chat-img', 'SKILL.md'));
|
|
@@ -2012,6 +2039,9 @@ async function selftest() {
|
|
|
2012
2039
|
}
|
|
2013
2040
|
const imagegenSkillText = await safeReadText(path.join(tmp, '.agents', 'skills', 'imagegen', 'SKILL.md'));
|
|
2014
2041
|
if (!imagegenSkillText.includes(CODEX_APP_IMAGE_GENERATION_DOC_URL) || !imagegenSkillText.includes('$imagegen') || !imagegenSkillText.includes('gpt-image-2') || !imagegenSkillText.includes('OPENAI_API_KEY')) throw new Error('selftest failed: imagegen skill missing official Codex App image generation priority');
|
|
2042
|
+
const getdesignSkillText = await safeReadText(path.join(tmp, '.agents', 'skills', 'getdesign-reference', 'SKILL.md')); if (!getdesignSkillText.includes(AWESOME_DESIGN_MD_REFERENCE.url) || !getdesignSkillText.includes('only design decision SSOT') || !getdesignSkillText.includes('source inputs')) throw new Error('selftest failed: getdesign-reference skill missing design SSOT source-input guidance');
|
|
2043
|
+
const designSystemBuilderSkillText = await safeReadText(path.join(tmp, '.agents', 'skills', 'design-system-builder', 'SKILL.md')); if (!designSystemBuilderSkillText.includes(AWESOME_DESIGN_MD_REFERENCE.url) || !designSystemBuilderSkillText.includes('Fuse those inputs into one design.md SSOT') || !designSystemBuilderSkillText.includes('competing authorities')) throw new Error('selftest failed: design-system-builder skill missing fused design SSOT guidance');
|
|
2044
|
+
const designSysPromptText = await safeReadText(path.join(packageRoot(), 'docs', 'Design-Sys-Prompt.md')); if (!designSysPromptText.includes('Design SSOT contract') || !designSysPromptText.includes('builder prompt') || !designSysPromptText.includes('not a competing design authority')) throw new Error('selftest failed: Design-Sys-Prompt missing design SSOT contract');
|
|
2015
2045
|
if (!(await exists(path.join(tmp, '.agents', 'skills', 'reasoning-router', 'agents', 'openai.yaml')))) throw new Error('selftest failed: skill metadata missing');
|
|
2016
2046
|
const hookGuardPayload = JSON.stringify({ cwd: tmp, tool_name: 'apply_patch', command: '*** Update File: .agents/skills/team/SKILL.md\n+tamper\n' });
|
|
2017
2047
|
const hookGuardResult = await runProcess(process.execPath, [path.join(packageRoot(), 'bin', 'sks.mjs'), 'hook', 'pre-tool'], { cwd: tmp, input: hookGuardPayload, env: { SKS_DISABLE_UPDATE_CHECK: '1' }, timeoutMs: 15000, maxOutputBytes: 64 * 1024 });
|
|
@@ -2759,7 +2789,7 @@ async function selftest() {
|
|
|
2759
2789
|
}
|
|
2760
2790
|
const pptSkillText = await safeReadText(path.join(tmp, '.agents', 'skills', 'ppt', 'SKILL.md'));
|
|
2761
2791
|
if (!pptSkillText.includes('STP') || !pptSkillText.includes('target audience profile') || !pptSkillText.includes('decision context') || !pptSkillText.includes('3+ pain-point to solution mappings')) throw new Error('selftest failed: generated PPT skill missing STP/audience/pain-point guidance');
|
|
2762
|
-
if (!pptSkillText.includes('simple, restrained, and information-first') || !pptSkillText.includes('over-designed decoration') || !pptSkillText.includes(CODEX_APP_IMAGE_GENERATION_DOC_URL)) throw new Error('selftest failed: generated PPT skill missing restrained design/imagegen guidance');
|
|
2792
|
+
if (!pptSkillText.includes('simple, restrained, and information-first') || !pptSkillText.includes('over-designed decoration') || !pptSkillText.includes(CODEX_APP_IMAGE_GENERATION_DOC_URL) || !pptSkillText.includes(AWESOME_DESIGN_MD_REFERENCE.url) || !pptSkillText.includes('only design decision SSOT') || !pptSkillText.includes('instead of treating references as parallel authorities')) throw new Error('selftest failed: generated PPT skill missing restrained design/imagegen/fused-SSOT guidance');
|
|
2763
2793
|
if (!pptSkillText.includes('source-html/') || !pptSkillText.includes('temporary build files') || !pptSkillText.includes('ppt-parallel-report.json')) throw new Error('selftest failed: generated PPT skill missing source preservation/temp cleanup/parallel guidance');
|
|
2764
2794
|
if (routeRequiresSubagents(pptRoute, '$PPT 투자자용 피치덱 만들어줘')) throw new Error('selftest failed: PPT route should not require subagents by default');
|
|
2765
2795
|
if (!reflectionRequiredForRoute(pptRoute)) throw new Error('selftest failed: PPT route should require reflection');
|
|
@@ -2787,6 +2817,8 @@ async function selftest() {
|
|
|
2787
2817
|
if (!PPT_HTML_ARTIFACT.startsWith(`${PPT_SOURCE_HTML_DIR}/`)) throw new Error('selftest failed: PPT HTML source must be stored in source-html folder');
|
|
2788
2818
|
const pptHtml = await safeReadText(path.join(pptMission.dir, PPT_HTML_ARTIFACT));
|
|
2789
2819
|
if (!pptHtml.includes('<html') || pptHtml.includes('gradient')) throw new Error('selftest failed: PPT HTML artifact missing or over-designed');
|
|
2820
|
+
const pptStyleTokens = await readJson(path.join(pptMission.dir, 'ppt-style-tokens.json'));
|
|
2821
|
+
if (pptStyleTokens.design_policy?.design_ssot?.authority !== DESIGN_SYSTEM_SSOT.authority_file || !pptStyleTokens.design_policy?.source_inputs?.some((entry) => entry.url === AWESOME_DESIGN_MD_REFERENCE.url && entry.role === 'source_input_for_ssot') || !pptStyleTokens.design_policy?.anti_generic_ai_style) throw new Error('selftest failed: PPT style tokens missing fused design SSOT/source-input anti-generic policy');
|
|
2790
2822
|
const audienceScript = pptHtml.match(/id="ppt-audience-strategy">([^<]+)<\/script>/);
|
|
2791
2823
|
if (!audienceScript) throw new Error('selftest failed: PPT HTML missing audience strategy script data');
|
|
2792
2824
|
JSON.parse(audienceScript[1]);
|
|
@@ -2852,13 +2884,14 @@ async function selftest() {
|
|
|
2852
2884
|
if (!harnessReport.forgetting.fixture.passed || !harnessReport.tmux.views.includes('Harness Experiments View') || !harnessReport.reliability.tool_error_taxonomy.includes('Unknown')) throw new Error('selftest failed: harness growth fixture incomplete');
|
|
2853
2885
|
const proofField = await proofFieldFixture();
|
|
2854
2886
|
if (!proofField.validation.ok || !validateProofFieldReport(proofField.report).ok) throw new Error('selftest failed: proof field report invalid');
|
|
2855
|
-
if (!proofField.checks.route_cone_selected || !proofField.checks.cli_cone_selected || !proofField.checks.catastrophic_guard_present || !proofField.checks.negative_release_work_recorded || !proofField.checks.outcome_rubric_present || !proofField.checks.adversarial_lenses_present || !proofField.checks.simplicity_score_usable || !proofField.checks.execution_fast_lane_selected) throw new Error('selftest failed: proof field fixture checks incomplete');
|
|
2887
|
+
if (!proofField.checks.route_cone_selected || !proofField.checks.cli_cone_selected || !proofField.checks.catastrophic_guard_present || !proofField.checks.negative_release_work_recorded || !proofField.checks.outcome_rubric_present || !proofField.checks.adversarial_lenses_present || !proofField.checks.route_economy_present || !proofField.checks.simplicity_score_usable || !proofField.checks.execution_fast_lane_selected) throw new Error('selftest failed: proof field fixture checks incomplete');
|
|
2856
2888
|
if (!speedLanePolicyText().includes('proof_field_fast_lane') || !proofField.report.execution_lane?.skip_when_fast?.includes('planning_debate')) throw new Error('selftest failed: Proof Field speed lane policy missing');
|
|
2857
2889
|
const fastPipelinePlan = buildPipelinePlan({ route: routePrompt('$Team small CLI help update'), task: 'small CLI help surface update', proofField: proofField.report });
|
|
2858
2890
|
if (!validatePipelinePlan(fastPipelinePlan).ok || fastPipelinePlan.runtime_lane?.lane !== 'proof_field_fast_lane' || !fastPipelinePlan.skipped_stages.includes('planning_debate') || !fastPipelinePlan.invariants.includes('no_unrequested_fallback_code')) throw new Error('selftest failed: pipeline plan did not encode fast lane stage skips and fallback guard');
|
|
2859
2891
|
const broadProofField = await buildProofField(tmp, { intent: 'database security route refactor', changedFiles: ['src/core/db-safety.mjs', 'src/core/routes.mjs', 'src/cli/main.mjs', 'README.md'] });
|
|
2860
2892
|
const broadPipelinePlan = buildPipelinePlan({ route: routePrompt('$Team database security route refactor'), task: 'database security route refactor', proofField: broadProofField });
|
|
2861
2893
|
if (!validatePipelinePlan(broadPipelinePlan).ok || broadPipelinePlan.runtime_lane?.lane === 'proof_field_fast_lane' || broadPipelinePlan.skipped_stages.includes('planning_debate')) throw new Error('selftest failed: pipeline plan did not fail closed for broad/security work');
|
|
2894
|
+
if (broadPipelinePlan.route_economy?.mode !== 'report_only' || !broadPipelinePlan.route_economy.active_team_triggers?.includes('broad_change_set') || !broadPipelinePlan.route_economy.verification_stage_cache_key) throw new Error('selftest failed: route economy projection missing from pipeline plan');
|
|
2862
2895
|
const workflowPerf = await runWorkflowPerfBench(tmp, {
|
|
2863
2896
|
iterations: 2,
|
|
2864
2897
|
intent: 'small CLI help surface update',
|
|
@@ -529,6 +529,8 @@ export async function perfCommand(sub, args = []) {
|
|
|
529
529
|
console.log(`Mode: ${report.metrics.decision_mode}`);
|
|
530
530
|
console.log(`Fast lane: ${report.metrics.fast_lane_eligible ? 'yes' : 'no'}`);
|
|
531
531
|
console.log(`Proof Field p95: ${report.metrics.proof_field_build_ms_p95}ms`);
|
|
532
|
+
console.log(`Contract clarity: ${report.metrics.contract_clarity_score}`);
|
|
533
|
+
console.log(`Workflow complexity: ${report.metrics.workflow_complexity_band} (${report.metrics.workflow_complexity_score})`);
|
|
532
534
|
console.log(`Proof cones: ${report.metrics.proof_cone_count}`);
|
|
533
535
|
console.log(`Negative work skipped: ${report.metrics.negative_work_skipped_count}`);
|
|
534
536
|
console.log(`Next: ${report.recommendation.next.join('; ')}`);
|
|
@@ -569,6 +571,9 @@ export async function proofFieldCommand(sub, args = []) {
|
|
|
569
571
|
console.log(`Mode: ${report.fast_lane_decision.mode}`);
|
|
570
572
|
console.log(`Eligible: ${report.fast_lane_decision.eligible ? 'yes' : 'no'}`);
|
|
571
573
|
if (report.fast_lane_decision.blockers.length) console.log(`Blockers: ${report.fast_lane_decision.blockers.join(', ')}`);
|
|
574
|
+
console.log(`Contract clarity: ${report.contract_clarity.score}${report.contract_clarity.ask_recommended ? ' (ask recommended)' : ''}`);
|
|
575
|
+
console.log(`Workflow complexity: ${report.workflow_complexity.band} (${report.workflow_complexity.score})`);
|
|
576
|
+
if (report.team_trigger_matrix.active_triggers.length) console.log(`Team triggers: ${report.team_trigger_matrix.active_triggers.join(', ')}`);
|
|
572
577
|
console.log(`Proof cones: ${report.proof_cones.map((cone) => cone.id).join(', ')}`);
|
|
573
578
|
console.log(`Verification: ${report.fast_lane_decision.verification.join('; ')}`);
|
|
574
579
|
console.log(`Report: ${path.relative(root, report.report_path)}`);
|
package/src/core/fsx.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import os from 'node:os';
|
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
7
|
|
|
8
|
-
export const PACKAGE_VERSION = '0.7.
|
|
8
|
+
export const PACKAGE_VERSION = '0.7.18';
|
|
9
9
|
export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
|
|
10
10
|
export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
|
|
11
11
|
|
package/src/core/init.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { DEFAULT_DB_SAFETY_POLICY } from './db-safety.mjs';
|
|
|
6
6
|
import { isHarnessSourceProject, writeHarnessGuardPolicy } from './harness-guard.mjs';
|
|
7
7
|
import { repairSksGeneratedArtifacts } from './harness-conflicts.mjs';
|
|
8
8
|
import { installVersionGitHook } from './version-manager.mjs';
|
|
9
|
-
import { CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_ONLY_POLICY, DOLLAR_COMMANDS, DOLLAR_COMMAND_ALIASES, 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, RECOMMENDED_DESIGN_REFERENCES, RECOMMENDED_MCP_SERVERS, RECOMMENDED_SKILLS, chatCaptureIntakeText, context7ConfigToml, getdesignReferencePolicyText, outcomeRubricPolicyText, speedLanePolicyText, stackCurrentDocsPolicyText, triwikiContextTracking, triwikiContextTrackingText, triwikiStagePolicyText } from './routes.mjs';
|
|
9
|
+
import { AWESOME_DESIGN_MD_REFERENCE, CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_ONLY_POLICY, DESIGN_SYSTEM_SSOT, DOLLAR_COMMANDS, DOLLAR_COMMAND_ALIASES, 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, RECOMMENDED_DESIGN_REFERENCES, RECOMMENDED_MCP_SERVERS, RECOMMENDED_SKILLS, chatCaptureIntakeText, context7ConfigToml, getdesignReferencePolicyText, outcomeRubricPolicyText, speedLanePolicyText, stackCurrentDocsPolicyText, triwikiContextTracking, triwikiContextTrackingText, triwikiStagePolicyText } from './routes.mjs';
|
|
10
10
|
import { SKILL_DREAM_POLICY, skillDreamPolicyText } from './skill-forge.mjs';
|
|
11
11
|
|
|
12
12
|
const REFLECTION_MEMORY_PATH = '.sneakoscope/memory/q2_facts/post-route-reflection.md';
|
|
@@ -91,7 +91,7 @@ function isSksManagedHook(hook) {
|
|
|
91
91
|
return hook.type === 'command' && /\bhook\s+(?:user-prompt-submit|pre-tool|post-tool|permission-request|stop)\b/.test(command) && /\b(?:sks|sneakoscope|sks\.mjs)\b/.test(command);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
const AGENTS_BLOCK = "\n# Sneakoscope Codex Managed Rules\n\nThis repository uses Sneakoscope Codex.\n\n## Core Rules\n\n- Codex native `/goal` workflows are the persisted continuation surface; Ralph is removed from the user-facing SKS surface.\n- Keep runtime state bounded: raw logs go to files, prompts get tails/summaries, and `sks gc` may prune stale artifacts.\n- Before substantive work, SKS checks npm for a newer package. If newer, ask update-now vs skip-for-this-conversation.\n- Versioning is managed by the SKS pre-commit hook; check `sks versioning status`. Bypass only with `SKS_DISABLE_VERSIONING=1`.\n- Installed harness files are immutable to LLM edits: `.codex/*`, `.agents/skills/`, `.codex/agents/`, `.sneakoscope/*policy*.json`, `AGENTS.md`, and `node_modules/sneakoscope`. The Sneakoscope engine source repo is the only automatic exception.\n- OMX/DCodex conflicts block setup/doctor. Show `sks conflicts prompt`; cleanup requires explicit human approval.\n- Do not stop at a plan when implementation was requested. Finish, verify, or report the hard blocker.\n- Do not create unrequested fallback implementation code. If the requested path is impossible, block with evidence instead of inventing substitute behavior.\n\n## Routes\n\n- General execution/code-changing prompts default to `$Team`: analysis scouts, TriWiki refresh/validate, read-only debate, consensus, concrete runtime task graph/inboxes, fresh executor team, review, integration, Honest Mode.\n- `$Computer-Use` / `$CU` is the maximum-speed Codex Computer Use lane for UI/browser/visual tasks: skip Team debate and upfront TriWiki loops, use Codex Computer Use directly, then refresh/validate TriWiki and run Honest Mode at final closeout.\n- `$Goal` is a fast bridge/overlay for Codex native `/goal` create/pause/resume/clear persistence controls; implementation continues through the selected SKS execution route.\n- TriWiki recall must stay bounded. Use `sks wiki sweep` to record demote, soft-forget, archive, delete, promote-to-skill, and promote-to-rule candidates instead of injecting every old claim.\n- Team missions must keep schema-backed evidence current: `work-order-ledger.json`, `effort-decision.json`, `team-dashboard-state.json`, and route-specific visual/dogfood artifacts where applicable. Use `sks validate-artifacts latest` before claiming those artifacts pass.\n- `$DFix` is only for tiny design/content edits and bypasses the main pipeline, Team, TriWiki/TriFix/reflection recording, and persistent route state; it still uses a one-line DFix-specific Honest check before final. `$PPT` is the restrained, information-first HTML/PDF presentation route and must seal delivery context, audience profile, STP, decision context, and 3+ pain-point/solution/aha mappings before design/render work. It must avoid over-designed visuals, carry detail through hierarchy, spacing, alignment, thin rules, source clarity, and subtle accents, preserve editable source HTML under `source-html/`, record `ppt-parallel-report.json`, and clean PPT-only temporary build files before completion. `$Answer`, `$Help`, and `$Wiki` stay lightweight.\n- For code work, surface route/guard/write scopes first, split independent worker scopes when available, and keep parent-owned integration and verification.\n- Design work reads `design.md
|
|
94
|
+
const AGENTS_BLOCK = "\n# Sneakoscope Codex Managed Rules\n\nThis repository uses Sneakoscope Codex.\n\n## Core Rules\n\n- Codex native `/goal` workflows are the persisted continuation surface; Ralph is removed from the user-facing SKS surface.\n- Keep runtime state bounded: raw logs go to files, prompts get tails/summaries, and `sks gc` may prune stale artifacts.\n- Before substantive work, SKS checks npm for a newer package. If newer, ask update-now vs skip-for-this-conversation.\n- Versioning is managed by the SKS pre-commit hook; check `sks versioning status`. Bypass only with `SKS_DISABLE_VERSIONING=1`.\n- Installed harness files are immutable to LLM edits: `.codex/*`, `.agents/skills/`, `.codex/agents/`, `.sneakoscope/*policy*.json`, `AGENTS.md`, and `node_modules/sneakoscope`. The Sneakoscope engine source repo is the only automatic exception.\n- OMX/DCodex conflicts block setup/doctor. Show `sks conflicts prompt`; cleanup requires explicit human approval.\n- Do not stop at a plan when implementation was requested. Finish, verify, or report the hard blocker.\n- Do not create unrequested fallback implementation code. If the requested path is impossible, block with evidence instead of inventing substitute behavior.\n\n## Routes\n\n- General execution/code-changing prompts default to `$Team`: analysis scouts, TriWiki refresh/validate, read-only debate, consensus, concrete runtime task graph/inboxes, fresh executor team, review, integration, Honest Mode.\n- `$Computer-Use` / `$CU` is the maximum-speed Codex Computer Use lane for UI/browser/visual tasks: skip Team debate and upfront TriWiki loops, use Codex Computer Use directly, then refresh/validate TriWiki and run Honest Mode at final closeout.\n- `$Goal` is a fast bridge/overlay for Codex native `/goal` create/pause/resume/clear persistence controls; implementation continues through the selected SKS execution route.\n- TriWiki recall must stay bounded. Use `sks wiki sweep` to record demote, soft-forget, archive, delete, promote-to-skill, and promote-to-rule candidates instead of injecting every old claim.\n- Team missions must keep schema-backed evidence current: `work-order-ledger.json`, `effort-decision.json`, `team-dashboard-state.json`, and route-specific visual/dogfood artifacts where applicable. Use `sks validate-artifacts latest` before claiming those artifacts pass.\n- `$DFix` is only for tiny design/content edits and bypasses the main pipeline, Team, TriWiki/TriFix/reflection recording, and persistent route state; it still uses a one-line DFix-specific Honest check before final. `$PPT` is the restrained, information-first HTML/PDF presentation route and must seal delivery context, audience profile, STP, decision context, and 3+ pain-point/solution/aha mappings before design/render work. It must avoid over-designed visuals, carry detail through hierarchy, spacing, alignment, thin rules, source clarity, and subtle accents, preserve editable source HTML under `source-html/`, record `ppt-parallel-report.json`, and clean PPT-only temporary build files before completion. `$Answer`, `$Help`, and `$Wiki` stay lightweight.\n- For code work, surface route/guard/write scopes first, split independent worker scopes when available, and keep parent-owned integration and verification.\n- Design work reads `design.md` as the only design decision SSOT. If missing, create it through `design-system-builder` from `docs/Design-Sys-Prompt.md`; getdesign.md, getdesign-reference, and curated DESIGN.md examples from https://github.com/VoltAgent/awesome-design-md are source inputs to fuse into that SSOT or route-local style tokens, not parallel design authorities. Image/logo/raster assets use `imagegen`, which must prefer official Codex App built-in image generation via `$imagegen` / `gpt-image-2` before API generation.\n- Research, AutoResearch, performance, token, accuracy, SEO/GEO, or workflow-improvement claims need experiment/eval evidence. Do not claim live model accuracy without a scored dataset.\n- Treat handwritten files above 3000 lines as split-review risks. Run `sks code-structure scan` and prefer extraction before adding substantial logic.\n- Skill dreaming stays lightweight: route use records JSON counters in `.sneakoscope/skills/dream-state.json`, and full skill inventory/recommendation runs only after the configured count/cooldown threshold. Reports are recommendation-only; deleting or merging skills needs explicit user approval.\n\n## Evidence And Context\n\n- Context7 is required for external libraries, APIs, MCPs, package managers, SDKs, and generated docs: resolve-library-id then query-docs.\n- When tech stack, framework, package, runtime, or deployment-platform versions change, use Context7 or official vendor web docs, record current syntax/security/limit guidance as high-priority TriWiki claims, then refresh and validate before coding.\n- TriWiki is the context-tracking SSOT for long-running missions, Team handoffs, and context-pressure recovery. Read `.sneakoscope/wiki/context-pack.json` before each stage, use `attention.use_first` for compact high-trust recall, hydrate `attention.hydrate_first` from source before risky or lower-trust decisions, refresh after findings or artifact changes, and validate before handoffs/final claims.\n- Source priority: current code/tests/config, decision contract, vgraph, beta, GX render/snapshot metadata, LLM Wiki coordinate index, then model knowledge only if allowed.\n- Final response before stop: summarize what was done, what changed for the user/repo, what was verified, and what remains unverified or blocked; then run Honest Mode. Say what passed and what was not verified.\n- `$From-Chat-IMG` uses forensic visual effort, not ordinary Team effort. Completion is blocked until source inventory, visual mapping, work-order coverage, scoped dogfood/QA, and post-fix verification artifacts are present and valid.\n\n## Safety\n\n- Database access is high risk. Use read-only inspection by default; live data mutation is out of scope unless a sealed contract allows local or branch-only migration files.\n- MAD and MAD-SKS widen only explicit scoped permissions; they still do not authorize unrequested fallback implementation code.\n- Task completion requires relevant tests or justification, zero unsupported critical claims, accepted visual/wiki drift, and final evidence.\n\n## Codex App\n\nUse `.codex/SNEAKOSCOPE.md`, generated `.agents/skills`, `.codex/hooks.json`, and SKS dollar commands (`$sks`, `$team`, `$computer-use`, `$cu`, `$ppt`, `$goal`, `$dfix`, `$qa-loop`, etc.) as the app control surface.\n";
|
|
95
95
|
|
|
96
96
|
export async function initProject(root, opts = {}) {
|
|
97
97
|
const created = [];
|
|
@@ -146,6 +146,7 @@ export async function initProject(root, opts = {}) {
|
|
|
146
146
|
},
|
|
147
147
|
recommended_skills: RECOMMENDED_SKILLS,
|
|
148
148
|
recommended_mcp_servers: RECOMMENDED_MCP_SERVERS,
|
|
149
|
+
design_system_ssot: DESIGN_SYSTEM_SSOT,
|
|
149
150
|
recommended_design_references: RECOMMENDED_DESIGN_REFERENCES,
|
|
150
151
|
skill_dreaming: {
|
|
151
152
|
state: SKILL_DREAM_POLICY.state_path,
|
|
@@ -276,6 +277,7 @@ export async function initProject(root, opts = {}) {
|
|
|
276
277
|
},
|
|
277
278
|
recommended_skills: RECOMMENDED_SKILLS,
|
|
278
279
|
recommended_mcp_servers: RECOMMENDED_MCP_SERVERS,
|
|
280
|
+
design_system_ssot: DESIGN_SYSTEM_SSOT,
|
|
279
281
|
recommended_design_references: RECOMMENDED_DESIGN_REFERENCES
|
|
280
282
|
});
|
|
281
283
|
}
|
|
@@ -394,6 +396,7 @@ export async function initProject(root, opts = {}) {
|
|
|
394
396
|
},
|
|
395
397
|
recommended_skills: RECOMMENDED_SKILLS,
|
|
396
398
|
recommended_mcp_servers: RECOMMENDED_MCP_SERVERS,
|
|
399
|
+
design_system_ssot: DESIGN_SYSTEM_SSOT,
|
|
397
400
|
recommended_design_references: RECOMMENDED_DESIGN_REFERENCES
|
|
398
401
|
};
|
|
399
402
|
}
|
|
@@ -547,7 +550,7 @@ export async function installSkills(root) {
|
|
|
547
550
|
'team': `---\nname: team\ndescription: SKS Team orchestration for $Team/code work; $From-Chat-IMG is the explicit chat-image alias.\n---\n\nUse for $Team/code work. Ambiguity gate first. Read pipeline-plan.json or run sks pipeline plan to see the runtime lane, kept/skipped stages, and verification before implementation. Write team-roster.json; team-gate.json needs team_roster_confirmed=true. executor:N means N scouts, N debate voices, then fresh N executors. After consensus, compile team-graph.json, team-runtime-tasks.json, team-decomposition-report.json, and team-inbox/ so worker handoff uses concrete runtime task ids with role/path/domain/lane hints. Refresh/validate TriWiki before debate, implementation, review, and final; consume attention.use_first and hydrate attention.hydrate_first before risky decisions. ${outcomeRubricPolicyText()} ${speedLanePolicyText()} ${skillDreamPolicyText()} Log events and use sks team message for bounded inter-agent communication in transcript/lane panes. Color-coded tmux lanes distinguish overview/scout/planning/execution/review/safety sessions. End with cleanup-tmux or a cleanup event so follow panes show cleanup and stop; pass team-session-cleanup.json, then reflection and Honest Mode. Parent integrates/verifies.\n\n${chatCaptureIntakeText()}\n`,
|
|
548
551
|
'from-chat-img': `---\nname: from-chat-img\ndescription: Explicit $From-Chat-IMG Team alias for chat screenshot plus attachment analysis.\n---\n\nUse only for From-Chat-IMG/$From-Chat-IMG. It enters the normal Team pipeline. Treat uploads as chat screenshot plus originals. Use Codex Computer Use visual inspection when available, list requirements first, match regions to attachments with confidence, write ${FROM_CHAT_IMG_COVERAGE_ARTIFACT}, ${FROM_CHAT_IMG_CHECKLIST_ARTIFACT}, ${FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT}, and ${FROM_CHAT_IMG_QA_LOOP_ARTIFACT}, then continue Team gates, review, reflection, and Honest Mode. ${CODEX_COMPUTER_USE_ONLY_POLICY} The ledger must account for every visible customer request, screenshot image region, and separate attachment; ${FROM_CHAT_IMG_CHECKLIST_ARTIFACT} must have a checked item for each request, image-region/attachment match, work item, scoped QA-LOOP, and verification step; ${FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT} stores temporary TriWiki-backed session context with expires_after_sessions=${FROM_CHAT_IMG_TEMP_TRIWIKI_SESSIONS}. ${FROM_CHAT_IMG_QA_LOOP_ARTIFACT} must prove QA-LOOP ran over the exact customer-request work-order range after implementation, with every work item covered, post-fix verification complete, and zero unresolved findings. team-gate.json cannot pass From-Chat-IMG completion until unresolved_items is empty, every checklist box is checked, and scoped_qa_loop_completed=true.\n`,
|
|
549
552
|
'qa-loop': `---\nname: qa-loop\ndescription: $QA-LOOP dogfoods UI/API as human proxy with safety gates, Codex Computer Use-only UI evidence, safe fixes, rechecks, and a QA report.\n---\n\nUse only $QA-LOOP. Ask scope, target, mutation, login. Credentials are runtime-only; never save secrets. UI-level E2E needs Codex Computer Use evidence or must be marked unverified; Chrome MCP, Browser Use, Playwright, Selenium, Puppeteer, and other browser automation do not satisfy UI/browser verification. Deployed targets are read-only; destructive removal is forbidden. After answer/run, dogfood real flows, apply safe contract-allowed code/test/docs fixes, recheck, and do not pass qa-gate.json with unresolved findings or without post_fix_verification_complete. Finish qa-ledger, date/version report, gate, completion summary, and Honest Mode.\n`,
|
|
550
|
-
'ppt': `---\nname: ppt\ndescription: $PPT information-first HTML/PDF presentation pipeline with STP, audience, pain-point, format, research, design-system, and verification questions.\n---\n\nUse only when the user invokes $PPT or asks to create a presentation, deck, slides, pitch deck, proposal deck, HTML presentation, or PDF presentation artifact. Before artifact work, seal presentation-specific ambiguity answers: delivery context, target audience profile including role/average age/job/industry/topic familiarity/decision power, STP strategy, decision context and objections, and 3+ pain-point to solution mappings with expected aha moments. Presentation design must be simple, restrained, and information-first: avoid over-designed decoration, ornamental gradients, nested cards, and effects that compete with the message. Design detail should be embedded through typography hierarchy, spacing, alignment, thin rules, source clarity, and subtle accents. Use getdesign-reference and
|
|
553
|
+
'ppt': `---\nname: ppt\ndescription: $PPT information-first HTML/PDF presentation pipeline with STP, audience, pain-point, format, research, design-system, and verification questions.\n---\n\nUse only when the user invokes $PPT or asks to create a presentation, deck, slides, pitch deck, proposal deck, HTML presentation, or PDF presentation artifact. Before artifact work, seal presentation-specific ambiguity answers: delivery context, target audience profile including role/average age/job/industry/topic familiarity/decision power, STP strategy, decision context and objections, and 3+ pain-point to solution mappings with expected aha moments. Presentation design must be simple, restrained, and information-first: avoid over-designed decoration, ornamental gradients, nested cards, and effects that compete with the message. Design detail should be embedded through typography hierarchy, spacing, alignment, thin rules, source clarity, and subtle accents. Use design.md as the only design decision SSOT. If design.md is missing, use docs/Design-Sys-Prompt.md plus getdesign-reference and curated DESIGN.md examples from ${AWESOME_DESIGN_MD_REFERENCE.url} only as source inputs, then fuse them into route-local PPT style tokens with a recorded design_ssot instead of treating references as parallel authorities. If generated image assets are needed, use imagegen and prefer Codex App built-in image generation (${CODEX_APP_IMAGE_GENERATION_DOC_URL}) before API generation. Use web or Context7 evidence when external facts/libraries are involved, then create the PDF plus editable source HTML under source-html/, keep independent strategy/render/file-write phases parallel where inputs allow, record ppt-parallel-report.json, and verify readability, overlap, format fit, source coverage, export state, and temporary build files cleanup. Finish with reflection and Honest Mode; do not skip STP/audience questions for presentation artifacts.\n`,
|
|
551
554
|
'computer-use': `---\nname: computer-use\ndescription: Maximum-speed $Computer-Use/$CU lane for Codex Computer Use UI/browser/visual tasks.\n---\n\nUse only when the user invokes $Computer-Use/$CU or asks for a Computer Use-specific fast lane. Skip Team debate, QA-LOOP clarification, upfront TriWiki refresh, Context7, subagents, and reflection unless explicitly requested. Infer the smallest target, use Codex Computer Use directly, and never substitute Playwright, Chrome MCP, Browser Use, Selenium, Puppeteer, or other browser automation for UI/browser evidence. If Computer Use is unavailable, mark UI/browser evidence unverified and stop with the blocker. At the end only, refresh or pack TriWiki, validate it, then provide a concise completion summary plus Honest Mode.\n`,
|
|
552
555
|
'computer-use-fast': `---\nname: computer-use-fast\ndescription: Alias for the maximum-speed $Computer-Use/$CU Codex Computer Use lane.\n---\n\nUse the same rules as computer-use: skip Team debate, QA-LOOP clarification, upfront TriWiki refresh, Context7, subagents, and reflection unless explicitly requested. Use Codex Computer Use directly; never substitute Playwright, Chrome MCP, Browser Use, Selenium, Puppeteer, or other browser automation for UI/browser evidence. At the end only, refresh/pack TriWiki, validate it, then provide a concise completion summary plus Honest Mode.\n`,
|
|
553
556
|
'cu': `---\nname: cu\ndescription: Short alias for the maximum-speed $Computer-Use Codex Computer Use lane.\n---\n\nUse the same rules as computer-use. This is a speed lane for focused UI/browser/visual tasks that require Codex Computer Use evidence, with TriWiki refresh/validate and Honest Mode deferred to final closeout.\n`,
|
|
@@ -576,8 +579,8 @@ export async function installSkills(root) {
|
|
|
576
579
|
'research-discovery': `---\nname: research-discovery\ndescription: Run SKS Research Mode for frontier-style research, hypotheses, novelty ledgers, falsification, and experiments.\n---\n\nFrame criteria, map assumptions, generate hypotheses, falsify, keep surviving insights, and record novelty/confidence/falsifiers/next experiments. Do not overclaim.\n`,
|
|
577
580
|
'performance-evaluator': `---\nname: performance-evaluator\ndescription: Evaluate SKS performance, token-saving, accuracy-proxy, context-compression, or workflow improvements.\n---\n\nUse sks eval run/compare before claims. Report token_savings_pct, accuracy_delta/proxy, required_recall, support, and meaningful_improvement.\n`,
|
|
578
581
|
'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\`; Codex uses built-in image generation with gpt-image-2 and counts it against Codex usage limits. For larger batches only, use the API path when OPENAI_API_KEY is explicitly available and the user or route contract allows API-priced generation. Do not substitute placeholder SVG/HTML/CSS for requested raster assets; follow design.md when relevant.\n`,
|
|
579
|
-
'getdesign-reference': `---\nname: getdesign-reference\ndescription: Use getdesign.md official design reference
|
|
580
|
-
'design-system-builder': `---\nname: design-system-builder\ndescription: Create design.md from docs/Design-Sys-Prompt.md when UI/UX work has no design system.\n---\n\nWhen \`design.md\` is missing, read docs/Design-Sys-Prompt.md, inspect product/UI context,
|
|
582
|
+
'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`,
|
|
583
|
+
'design-system-builder': `---\nname: design-system-builder\ndescription: Create the single design.md SSOT from docs/Design-Sys-Prompt.md when UI/UX work has no design system.\n---\n\nWhen \`design.md\` is missing, read docs/Design-Sys-Prompt.md as the builder prompt, inspect product/UI context, and use getdesign-reference, official getdesign.md docs, and curated DESIGN.md examples from ${AWESOME_DESIGN_MD_REFERENCE.url} only as source inputs. Fuse those inputs into one design.md SSOT with tokens, components, states, imagery, accessibility, and verification rules; do not leave multiple design files or references as competing authorities. Use the plan tool only for real ambiguity plus default font recommendation. Use imagegen for assets.\n`,
|
|
581
584
|
'design-ui-editor': `---\nname: design-ui-editor\ndescription: Edit UI/UX using design.md, getdesign-reference, and design-artifact-expert.\n---\n\nRead \`design.md\`, inspect relevant UI/assets/tests, consult getdesign-reference when improving the design system, apply the smallest design-system-conformant change, use imagegen for image/logo/raster assets, and verify render quality. If missing, use design-system-builder first.\n`,
|
|
582
585
|
'design-artifact-expert': `---\nname: design-artifact-expert\ndescription: Create or revise high-fidelity HTML, UI, prototype, deck-like, or visual design artifacts with rendered verification.\n---\n\nUse for design/UI/prototype/HTML visual work, including presentation-like HTML/PDF artifacts. Read design.md when present, consult getdesign-reference for design-system grounding, build the usable artifact first, preserve state, verify overlap/readability/responsiveness, and use imagegen for required assets.\n`
|
|
583
586
|
};
|
package/src/core/perf-bench.mjs
CHANGED
|
@@ -105,6 +105,11 @@ export async function runWorkflowPerfBench(root, opts = {}) {
|
|
|
105
105
|
verification_count: verification.length,
|
|
106
106
|
negative_work_skipped_count: estimatedSavedWork,
|
|
107
107
|
simplicity_score: Number(proofField?.simplicity_scorecard?.score || 0),
|
|
108
|
+
contract_clarity_score: Number(proofField?.contract_clarity?.score || 0),
|
|
109
|
+
workflow_complexity_score: Number(proofField?.workflow_complexity?.score || 0),
|
|
110
|
+
workflow_complexity_band: proofField?.workflow_complexity?.band || null,
|
|
111
|
+
team_trigger_count: proofField?.team_trigger_matrix?.active_triggers?.length || 0,
|
|
112
|
+
verification_stage_cache_key: proofField?.verification_stage_cache?.cache_key || null,
|
|
108
113
|
outcome_criteria_passed: (proofField?.simplicity_scorecard?.criteria || []).filter((item) => item.passed).length,
|
|
109
114
|
proof_field_valid: proofValidation.ok,
|
|
110
115
|
pipeline_plan_valid: planValidation.ok
|
|
@@ -129,6 +134,10 @@ export function validateWorkflowPerfReport(report = {}) {
|
|
|
129
134
|
if (!report.metrics?.execution_lane) issues.push('execution_lane');
|
|
130
135
|
if (!report.metrics?.pipeline_lane) issues.push('pipeline_lane');
|
|
131
136
|
if (!Number.isFinite(Number(report.metrics?.simplicity_score))) issues.push('simplicity_score');
|
|
137
|
+
if (!Number.isFinite(Number(report.metrics?.contract_clarity_score))) issues.push('contract_clarity_score');
|
|
138
|
+
if (!Number.isFinite(Number(report.metrics?.workflow_complexity_score))) issues.push('workflow_complexity_score');
|
|
139
|
+
if (!report.metrics?.workflow_complexity_band) issues.push('workflow_complexity_band');
|
|
140
|
+
if (!report.metrics?.verification_stage_cache_key) issues.push('verification_stage_cache_key');
|
|
132
141
|
if (!report.proof_field || !validateProofFieldReport(report.proof_field).ok) issues.push('proof_field');
|
|
133
142
|
if (!report.pipeline_plan || !validatePipelinePlan(report.pipeline_plan).ok) issues.push('pipeline_plan');
|
|
134
143
|
if (!report.recommendation?.mode) issues.push('recommendation');
|
package/src/core/pipeline.mjs
CHANGED
|
@@ -65,6 +65,7 @@ export function buildPipelinePlan(input = {}) {
|
|
|
65
65
|
const verification = planVerification(route, proof);
|
|
66
66
|
const skipped = stages.filter((stage) => stage.status === 'skipped').map((stage) => stage.id);
|
|
67
67
|
const kept = stages.filter((stage) => stage.status !== 'skipped' && stage.status !== 'not_applicable').map((stage) => stage.id);
|
|
68
|
+
const routeEconomy = routeEconomyPlan(proof);
|
|
68
69
|
return {
|
|
69
70
|
schema_version: PIPELINE_PLAN_SCHEMA_VERSION,
|
|
70
71
|
generated_at: nowIso(),
|
|
@@ -94,6 +95,7 @@ export function buildPipelinePlan(input = {}) {
|
|
|
94
95
|
verification,
|
|
95
96
|
invariants: ['no_unrequested_fallback_code', 'listed_verification', 'triwiki_validate_before_final', 'honest_mode'],
|
|
96
97
|
proof_field: proof,
|
|
98
|
+
route_economy: routeEconomy,
|
|
97
99
|
skill_dream: input.skillDream || { attached: false, reason: 'skill dreaming uses cheap counters and only runs inventory at threshold' },
|
|
98
100
|
next_actions: planNextActions(route, task, ambiguity, lane),
|
|
99
101
|
no_unrequested_fallback_code: true
|
|
@@ -113,6 +115,7 @@ export function validatePipelinePlan(plan = {}) {
|
|
|
113
115
|
if (!plan.runtime_lane?.lane) issues.push('runtime_lane');
|
|
114
116
|
if (!Array.isArray(plan.stages) || !plan.stages.length) issues.push('stages');
|
|
115
117
|
if (!Array.isArray(plan.verification) || !plan.verification.length) issues.push('verification');
|
|
118
|
+
if (!plan.route_economy?.mode) issues.push('route_economy');
|
|
116
119
|
if (plan.no_unrequested_fallback_code !== true || !plan.invariants?.includes('no_unrequested_fallback_code')) issues.push('fallback_guard');
|
|
117
120
|
if (!plan.next_actions?.length) issues.push('next_actions');
|
|
118
121
|
return { ok: issues.length === 0, issues };
|
|
@@ -147,7 +150,37 @@ function normalizeProofField(report) {
|
|
|
147
150
|
keep: report.execution_lane?.keep || SPEED_LANE_POLICY.always_keep,
|
|
148
151
|
verification: report.execution_lane?.verification || report.fast_lane_decision?.verification || [],
|
|
149
152
|
proof_cones: (report.proof_cones || []).map((cone) => cone.id),
|
|
150
|
-
source_hash: report.source_hash || null
|
|
153
|
+
source_hash: report.source_hash || null,
|
|
154
|
+
contract_clarity: report.contract_clarity || null,
|
|
155
|
+
workflow_complexity: report.workflow_complexity || null,
|
|
156
|
+
team_trigger_matrix: report.team_trigger_matrix || null,
|
|
157
|
+
verification_stage_cache: report.verification_stage_cache || null
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function routeEconomyPlan(proof = {}) {
|
|
162
|
+
if (!proof.attached) {
|
|
163
|
+
return {
|
|
164
|
+
schema_version: 1,
|
|
165
|
+
mode: 'unavailable',
|
|
166
|
+
report_only: true,
|
|
167
|
+
reason: proof.reason || 'Proof Field not attached yet'
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const triggers = proof.team_trigger_matrix?.active_triggers || [];
|
|
171
|
+
return {
|
|
172
|
+
schema_version: 1,
|
|
173
|
+
mode: 'report_only',
|
|
174
|
+
report_only: true,
|
|
175
|
+
contract_clarity_score: Number(proof.contract_clarity?.score || 0),
|
|
176
|
+
contract_clarity_passed: proof.contract_clarity?.passed === true,
|
|
177
|
+
ask_recommended: proof.contract_clarity?.ask_recommended === true,
|
|
178
|
+
workflow_complexity_score: Number(proof.workflow_complexity?.score || 0),
|
|
179
|
+
workflow_complexity_band: proof.workflow_complexity?.band || null,
|
|
180
|
+
team_trigger_count: triggers.length,
|
|
181
|
+
active_team_triggers: triggers,
|
|
182
|
+
verification_stage_cache_key: proof.verification_stage_cache?.cache_key || null,
|
|
183
|
+
deletion_policy: 'do_not_delete_or_skip_pipeline_stages_until_report_only_metrics_are_calibrated'
|
|
151
184
|
};
|
|
152
185
|
}
|
|
153
186
|
|
|
@@ -920,11 +953,76 @@ function reflectionStopReason(state = {}, status = {}) {
|
|
|
920
953
|
return `SKS ${route} must run reflection before final. Write .sneakoscope/missions/${id}/${REFLECTION_ARTIFACT}, record real lessons in ${REFLECTION_MEMORY_PATH} when present, refresh/pack and validate TriWiki, then pass .sneakoscope/missions/${id}/${REFLECTION_GATE}.${missing}`;
|
|
921
954
|
}
|
|
922
955
|
|
|
956
|
+
export async function projectGateStatus(root, state = {}) {
|
|
957
|
+
const gates = [];
|
|
958
|
+
const id = state?.mission_id || null;
|
|
959
|
+
if (clarificationGatePending(state)) {
|
|
960
|
+
gates.push({
|
|
961
|
+
id: 'clarification-gate',
|
|
962
|
+
ok: false,
|
|
963
|
+
missing: ['explicit_user_answers', 'pipeline_answer'],
|
|
964
|
+
source: id ? `.sneakoscope/missions/${id}/questions.md` : null
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
if (state?.context7_required) {
|
|
968
|
+
const evidence = await context7Evidence(root, state);
|
|
969
|
+
gates.push({
|
|
970
|
+
id: 'context7-evidence',
|
|
971
|
+
ok: evidence.ok,
|
|
972
|
+
missing: evidence.ok ? [] : ['resolve-library-id', 'query-docs'],
|
|
973
|
+
source: id ? `.sneakoscope/missions/${id}/context7-evidence.jsonl` : '.sneakoscope/state/context7-evidence.jsonl'
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
if (state?.subagents_required) {
|
|
977
|
+
const evidence = await subagentEvidence(root, state);
|
|
978
|
+
gates.push({
|
|
979
|
+
id: 'subagent-evidence',
|
|
980
|
+
ok: evidence.ok,
|
|
981
|
+
missing: evidence.ok ? [] : ['spawn_agent_or_exception_evidence'],
|
|
982
|
+
source: id ? `.sneakoscope/missions/${id}/subagent-evidence.jsonl` : '.sneakoscope/state/subagent-evidence.jsonl'
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
if (id && state?.stop_gate && !['none', 'honest_mode'].includes(state.stop_gate)) {
|
|
986
|
+
const active = await passedActiveGate(root, state);
|
|
987
|
+
gates.push({
|
|
988
|
+
id: active.file || state.stop_gate,
|
|
989
|
+
ok: active.ok,
|
|
990
|
+
missing: active.missing || (active.ok ? [] : ['passed']),
|
|
991
|
+
source: active.file ? `.sneakoscope/missions/${id}/${active.file}` : null
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
const reflection = await reflectionGateStatus(root, state);
|
|
995
|
+
if (reflectionRequiredForState(state)) {
|
|
996
|
+
gates.push({
|
|
997
|
+
id: REFLECTION_GATE,
|
|
998
|
+
ok: reflection.ok,
|
|
999
|
+
missing: reflection.missing || [],
|
|
1000
|
+
source: id ? `.sneakoscope/missions/${id}/${REFLECTION_GATE}` : null
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
const blockers = gates.filter((gate) => !gate.ok).flatMap((gate) => gate.missing.map((item) => `${gate.id}:${item}`));
|
|
1004
|
+
return {
|
|
1005
|
+
schema_version: 1,
|
|
1006
|
+
generated_at: nowIso(),
|
|
1007
|
+
mission_id: id,
|
|
1008
|
+
mode: state?.mode || null,
|
|
1009
|
+
report_only: true,
|
|
1010
|
+
ok: blockers.length === 0,
|
|
1011
|
+
blockers,
|
|
1012
|
+
gates
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
|
|
923
1016
|
export async function evaluateStop(root, state, payload, opts = {}) {
|
|
924
1017
|
const last = extractLastMessage(payload);
|
|
925
|
-
if (
|
|
1018
|
+
if (clarificationGatePending(state)) {
|
|
926
1019
|
if (await hasVisibleClarificationQuestionBlock(root, state, last)) return { continue: true };
|
|
927
|
-
return
|
|
1020
|
+
return {
|
|
1021
|
+
decision: 'block',
|
|
1022
|
+
reason: await clarificationStopReason(root, state, 'route'),
|
|
1023
|
+
gate: 'clarification',
|
|
1024
|
+
missing: ['explicit_user_answers', 'pipeline_answer']
|
|
1025
|
+
};
|
|
928
1026
|
}
|
|
929
1027
|
if (state?.context7_required && !(await hasContext7DocsEvidence(root, state))) {
|
|
930
1028
|
return complianceBlock(root, state, `SKS ${state.route_command || state.mode || 'route'} requires Context7 evidence before completion. Use Context7 resolve-library-id, then query-docs (or legacy get-library-docs), so SKS can record context7-evidence.jsonl.`, { gate: 'context7-evidence' });
|
|
@@ -955,6 +1053,16 @@ export async function evaluateStop(root, state, payload, opts = {}) {
|
|
|
955
1053
|
return null;
|
|
956
1054
|
}
|
|
957
1055
|
|
|
1056
|
+
function clarificationGatePending(state = {}) {
|
|
1057
|
+
return Boolean(state?.clarification_required && String(state.phase || '').includes('CLARIFICATION_AWAITING_ANSWERS'))
|
|
1058
|
+
|| Boolean(
|
|
1059
|
+
state?.mission_id
|
|
1060
|
+
&& state.implementation_allowed === false
|
|
1061
|
+
&& state.ambiguity_gate_required === true
|
|
1062
|
+
&& state.ambiguity_gate_passed !== true
|
|
1063
|
+
);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
958
1066
|
async function complianceBlock(root, state = {}, reason = '', detail = {}) {
|
|
959
1067
|
if (!state?.mission_id) return { decision: 'block', reason };
|
|
960
1068
|
const dir = missionDir(root, state.mission_id);
|
package/src/core/ppt.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import fsp from 'node:fs/promises';
|
|
3
3
|
import { nowIso, readJson, writeJsonAtomic, writeTextAtomic } from './fsx.mjs';
|
|
4
|
+
import { AWESOME_DESIGN_MD_REFERENCE, DESIGN_SYSTEM_SSOT, GETDESIGN_REFERENCE } from './routes.mjs';
|
|
4
5
|
|
|
5
6
|
export const PPT_AUDIENCE_STRATEGY_ARTIFACT = 'ppt-audience-strategy.json';
|
|
6
7
|
export const PPT_GATE_ARTIFACT = 'ppt-gate.json';
|
|
@@ -314,8 +315,27 @@ export function buildPptStyleTokens(contract = {}) {
|
|
|
314
315
|
design_policy: {
|
|
315
316
|
priority: 'information_first',
|
|
316
317
|
visual_style: 'simple_restrained_detailed',
|
|
318
|
+
design_ssot: {
|
|
319
|
+
authority: DESIGN_SYSTEM_SSOT.authority_file,
|
|
320
|
+
builder_prompt: DESIGN_SYSTEM_SSOT.builder_prompt,
|
|
321
|
+
route_local_artifact: PPT_STYLE_TOKENS_ARTIFACT,
|
|
322
|
+
rule: 'PPT style tokens are a route-local projection of the design SSOT; source inputs are fused here and are not independent authorities.'
|
|
323
|
+
},
|
|
324
|
+
source_inputs: [
|
|
325
|
+
{
|
|
326
|
+
id: GETDESIGN_REFERENCE.id,
|
|
327
|
+
url: GETDESIGN_REFERENCE.url,
|
|
328
|
+
role: 'source_input_for_ssot'
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
id: AWESOME_DESIGN_MD_REFERENCE.id,
|
|
332
|
+
url: AWESOME_DESIGN_MD_REFERENCE.url,
|
|
333
|
+
role: 'source_input_for_ssot'
|
|
334
|
+
}
|
|
335
|
+
],
|
|
317
336
|
avoid: ['over-designed decoration', 'ornamental gradients', 'nested cards', 'low-contrast gray body text', 'excessive motion or effects'],
|
|
318
337
|
detail_strategy: ['precise spacing', 'clear hierarchy', 'thin rules', 'disciplined alignment', 'subtle accent color only when it clarifies meaning'],
|
|
338
|
+
anti_generic_ai_style: 'select a concrete DESIGN.md visual system before adding decorative styling; do not default to generic cards, gradients, or vague SaaS visuals',
|
|
319
339
|
image_policy: 'use images only when they improve comprehension; prefer Codex App built-in image generation via https://developers.openai.com/codex/app/features#image-generation when generated assets are needed'
|
|
320
340
|
}
|
|
321
341
|
};
|
|
@@ -464,6 +484,8 @@ export function buildPptRenderReport({ contract = {}, audience, sourceLedger, st
|
|
|
464
484
|
design_policy_checks: [
|
|
465
485
|
{ id: 'information_first', passed: styleTokens.design_policy?.priority === 'information_first' },
|
|
466
486
|
{ id: 'restrained_detail', passed: styleTokens.design_policy?.visual_style === 'simple_restrained_detailed' },
|
|
487
|
+
{ id: 'design_ssot_declared', passed: styleTokens.design_policy?.design_ssot?.authority === DESIGN_SYSTEM_SSOT.authority_file },
|
|
488
|
+
{ id: 'curated_design_md_input_fused', passed: (styleTokens.design_policy?.source_inputs || []).some((entry) => entry.url === AWESOME_DESIGN_MD_REFERENCE.url && entry.role === 'source_input_for_ssot') },
|
|
467
489
|
{ id: 'no_decorative_overdesign', passed: !String(html).includes('gradient') }
|
|
468
490
|
],
|
|
469
491
|
broken_links: [],
|
package/src/core/proof-field.mjs
CHANGED
|
@@ -82,8 +82,12 @@ export async function buildProofField(root, opts = {}) {
|
|
|
82
82
|
const negativeWork = buildNegativeWorkCache(selectedCones, risk);
|
|
83
83
|
const fastLane = fastLaneDecision({ changedFiles, selectedCones, risk, negativeWork });
|
|
84
84
|
const sourceHash = await sourceDigest(root, changedFiles);
|
|
85
|
-
const
|
|
86
|
-
const
|
|
85
|
+
const contractClarity = contractClarityScore({ intent, changedFiles, selectedCones, risk });
|
|
86
|
+
const workflowComplexity = workflowComplexityScore({ changedFiles, selectedCones, risk, verification: fastLane.verification });
|
|
87
|
+
const teamTriggerMatrix = teamTriggerDecision({ intent, changedFiles, risk });
|
|
88
|
+
const verificationStageCache = verificationStageCachePlan({ sourceHash, changedFiles, verification: fastLane.verification });
|
|
89
|
+
const simplicity = outcomeScorecard({ intent, changedFiles, selectedCones, risk, negativeWork, fastLane, workflowComplexity });
|
|
90
|
+
const executionLane = executionLaneDecision({ fastLane, simplicity, workflowComplexity, teamTriggerMatrix });
|
|
87
91
|
return {
|
|
88
92
|
schema_version: PROOF_FIELD_SCHEMA_VERSION,
|
|
89
93
|
generated_at: nowIso(),
|
|
@@ -94,6 +98,10 @@ export async function buildProofField(root, opts = {}) {
|
|
|
94
98
|
invariant_ledger: INVARIANT_LEDGER,
|
|
95
99
|
outcome_rubric: OUTCOME_RUBRIC,
|
|
96
100
|
speed_lane_policy: SPEED_LANE_POLICY,
|
|
101
|
+
contract_clarity: contractClarity,
|
|
102
|
+
workflow_complexity: workflowComplexity,
|
|
103
|
+
team_trigger_matrix: teamTriggerMatrix,
|
|
104
|
+
verification_stage_cache: verificationStageCache,
|
|
97
105
|
simplicity_scorecard: simplicity,
|
|
98
106
|
execution_lane: executionLane,
|
|
99
107
|
proof_cones: selectedCones,
|
|
@@ -120,6 +128,11 @@ export function validateProofFieldReport(report = {}) {
|
|
|
120
128
|
if (!Array.isArray(report.simplicity_scorecard?.criteria) || report.simplicity_scorecard.criteria.length !== OUTCOME_RUBRIC.length) issues.push('simplicity_criteria');
|
|
121
129
|
if (!report.simplicity_scorecard?.criteria?.every((item) => item.adversarial_lens)) issues.push('simplicity_adversarial_lenses');
|
|
122
130
|
if (!report.speed_lane_policy || Number(report.speed_lane_policy.min_score) !== FAST_LANE_MIN_SCORE) issues.push('speed_lane_policy');
|
|
131
|
+
if (!Number.isFinite(Number(report.contract_clarity?.score))) issues.push('contract_clarity');
|
|
132
|
+
if (!Array.isArray(report.contract_clarity?.components) || report.contract_clarity.components.length < 1) issues.push('contract_clarity_components');
|
|
133
|
+
if (!Number.isFinite(Number(report.workflow_complexity?.score))) issues.push('workflow_complexity');
|
|
134
|
+
if (!Array.isArray(report.team_trigger_matrix?.triggers)) issues.push('team_trigger_matrix');
|
|
135
|
+
if (report.verification_stage_cache?.report_only !== true || !report.verification_stage_cache?.cache_key) issues.push('verification_stage_cache');
|
|
123
136
|
if (!report.execution_lane?.lane) issues.push('execution_lane');
|
|
124
137
|
if (report.execution_lane?.lane === SPEED_LANE_POLICY.fast_lane && report.execution_lane?.score < FAST_LANE_MIN_SCORE) issues.push('execution_lane_score');
|
|
125
138
|
if (!Array.isArray(report.proof_cones)) issues.push('proof_cones');
|
|
@@ -144,6 +157,7 @@ export async function proofFieldFixture() {
|
|
|
144
157
|
negative_release_work_recorded: report.negative_work_cache.some((item) => item.id === 'full_release_gate' && item.disposition === 'skip_with_evidence'),
|
|
145
158
|
outcome_rubric_present: report.outcome_rubric.length === OUTCOME_RUBRIC.length,
|
|
146
159
|
adversarial_lenses_present: report.outcome_rubric.every((item) => item.adversarial_lens) && report.simplicity_scorecard.criteria.every((item) => item.adversarial_lens),
|
|
160
|
+
route_economy_present: report.contract_clarity?.report_only === true && report.workflow_complexity?.report_only === true && report.team_trigger_matrix?.report_only === true && report.verification_stage_cache?.report_only === true,
|
|
147
161
|
simplicity_score_usable: Number(report.simplicity_scorecard?.score) >= FAST_LANE_MIN_SCORE,
|
|
148
162
|
execution_fast_lane_selected: report.execution_lane?.lane === SPEED_LANE_POLICY.fast_lane
|
|
149
163
|
}
|
|
@@ -237,11 +251,120 @@ function fastLaneDecision({ changedFiles, selectedCones, risk, negativeWork }) {
|
|
|
237
251
|
};
|
|
238
252
|
}
|
|
239
253
|
|
|
240
|
-
function
|
|
254
|
+
function contractClarityScore({ intent, changedFiles, selectedCones, risk }) {
|
|
255
|
+
const components = [
|
|
256
|
+
{
|
|
257
|
+
id: 'goal_fit',
|
|
258
|
+
floor: 0.7,
|
|
259
|
+
score: intent ? 1 : 0.25,
|
|
260
|
+
evidence: intent ? 'intent provided' : 'missing explicit intent'
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
id: 'safety_scope_clarity',
|
|
264
|
+
floor: 0.7,
|
|
265
|
+
score: risk.flags.unknown_surface ? 0.4 : 1,
|
|
266
|
+
evidence: risk.flags.unknown_surface ? 'unknown surface present' : `risk flags classified: ${Object.entries(risk.flags).filter(([, value]) => value).map(([key]) => key).join(', ') || 'none'}`
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
id: 'acceptance_observability',
|
|
270
|
+
floor: 0.6,
|
|
271
|
+
score: /accept|verify|test|done|complete|검증|완료|구현|개선/i.test(intent || '') ? 1 : 0.65,
|
|
272
|
+
evidence: /accept|verify|test|done|complete|검증|완료|구현|개선/i.test(intent || '') ? 'observable outcome language present' : 'acceptance inferred from proof cones'
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
id: 'write_scope_certainty',
|
|
276
|
+
floor: 0.7,
|
|
277
|
+
score: changedFiles.length > 0 && changedFiles.length <= 3 ? 1 : (changedFiles.length > 0 ? 0.55 : 0.2),
|
|
278
|
+
evidence: `${changedFiles.length} changed file(s) in proposed scope`
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
id: 'context_confidence',
|
|
282
|
+
floor: 0.7,
|
|
283
|
+
score: selectedCones.length > 0 && !risk.flags.unknown_surface ? 1 : 0.45,
|
|
284
|
+
evidence: `${selectedCones.length} proof cone(s), unknown_surface=${risk.flags.unknown_surface}`
|
|
285
|
+
}
|
|
286
|
+
];
|
|
287
|
+
const score = Number((components.reduce((sum, item) => sum + item.score, 0) / components.length).toFixed(2));
|
|
288
|
+
const failed = components.filter((item) => item.score < item.floor).map((item) => item.id);
|
|
289
|
+
return {
|
|
290
|
+
schema_version: 1,
|
|
291
|
+
report_only: true,
|
|
292
|
+
score,
|
|
293
|
+
passed: score >= 0.8 && failed.length === 0,
|
|
294
|
+
ask_recommended: failed.length > 0,
|
|
295
|
+
failed_floors: failed,
|
|
296
|
+
components
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function workflowComplexityScore({ changedFiles, selectedCones, risk, verification }) {
|
|
301
|
+
const surfaces = new Set(selectedCones.flatMap((cone) => cone.surfaces || []));
|
|
302
|
+
const weighted = {
|
|
303
|
+
changed_files: Math.min(changedFiles.length, 8) / 8 * 0.3,
|
|
304
|
+
proof_cones: Math.min(selectedCones.length, 4) / 4 * 0.2,
|
|
305
|
+
risk_flags: Math.min(risk.score, 4) / 4 * 0.25,
|
|
306
|
+
verification: Math.min((verification || []).length, 6) / 6 * 0.15,
|
|
307
|
+
surfaces: Math.min(surfaces.size, 6) / 6 * 0.1
|
|
308
|
+
};
|
|
309
|
+
const score = Number(Object.values(weighted).reduce((sum, value) => sum + value, 0).toFixed(2));
|
|
310
|
+
const band = score >= 0.67 ? 'frontier' : (score >= 0.34 ? 'balanced' : 'focused');
|
|
311
|
+
return {
|
|
312
|
+
schema_version: 1,
|
|
313
|
+
report_only: true,
|
|
314
|
+
score,
|
|
315
|
+
band,
|
|
316
|
+
inputs: {
|
|
317
|
+
changed_file_count: changedFiles.length,
|
|
318
|
+
proof_cone_count: selectedCones.length,
|
|
319
|
+
route_surface_count: surfaces.size,
|
|
320
|
+
risk_flag_count: risk.score,
|
|
321
|
+
verification_count: (verification || []).length
|
|
322
|
+
},
|
|
323
|
+
weighted
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function teamTriggerDecision({ intent, changedFiles, risk }) {
|
|
328
|
+
const triggers = [
|
|
329
|
+
{ id: 'explicit_team', active: /\$?team\b/i.test(intent || ''), reason: 'user explicitly selected Team' },
|
|
330
|
+
{ id: 'broad_change_set', active: changedFiles.length > 3, reason: `${changedFiles.length} changed file(s)` },
|
|
331
|
+
{ id: 'database_surface', active: risk.flags.database, reason: 'database risk flag present' },
|
|
332
|
+
{ id: 'security_surface', active: risk.flags.security, reason: 'security risk flag present' },
|
|
333
|
+
{ id: 'visual_forensic_surface', active: risk.flags.visual_forensic, reason: 'visual forensic risk flag present' },
|
|
334
|
+
{ id: 'unknown_surface', active: risk.flags.unknown_surface, reason: 'unknown proof cone selected' },
|
|
335
|
+
{ id: 'unsupported_claim', active: false, reason: 'only activated by Honest/H-Proof evidence' },
|
|
336
|
+
{ id: 'verification_failed', active: false, reason: 'only activated after verification failure' }
|
|
337
|
+
];
|
|
338
|
+
const active = triggers.filter((trigger) => trigger.active).map((trigger) => trigger.id);
|
|
339
|
+
return {
|
|
340
|
+
schema_version: 1,
|
|
341
|
+
report_only: true,
|
|
342
|
+
full_team_recommended: active.length > 0,
|
|
343
|
+
active_triggers: active,
|
|
344
|
+
triggers
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function verificationStageCachePlan({ sourceHash, changedFiles, verification }) {
|
|
349
|
+
const stage1 = [...new Set(verification || [])].filter((command) => /packcheck|selftest|commands --json|wiki validate|eval run/i.test(command));
|
|
350
|
+
const cacheInput = { source_hash: sourceHash || null, changed_files: changedFiles, stage1 };
|
|
351
|
+
return {
|
|
352
|
+
schema_version: 1,
|
|
353
|
+
report_only: true,
|
|
354
|
+
status: sourceHash ? 'planned' : 'source_hash_missing',
|
|
355
|
+
cache_key: sha256(JSON.stringify(cacheInput)).slice(0, 16),
|
|
356
|
+
source_hash: sourceHash || null,
|
|
357
|
+
stage1_commands: stage1,
|
|
358
|
+
invalidates_on: ['source_hash_changed', 'command_changed', 'cwd_changed', 'env_changed'],
|
|
359
|
+
reuse_policy: 'fail_closed'
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function outcomeScorecard({ intent, changedFiles, selectedCones, risk, negativeWork, fastLane, workflowComplexity }) {
|
|
241
364
|
const skipped = negativeWork.filter((item) => item.disposition === 'skip_with_evidence').length;
|
|
242
365
|
const criteria = [
|
|
243
366
|
{ id: 'goal_fit', passed: Boolean(intent || changedFiles.length), evidence: intent ? 'intent provided' : 'changed files define scope' },
|
|
244
|
-
{ id: 'minimum_surface', passed: changedFiles.length <= 3 && !risk.flags.unknown_surface, evidence: `${changedFiles.length} changed file(s), ${selectedCones.length} proof cone(s)` },
|
|
367
|
+
{ id: 'minimum_surface', passed: changedFiles.length <= 3 && !risk.flags.unknown_surface, evidence: `${changedFiles.length} changed file(s), ${selectedCones.length} proof cone(s), complexity=${workflowComplexity?.band || 'unknown'}` },
|
|
245
368
|
{ id: 'bounded_verification', passed: fastLane.verification.length > 0 && fastLane.verification.length <= 4, evidence: `${fastLane.verification.length} focused verification command(s)` },
|
|
246
369
|
{ id: 'escalation_defined', passed: Array.isArray(fastLane.escalate_on) && fastLane.escalate_on.length > 0, evidence: `${fastLane.escalate_on.length} escalation trigger(s)` }
|
|
247
370
|
].map((criterion) => ({
|
|
@@ -258,7 +381,7 @@ function outcomeScorecard({ intent, changedFiles, selectedCones, risk, negativeW
|
|
|
258
381
|
};
|
|
259
382
|
}
|
|
260
383
|
|
|
261
|
-
function executionLaneDecision({ fastLane, simplicity }) {
|
|
384
|
+
function executionLaneDecision({ fastLane, simplicity, workflowComplexity, teamTriggerMatrix }) {
|
|
262
385
|
const score = Number(simplicity?.score || 0);
|
|
263
386
|
const fast = Boolean(fastLane?.eligible) && score >= FAST_LANE_MIN_SCORE;
|
|
264
387
|
const lane = fast
|
|
@@ -276,7 +399,7 @@ function executionLaneDecision({ fastLane, simplicity }) {
|
|
|
276
399
|
escalate_on: [...new Set([...(fastLane?.escalate_on || []), ...SPEED_LANE_POLICY.fail_closed_on])],
|
|
277
400
|
reason: fast
|
|
278
401
|
? `Proof Field score ${score} >= ${FAST_LANE_MIN_SCORE} with no fast-lane blockers`
|
|
279
|
-
: `Fast lane not allowed: mode=${fastLane?.mode || 'unknown'}, score=${score}, blockers=${(fastLane?.blockers || []).join(', ') || 'none'}`
|
|
402
|
+
: `Fast lane not allowed: mode=${fastLane?.mode || 'unknown'}, score=${score}, complexity=${workflowComplexity?.band || 'unknown'}, team_triggers=${(teamTriggerMatrix?.active_triggers || []).join(', ') || 'none'}, blockers=${(fastLane?.blockers || []).join(', ') || 'none'}`
|
|
280
403
|
};
|
|
281
404
|
}
|
|
282
405
|
|
package/src/core/routes.mjs
CHANGED
|
@@ -50,10 +50,23 @@ export const GETDESIGN_REFERENCE = {
|
|
|
50
50
|
purpose: 'Ground DESIGN.md, UI/UX design systems, and presentation-like HTML/PDF artifacts in current design references.'
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
export const
|
|
53
|
+
export const DESIGN_SYSTEM_SSOT = {
|
|
54
|
+
id: 'design-system-ssot',
|
|
55
|
+
authority_file: 'design.md',
|
|
56
|
+
builder_prompt: 'docs/Design-Sys-Prompt.md',
|
|
57
|
+
rule: 'design.md is the single design decision authority. When it is missing, synthesize it from the builder prompt plus approved source inputs; external references must be fused into design.md or route artifacts and must not become parallel design authorities.'
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const AWESOME_DESIGN_MD_REFERENCE = {
|
|
61
|
+
id: 'awesome-design-md',
|
|
62
|
+
url: 'https://github.com/VoltAgent/awesome-design-md',
|
|
63
|
+
purpose: 'Curated ready-to-use DESIGN.md examples extracted from public brand and product websites; use only as source input to the design SSOT, not as a parallel authority.'
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const RECOMMENDED_DESIGN_REFERENCES = [GETDESIGN_REFERENCE, AWESOME_DESIGN_MD_REFERENCE];
|
|
54
67
|
|
|
55
68
|
export function getdesignReferencePolicyText() {
|
|
56
|
-
return `
|
|
69
|
+
return `Design SSOT policy: ${DESIGN_SYSTEM_SSOT.authority_file} is the single design decision authority. If it is missing, create or update it through ${DESIGN_SYSTEM_SSOT.builder_prompt}; getdesign.md (${GETDESIGN_REFERENCE.url}), its official docs, and curated DESIGN.md examples at ${AWESOME_DESIGN_MD_REFERENCE.url} are source inputs to fuse into that SSOT or into route-local style tokens, not parallel authorities. Prefer the official Codex skill when available (${GETDESIGN_REFERENCE.codex_skill_install}); otherwise use the generated getdesign-reference skill plus official Web/API/CLI/SDK docs and curated DESIGN.md examples as inputs. Do not claim an official getdesign MCP server is configured unless a current official MCP surface is actually available.`;
|
|
57
70
|
}
|
|
58
71
|
|
|
59
72
|
export const RECOMMENDED_SKILLS = [
|