sneakoscope 0.7.57 → 0.7.58
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 +34 -54
- package/src/cli/maintenance-commands.mjs +23 -6
- package/src/core/fsx.mjs +1 -1
- package/src/core/hooks-runtime.mjs +4 -3
- package/src/core/init.mjs +6 -6
- package/src/core/pipeline.mjs +83 -83
- package/src/core/ppt.mjs +12 -59
- package/src/core/qa-loop.mjs +103 -6
- package/src/core/questions.mjs +60 -16
- package/src/core/routes.mjs +10 -2
- package/src/core/team-live.mjs +9 -0
- package/src/core/tmux-ui.mjs +15 -0
- package/src/core/triwiki-attention.mjs +1 -1
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.58",
|
|
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
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
} from '../core/image-ux-review.mjs';
|
|
53
53
|
import { contextCapsule } from '../core/triwiki-attention.mjs';
|
|
54
54
|
import { rgbaKey, rgbaToWikiCoord, validateWikiCoordinateIndex } from '../core/wiki-coordinate.mjs';
|
|
55
|
-
import { ALLOWED_REASONING_EFFORTS, AWESOME_DESIGN_MD_REFERENCE, CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_EVIDENCE_SOURCE, CODEX_COMPUTER_USE_ONLY_POLICY, CODEX_IMAGEGEN_REQUIRED_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, PPT_PIPELINE_SKILL_ALLOWLIST, RECOMMENDED_SKILLS, ROUTES, USAGE_TOPICS, context7ConfigToml, hasContext7ConfigText, hasFromChatImgSignal, looksLikeAnswerOnlyRequest, noUnrequestedFallbackCodePolicyText, reflectionRequiredForRoute, reasoningInstruction, routePrompt, routeReasoning, routeRequiresSubagents, speedLanePolicyText, stackCurrentDocsPolicy, triwikiContextTracking } from '../core/routes.mjs';
|
|
55
|
+
import { ALLOWED_REASONING_EFFORTS, AWESOME_DESIGN_MD_REFERENCE, CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_EVIDENCE_SOURCE, CODEX_COMPUTER_USE_ONLY_POLICY, CODEX_IMAGEGEN_REQUIRED_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, PPT_PIPELINE_SKILL_ALLOWLIST, RECOMMENDED_SKILLS, ROUTES, USAGE_TOPICS, context7ConfigToml, hasContext7ConfigText, hasFromChatImgSignal, looksLikeAnswerOnlyRequest, noUnrequestedFallbackCodePolicyText, reflectionRequiredForRoute, reasoningInstruction, routePrompt, routeReasoning, routeRequiresSubagents, speedLanePolicyText, stackCurrentDocsPolicy, stripVisibleDecisionAnswerBlocks, triwikiContextTracking } from '../core/routes.mjs';
|
|
56
56
|
import { PIPELINE_PLAN_ARTIFACT, buildPipelinePlan, context7Evidence, evaluateStop, projectGateStatus, recordContext7Evidence, recordSubagentEvidence, validatePipelinePlan, writePipelinePlan } from '../core/pipeline.mjs';
|
|
57
57
|
import { TEAM_DECOMPOSITION_ARTIFACT, TEAM_GRAPH_ARTIFACT, TEAM_INBOX_DIR, TEAM_RUNTIME_TASKS_ARTIFACT, validateTeamRuntimeArtifacts, writeTeamRuntimeArtifacts } from '../core/team-dag.mjs';
|
|
58
58
|
import { appendTeamEvent, initTeamLive, parseTeamSpecText, readTeamDashboard, readTeamLive, readTeamTranscriptTail, renderTeamAgentLane, renderTeamWatch } from '../core/team-live.mjs';
|
|
@@ -348,7 +348,7 @@ async function updateCheck(args = []) {
|
|
|
348
348
|
if (result.update_available) console.log('Run: npm i -g sneakoscope');
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
-
const DOLLAR_DEFAULT_PIPELINE_TEXT = 'Default pipeline:
|
|
351
|
+
const DOLLAR_DEFAULT_PIPELINE_TEXT = 'Default pipeline: direct answers -> $Answer, tiny Direct Fix edits -> $DFix, presentation/PDF artifacts -> $PPT, image-generation UI/UX reviews -> $Image-UX-Review/$UX-Review, Computer Use UI/browser speed work -> $Computer-Use, code -> $Team. Execution routes infer their contract from prompt, TriWiki/current-code defaults, and conservative policy instead of surfacing prequestion sheets. Use $From-Chat-IMG only for chat screenshot plus original attachments. Use $MAD-SKS only as an explicit scoped DB authorization modifier that can be combined with another $ route. No route may invent unrequested fallback implementation code.';
|
|
352
352
|
|
|
353
353
|
function commands(args = []) {
|
|
354
354
|
if (flag(args, '--json')) return console.log(JSON.stringify({ aliases: ['sks', 'sneakoscope'], dollar_commands: DOLLAR_COMMANDS, app_skill_aliases: DOLLAR_COMMAND_ALIASES, commands: COMMAND_CATALOG }, null, 2));
|
|
@@ -1450,9 +1450,9 @@ function usage(args = []) {
|
|
|
1450
1450
|
deps: ['Dependencies', '', ' sks deps check [--json]', ' sks deps install [tmux|codex|context7|all] [--yes]', '', 'tmux on macOS uses Homebrew after Y/n approval for missing installs or Homebrew-managed upgrades. If PATH resolves an npm-managed tmux, SKS prompts for npm i -g tmux@latest instead. Unknown non-Homebrew tmux paths are reported as conflicts.'],
|
|
1451
1451
|
tmux: ['tmux', '', ' sks', ' sks tmux open', ' sks tmux check', ' sks tmux status --once', ' sks deps install tmux', '', 'Running bare `sks` opens or reuses the default tmux Codex CLI session in fast-high mode: --model gpt-5.5 -c model_reasoning_effort="high". SKS always forces gpt-5.5; SKS_CODEX_MODEL and SKS_CODEX_FAST_HIGH=0 cannot downgrade or remove that model pin. Use SKS_CODEX_REASONING only for reasoning effort. Before launch, SKS checks npm @openai/codex@latest and prompts Y/n when the installed Codex CLI is missing or outdated. Use `sks tmux open` when you need explicit session/workspace flags, and `sks help` for CLI help.'],
|
|
1452
1452
|
openclaw: ['OpenClaw', '', ' sks openclaw install', ' sks openclaw path', ' sks openclaw print SKILL.md', '', 'Installs an OpenClaw skill package under ~/.openclaw/skills/sneakoscope-codex so OpenClaw agents can attach skills: [sneakoscope-codex] with the shell tool and call local SKS commands from a project root.'],
|
|
1453
|
-
team: ['Team', '', ' sks team "task" executor:5 reviewer:6 user:1', ' sks team watch latest', ' sks team lane latest --agent analysis_scout_1 --follow', ' sks team message latest --from analysis_scout_1 --to executor_1 --message "handoff note"', ' sks team cleanup-tmux latest', '', '$Team
|
|
1453
|
+
team: ['Team', '', ' sks team "task" executor:5 reviewer:6 user:1', ' sks team watch latest', ' sks team lane latest --agent analysis_scout_1 --follow', ' sks team message latest --from analysis_scout_1 --to executor_1 --message "handoff note"', ' sks team cleanup-tmux latest', '', '$Team auto-seals a route contract, opens scout-first tmux lanes when available, then runs scouts -> TriWiki attention -> debate -> runtime graph/inbox -> fresh executors -> review -> cleanup -> reflection -> Honest.'],
|
|
1454
1454
|
'qa-loop': ['QA-LOOP', '', ' sks qa-loop prepare "QA this app"', ' sks qa-loop answer <MISSION_ID> answers.json', ' sks qa-loop run <MISSION_ID> --max-cycles 8', '', 'Report: YYYY-MM-DD-v<version>-qa-report.md'],
|
|
1455
|
-
ppt: ['PPT', '', ' $PPT 투자자용 피치덱을 HTML 기반 PDF로 만들어줘', ' $PPT 우리 SaaS 소개자료 만들어줘', ' sks ppt build latest --json', ' sks ppt status latest --json', '', '$PPT
|
|
1455
|
+
ppt: ['PPT', '', ' $PPT 투자자용 피치덱을 HTML 기반 PDF로 만들어줘', ' $PPT 우리 SaaS 소개자료 만들어줘', ' sks ppt build latest --json', ' sks ppt status latest --json', '', '$PPT infers delivery context, audience profile, STP strategy, decision context, and 3+ pain-point/solution/aha mappings before source research, design-system work, HTML/PDF export, render QA, fact-ledger validation, and bounded review-loop validation. Independent strategy/render/file-write phases run in parallel where inputs allow and are recorded in ppt-parallel-report.json. The visual system must stay simple, restrained, and information-first; editable source HTML is kept under source-html/, PPT-only temporary build files are cleaned, and installed skills/MCPs outside the $PPT allowlist are ignored. Design uses getdesign-reference plus the built-in PPT design pipeline; Codex App $imagegen/gpt-image-2 and Context7 are conditional only when the sealed PPT contract needs raster assets, slide visual critique, or current external docs. Missing required $imagegen/gpt-image-2 output blocks instead of being simulated.'],
|
|
1456
1456
|
'image-ux-review': ['Image UX Review', '', ' $Image-UX-Review localhost 화면을 이미지 생성 리뷰 루프로 검수해줘', ' $UX-Review 이 스크린샷을 gpt-image-2 콜아웃 리뷰로 분석하고 고쳐줘', ' sks image-ux-review status latest --json', '', '$Image-UX-Review captures or receives source UI screenshots, runs Codex App $imagegen/gpt-image-2 to create generated annotated review images with numbered callouts, then extracts those generated images into image-ux-issue-ledger.json. Text-only screenshot critique cannot pass image-ux-review-gate.json; missing generated review images remain an explicit blocker.'],
|
|
1457
1457
|
goal: ['Goal', '', ' sks goal create "task"', ' sks goal status latest', ' sks goal pause latest', ' sks goal resume latest', ' sks goal clear latest'],
|
|
1458
1458
|
'codex-app': ['Codex App', '', ' sks bootstrap', ' sks codex-app check', ' sks codex-app remote-control --status', ' sks dollar-commands', ' cat .codex/SNEAKOSCOPE.md'],
|
|
@@ -1982,11 +1982,10 @@ async function selftest() {
|
|
|
1982
1982
|
};
|
|
1983
1983
|
for (let i = 0; i < 5; i++) {
|
|
1984
1984
|
const stop = await evaluateStop(tmp, clarificationState, { last_assistant_message: 'continuing implementation without visible questions' });
|
|
1985
|
-
if (stop?.
|
|
1985
|
+
if (stop?.gate === 'clarification' || /ambiguity|clarification|question/i.test(String(stop?.reason || ''))) throw new Error('selftest failed: stale clarification gate still hard-paused without visible questions');
|
|
1986
1986
|
}
|
|
1987
|
-
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');
|
|
1988
1987
|
const visibleQuestionStop = await evaluateStop(tmp, clarificationState, { last_assistant_message: 'Required questions still pending:\n1. GOAL_PRECISE: What should be changed?\n\nReply by slot id; I will seal the contract with sks pipeline answer latest --stdin.' });
|
|
1989
|
-
if (visibleQuestionStop?.
|
|
1988
|
+
if (visibleQuestionStop?.gate === 'clarification' || /ambiguity|clarification/i.test(String(visibleQuestionStop?.reason || ''))) throw new Error('selftest failed: visible stale clarification wording still blocked stop');
|
|
1990
1989
|
await setCurrent(tmp, loopState);
|
|
1991
1990
|
const dfixPromptHook = await runProcess(process.execPath, [path.join(packageRoot(), 'bin', 'sks.mjs'), 'hook', 'user-prompt-submit'], {
|
|
1992
1991
|
cwd: tmp,
|
|
@@ -2405,7 +2404,7 @@ async function selftest() {
|
|
|
2405
2404
|
if (!(await exists(path.join(tmp, '.agents', 'skills', supportSkill, 'SKILL.md')))) throw new Error(`selftest failed: ${supportSkill} skill not installed`);
|
|
2406
2405
|
}
|
|
2407
2406
|
const imagegenSkillText = await safeReadText(path.join(tmp, '.agents', 'skills', 'imagegen', 'SKILL.md'));
|
|
2408
|
-
if (!imagegenSkillText.includes(CODEX_APP_IMAGE_GENERATION_DOC_URL) || !imagegenSkillText.includes('$imagegen') || !imagegenSkillText.includes('gpt-image-2') || !imagegenSkillText.includes('
|
|
2407
|
+
if (!imagegenSkillText.includes(CODEX_APP_IMAGE_GENERATION_DOC_URL) || !imagegenSkillText.includes('$imagegen') || !imagegenSkillText.includes('gpt-image-2') || !imagegenSkillText.includes('Direct API fallback does not satisfy SKS route evidence') || !imagegenSkillText.includes(CODEX_IMAGEGEN_REQUIRED_POLICY)) throw new Error('selftest failed: imagegen skill missing official Codex App image generation priority');
|
|
2409
2408
|
const imageUxReviewSkillText = await safeReadText(path.join(tmp, '.agents', 'skills', 'image-ux-review', 'SKILL.md'));
|
|
2410
2409
|
if (!imageUxReviewSkillText.includes('gpt-image-2') || !imageUxReviewSkillText.includes('$imagegen') || !imageUxReviewSkillText.includes('generated annotated review image') || !imageUxReviewSkillText.includes('Text-only screenshot critique cannot satisfy this route') || !imageUxReviewSkillText.includes(IMAGE_UX_REVIEW_GATE_ARTIFACT) || !imageUxReviewSkillText.includes(IMAGE_UX_REVIEW_ISSUE_LEDGER_ARTIFACT) || !imageUxReviewSkillText.includes(CODEX_IMAGEGEN_REQUIRED_POLICY)) throw new Error('selftest failed: image-ux-review skill missing gpt-image-2 generated-image review gate guidance');
|
|
2411
2410
|
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');
|
|
@@ -2430,6 +2429,7 @@ async function selftest() {
|
|
|
2430
2429
|
if (routePrompt('$agent-team run specialists')) throw new Error('selftest failed: deprecated $agent-team route still resolved');
|
|
2431
2430
|
if (routePrompt('$QA-LOOP run UI E2E')?.id !== 'QALoop' || routePrompt('$QALoop deployed smoke')) throw new Error('selftest failed: QA-LOOP route is not standardized to $QA-LOOP');
|
|
2432
2431
|
if (routePrompt('[$qa-loop](/tmp/qa-loop/SKILL.md) localhost UI 검증, Codex Computer Use만 사용')?.id !== 'QALoop') throw new Error('selftest failed: markdown-linked $QA-LOOP was hijacked by heuristic routing');
|
|
2432
|
+
if (stripVisibleDecisionAnswerBlocks('qa-loop [GOAL_PRECISE: local QA QA_SCOPE: ui_e2e_only TARGET_BASE_URL: http://localhost:3000] 다시 실행').includes('GOAL_PRECISE')) throw new Error('selftest failed: visible decision answer block sanitizer did not remove slot payload');
|
|
2433
2433
|
if (routePrompt('[$research](/tmp/research/SKILL.md) Codex Computer Use 도구 노출 문제를 QA루프 관점에서 연구')?.id !== 'Research') throw new Error('selftest failed: markdown-linked $Research was not treated as explicit route');
|
|
2434
2434
|
if (routePrompt('$WikiRefresh 갱신')) throw new Error('selftest failed: deprecated $WikiRefresh route still resolved');
|
|
2435
2435
|
if (routePrompt('$MAD-SKS Supabase MCP main 작업')?.id !== 'MadSKS') throw new Error('selftest failed: $MAD-SKS route did not resolve');
|
|
@@ -2700,31 +2700,20 @@ async function selftest() {
|
|
|
2700
2700
|
const hookTeamPendingContext = hookTeamPendingJson.hookSpecificOutput?.additionalContext || '';
|
|
2701
2701
|
if (hookTeamPendingState.mission_id === hookTeamState.mission_id || hookTeamPendingContext.includes('Required questions still pending') || hookTeamPendingContext.includes('MANDATORY ambiguity-removal gate activated')) throw new Error('selftest failed: direct Team follow-up was blocked by stale clarification behavior');
|
|
2702
2702
|
if (hookTeamPendingState.phase !== 'TEAM_PARALLEL_ANALYSIS_SCOUTING' || !hookTeamPendingState.team_plan_ready) throw new Error('selftest failed: direct Team follow-up did not prepare a fresh Team mission');
|
|
2703
|
-
const
|
|
2704
|
-
await initProject(
|
|
2705
|
-
const
|
|
2706
|
-
if (
|
|
2707
|
-
const
|
|
2708
|
-
const
|
|
2709
|
-
const
|
|
2710
|
-
const
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
const visibleQuestionDecision = await evaluateStop(qaClarificationTmp, hookQaClarificationState, { last_assistant_message: visibleQuestionsBlock }, { noQuestion: false });
|
|
2716
|
-
if (!visibleQuestionDecision?.continue) throw new Error('selftest failed: visible Required questions block was not accepted by clarification stop gate');
|
|
2717
|
-
const hookTeamPreToolBlocked = await runProcess(process.execPath, [hookBin, 'hook', 'pre-tool'], { cwd: qaClarificationTmp, input: JSON.stringify({ cwd: qaClarificationTmp, command: 'npm run selftest' }), env: { SKS_DISABLE_UPDATE_CHECK: '1' }, timeoutMs: 15000, maxOutputBytes: 64 * 1024 });
|
|
2718
|
-
if (hookTeamPreToolBlocked.code !== 0) throw new Error(`selftest failed: pending clarification pre-tool hook exited ${hookTeamPreToolBlocked.code}: ${hookTeamPreToolBlocked.stderr}`);
|
|
2719
|
-
const hookTeamPreToolBlockedJson = JSON.parse(hookTeamPreToolBlocked.stdout);
|
|
2720
|
-
if (hookTeamPreToolBlockedJson.decision !== 'block' || !String(hookTeamPreToolBlockedJson.reason || '').includes('ambiguity gate is paused')) throw new Error('selftest failed: pending clarification allowed implementation tool use before answers');
|
|
2721
|
-
const hookTeamAnswerToolAllowed = await runProcess(process.execPath, [hookBin, 'hook', 'pre-tool'], { cwd: qaClarificationTmp, input: JSON.stringify({ cwd: qaClarificationTmp, command: 'node ./bin/sks.mjs pipeline answer latest --stdin' }), env: { SKS_DISABLE_UPDATE_CHECK: '1' }, timeoutMs: 15000, maxOutputBytes: 64 * 1024 });
|
|
2722
|
-
if (hookTeamAnswerToolAllowed.code !== 0) throw new Error(`selftest failed: pipeline-answer pre-tool hook exited ${hookTeamAnswerToolAllowed.code}: ${hookTeamAnswerToolAllowed.stderr}`);
|
|
2723
|
-
const hookTeamAnswerToolAllowedJson = JSON.parse(hookTeamAnswerToolAllowed.stdout);
|
|
2724
|
-
if (hookTeamAnswerToolAllowedJson.decision === 'block') throw new Error('selftest failed: pending clarification blocked the pipeline answer command');
|
|
2725
|
-
const nonGoalsSlot = hookTeamSchema.slots.find((s) => s.id === 'NON_GOALS');
|
|
2703
|
+
const pptClarificationTmp = tmpdir();
|
|
2704
|
+
await initProject(pptClarificationTmp, {});
|
|
2705
|
+
const hookPptClarificationResult = await runProcess(process.execPath, [hookBin, 'hook', 'user-prompt-submit'], { cwd: pptClarificationTmp, input: JSON.stringify({ cwd: pptClarificationTmp, prompt: '$PPT 투자 제안서 만들어줘' }), env: { SKS_DISABLE_UPDATE_CHECK: '1' }, timeoutMs: 15000, maxOutputBytes: 256 * 1024 });
|
|
2706
|
+
if (hookPptClarificationResult.code !== 0) throw new Error(`selftest failed: PPT clarification hook exited ${hookPptClarificationResult.code}: ${hookPptClarificationResult.stderr}`);
|
|
2707
|
+
const hookPptClarificationState = await readJson(stateFile(pptClarificationTmp), {});
|
|
2708
|
+
const hookPptClarificationJson = JSON.parse(hookPptClarificationResult.stdout);
|
|
2709
|
+
const hookPptContext = hookPptClarificationJson.hookSpecificOutput?.additionalContext || '';
|
|
2710
|
+
const hookPptSchema = await readJson(path.join(missionDir(pptClarificationTmp, hookPptClarificationState.mission_id), 'required-answers.schema.json'));
|
|
2711
|
+
if (hookPptClarificationState.phase !== 'PPT_AUDIENCE_STRATEGY_READY' || hookPptClarificationState.implementation_allowed !== true || hookPptSchema.slots.length !== 0) throw new Error('selftest failed: PPT hook did not auto-seal without visible questions');
|
|
2712
|
+
if (hookPptContext.includes('Required questions') || hookPptContext.includes('VISIBLE RESPONSE CONTRACT') || hookPptContext.includes('MANDATORY ambiguity-removal gate')) throw new Error('selftest failed: PPT hook still exposed prequestion wording');
|
|
2713
|
+
if (!(await exists(path.join(missionDir(pptClarificationTmp, hookPptClarificationState.mission_id), 'ppt-audience-strategy.json')))) throw new Error('selftest failed: PPT auto-seal did not materialize audience strategy');
|
|
2714
|
+
const nonGoalsSlot = hookPptSchema.slots.find((s) => s.id === 'NON_GOALS');
|
|
2726
2715
|
if (nonGoalsSlot && !nonGoalsSlot.allow_empty) throw new Error('selftest failed: NON_GOALS does not allow an empty array answer');
|
|
2727
|
-
if (!nonGoalsSlot && !Array.isArray(
|
|
2716
|
+
if (!nonGoalsSlot && !Array.isArray(hookPptSchema.inferred_answers?.NON_GOALS)) throw new Error('selftest failed: NON_GOALS was neither asked nor inferred');
|
|
2728
2717
|
const textParsedAnswers = parseAnswersText({ slots: [{ id: 'INTENT_TARGET', type: 'string', required: true }] }, 'INTENT_TARGET: compact contract sealing');
|
|
2729
2718
|
if (textParsedAnswers.INTENT_TARGET !== 'compact contract sealing') throw new Error('selftest failed: text answer parser did not parse slot-id answers');
|
|
2730
2719
|
const textParsedImplicitAnswer = parseAnswersText({ slots: [{ id: 'INTENT_TARGET', type: 'string', required: true }] }, 'compact contract sealing');
|
|
@@ -2773,26 +2762,18 @@ async function selftest() {
|
|
|
2773
2762
|
if (honestSummaryCaseJson.decision === 'block') throw new Error('selftest failed: summary block/pass wording was treated as unresolved gap');
|
|
2774
2763
|
const hookQaTmp = tmpdir();
|
|
2775
2764
|
await initProject(hookQaTmp, {});
|
|
2776
|
-
const hookQaPayload = JSON.stringify({ cwd: hookQaTmp, prompt: '$QA-LOOP run
|
|
2765
|
+
const hookQaPayload = JSON.stringify({ cwd: hookQaTmp, prompt: '$QA-LOOP run API E2E against local dev' });
|
|
2777
2766
|
const hookQaResult = await runProcess(process.execPath, [hookBin, 'hook', 'user-prompt-submit'], { cwd: hookQaTmp, input: hookQaPayload, env: { SKS_DISABLE_UPDATE_CHECK: '1' }, timeoutMs: 15000, maxOutputBytes: 256 * 1024 });
|
|
2778
2767
|
if (hookQaResult.code !== 0) throw new Error(`selftest failed: $QA-LOOP hook exited ${hookQaResult.code}: ${hookQaResult.stderr}`);
|
|
2779
2768
|
const hookQaJson = JSON.parse(hookQaResult.stdout);
|
|
2780
2769
|
const hookQaContext = hookQaJson.hookSpecificOutput?.additionalContext || '';
|
|
2781
|
-
if (!hookQaContext.includes('MANDATORY ambiguity-removal gate activated') ||
|
|
2770
|
+
if (!hookQaContext.includes('Route contract auto-sealed') || hookQaContext.includes('MANDATORY ambiguity-removal gate activated') || hookQaContext.includes('Required questions:') || hookQaContext.includes('QA_SCOPE:') || hookQaContext.includes('UI_COMPUTER_USE_ACK:')) throw new Error('selftest failed: $QA-LOOP hook did not auto-seal without visible answer slots');
|
|
2782
2771
|
if (!hookQaContext.includes('Codex Computer Use') || !hookQaContext.includes('Playwright') || !hookQaContext.includes('Chrome MCP')) throw new Error('selftest failed: $QA-LOOP hook did not state Computer Use-only UI policy');
|
|
2783
2772
|
if (hookQaContext.includes('Browser Use 또는 Computer Use') || hookQaContext.includes('Browser/Computer Use evidence')) throw new Error('selftest failed: $QA-LOOP hook still allows Browser Use as UI evidence');
|
|
2784
2773
|
const hookQaState = await readJson(stateFile(hookQaTmp), {});
|
|
2785
|
-
if (hookQaState.phase !== '
|
|
2774
|
+
if (hookQaState.phase !== 'QALOOP_CLARIFICATION_CONTRACT_SEALED' || hookQaState.implementation_allowed !== true || hookQaState.clarification_required !== false || !hookQaState.ambiguity_gate_passed) throw new Error('selftest failed: $QA-LOOP hook did not auto-seal the ambiguity gate');
|
|
2786
2775
|
const hookQaSchema = await readJson(path.join(missionDir(hookQaTmp, hookQaState.mission_id), 'required-answers.schema.json'));
|
|
2787
|
-
|
|
2788
|
-
for (const s of hookQaSchema.slots) hookQaAnswers[s.id] = s.options ? (s.type === 'array' ? [s.options[0]] : s.options[0]) : (s.type.includes('array') ? ['selftest'] : 'selftest');
|
|
2789
|
-
hookQaAnswers.QA_SCOPE = 'all_available';
|
|
2790
|
-
hookQaAnswers.TARGET_BASE_URL = 'none';
|
|
2791
|
-
hookQaAnswers.API_BASE_URL = 'same_as_target';
|
|
2792
|
-
const hookQaAnswersPath = path.join(hookQaTmp, 'qa-answers.json');
|
|
2793
|
-
await writeJsonAtomic(hookQaAnswersPath, hookQaAnswers);
|
|
2794
|
-
const qaAnswerResult = await runProcess(process.execPath, [hookBin, 'pipeline', 'answer', 'latest', hookQaAnswersPath], { cwd: hookQaTmp, env: { SKS_DISABLE_UPDATE_CHECK: '1' }, timeoutMs: 15000, maxOutputBytes: 64 * 1024 });
|
|
2795
|
-
if (qaAnswerResult.code !== 0) throw new Error(`selftest failed: QA pipeline answer exited ${qaAnswerResult.code}: ${qaAnswerResult.stderr}`);
|
|
2776
|
+
if (hookQaSchema.slots.length !== 0 || hookQaSchema.inferred_answers?.QA_SCOPE !== 'api_e2e_only') throw new Error('selftest failed: $QA-LOOP schema did not infer QA answers without visible slots');
|
|
2796
2777
|
const qaMissionDir = missionDir(hookQaTmp, hookQaState.mission_id);
|
|
2797
2778
|
const initialQaGate = await readJson(path.join(qaMissionDir, 'qa-gate.json'));
|
|
2798
2779
|
const qaReportFile = initialQaGate.qa_report_file;
|
|
@@ -3304,8 +3285,8 @@ async function selftest() {
|
|
|
3304
3285
|
if (!predictableAuthCliSchema.inferred_answers.RISK_BOUNDARY?.includes('no destructive commands or live data writes')) throw new Error('selftest failed: predictable auth-worded CLI work did not infer conservative risk boundary');
|
|
3305
3286
|
const vagueSchema = buildQuestionSchema('뭔가 개선해줘');
|
|
3306
3287
|
const vagueSlotIds = vagueSchema.slots.map((s) => s.id);
|
|
3307
|
-
if (
|
|
3308
|
-
if (
|
|
3288
|
+
if (vagueSlotIds.length !== 0) throw new Error(`selftest failed: vague work should auto-seal inferred defaults without visible questions, got ${vagueSlotIds.join(',')}`);
|
|
3289
|
+
if (!vagueSchema.inferred_answers?.GOAL_PRECISE || !vagueSchema.inferred_answers?.ACCEPTANCE_CRITERIA) throw new Error('selftest failed: vague work did not infer core contract defaults');
|
|
3309
3290
|
if (vagueSchema.ambiguity_assessment?.method !== 'weighted_clarity_interview' || !vagueSchema.ambiguity_assessment?.adversarial_lenses?.includes('challenge_framing')) throw new Error('selftest failed: ambiguity schema missing weighted clarity / planning lenses');
|
|
3310
3291
|
const pptRoute = routePrompt('$PPT 투자자용 피치덱 만들어줘');
|
|
3311
3292
|
if (pptRoute?.id !== 'PPT') throw new Error('selftest failed: $PPT did not route to presentation pipeline');
|
|
@@ -3314,14 +3295,14 @@ async function selftest() {
|
|
|
3314
3295
|
const pptSchema = buildQuestionSchema('$PPT 투자자용 피치덱 만들어줘');
|
|
3315
3296
|
const pptSlotIds = pptSchema.slots.map((s) => s.id);
|
|
3316
3297
|
for (const id of ['PRESENTATION_DELIVERY_CONTEXT', 'PRESENTATION_AUDIENCE_PROFILE', 'PRESENTATION_STP_STRATEGY', 'PRESENTATION_PAINPOINT_SOLUTION_MAP', 'PRESENTATION_DECISION_CONTEXT']) {
|
|
3317
|
-
if (
|
|
3298
|
+
if (pptSlotIds.includes(id) || pptSchema.inferred_answers?.[id] === undefined) throw new Error(`selftest failed: PPT schema did not infer ${id}`);
|
|
3318
3299
|
}
|
|
3319
3300
|
const pptSkillText = await safeReadText(path.join(tmp, '.agents', 'skills', 'ppt', 'SKILL.md'));
|
|
3320
|
-
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');
|
|
3301
|
+
if (!pptSkillText.includes('STP') || !pptSkillText.includes('target audience profile') || !pptSkillText.includes('decision context') || !pptSkillText.includes('3+ pain-point to solution mappings') || !pptSkillText.includes('Do not surface a prequestion sheet')) throw new Error('selftest failed: generated PPT skill missing inferred STP/audience/pain-point guidance');
|
|
3321
3302
|
if (!pptSkillText.includes('simple, restrained, and information-first') || !pptSkillText.includes('over-designed decoration') || !pptSkillText.includes(CODEX_APP_IMAGE_GENERATION_DOC_URL) || !pptSkillText.includes(CODEX_IMAGEGEN_REQUIRED_POLICY) || !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');
|
|
3322
3303
|
if (!pptSkillText.includes('PPT pipeline allowlist') || !pptSkillText.includes('ignore installed skills and MCPs') || !pptSkillText.includes('prevent AI-like generic presentation design') || !pptSkillText.includes('Do not use generic design skills such as design-artifact-expert')) throw new Error('selftest failed: generated PPT skill missing pipeline allowlist enforcement');
|
|
3323
3304
|
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');
|
|
3324
|
-
if (!pptSkillText.includes('ppt-fact-ledger.json') || !pptSkillText.includes('ppt-image-asset-ledger.json') || !pptSkillText.includes('
|
|
3305
|
+
if (!pptSkillText.includes('ppt-fact-ledger.json') || !pptSkillText.includes('ppt-image-asset-ledger.json') || !pptSkillText.includes('direct API fallback') || !pptSkillText.includes('ppt-review-ledger.json') || !pptSkillText.includes('ppt-iteration-report.json') || !pptSkillText.includes('never simulate missing gpt-image-2 output')) throw new Error('selftest failed: generated PPT skill missing fact/image/review loop anti-fake guidance');
|
|
3325
3306
|
if (routeRequiresSubagents(pptRoute, '$PPT 투자자용 피치덱 만들어줘')) throw new Error('selftest failed: PPT route should not require subagents by default');
|
|
3326
3307
|
if (!reflectionRequiredForRoute(pptRoute)) throw new Error('selftest failed: PPT route should require reflection');
|
|
3327
3308
|
const pptMission = await createMission(tmp, { mode: 'ppt', prompt: '$PPT 투자자용 피치덱 만들어줘' });
|
|
@@ -3408,11 +3389,11 @@ async function selftest() {
|
|
|
3408
3389
|
unsupported_critical_claims_count: 0,
|
|
3409
3390
|
passed: true
|
|
3410
3391
|
});
|
|
3411
|
-
const requiredImageBuildResult = await runProcess(process.execPath, [hookBin, 'ppt', 'build', requiredImagePptMission.id, '--json'], { cwd: tmp, env: { SKS_DISABLE_UPDATE_CHECK: '1',
|
|
3392
|
+
const requiredImageBuildResult = await runProcess(process.execPath, [hookBin, 'ppt', 'build', requiredImagePptMission.id, '--json'], { cwd: tmp, env: { SKS_DISABLE_UPDATE_CHECK: '1', SKS_FAKE_IMAGE_GATE_TOKEN: 'ignored-by-sks-route-gate' }, timeoutMs: 15000, maxOutputBytes: 128 * 1024 });
|
|
3412
3393
|
if (requiredImageBuildResult.code !== 0) throw new Error(`selftest failed: required-image PPT build command failed: ${requiredImageBuildResult.stderr || requiredImageBuildResult.stdout}`);
|
|
3413
3394
|
const requiredImageBuild = JSON.parse(requiredImageBuildResult.stdout);
|
|
3414
3395
|
const requiredImageLedger = await readJson(path.join(requiredImagePptMission.dir, PPT_IMAGE_ASSET_LEDGER_ARTIFACT));
|
|
3415
|
-
if (requiredImageBuild.ok || requiredImageBuild.gate?.passed || !requiredImageBuild.gate?.image_asset_ledger_created || requiredImageBuild.gate?.image_asset_policy_satisfied !== false || !requiredImageLedger.required || requiredImageLedger.passed || !requiredImageLedger.blockers?.includes('
|
|
3396
|
+
if (requiredImageBuild.ok || requiredImageBuild.gate?.passed || !requiredImageBuild.gate?.image_asset_ledger_created || requiredImageBuild.gate?.image_asset_policy_satisfied !== false || !requiredImageLedger.required || requiredImageLedger.passed || !requiredImageLedger.blockers?.includes('missing_codex_app_imagegen_gpt_image_2_asset_evidence') || requiredImageLedger.generated_count !== 0) throw new Error('selftest failed: required PPT image assets were not blocked without Codex App imagegen evidence');
|
|
3416
3397
|
const installUxSchema = buildQuestionSchema('SKS first install/bootstrap UX and Context7 MCP setup improvement');
|
|
3417
3398
|
const installUxSlotIds = installUxSchema.slots.map((s) => s.id);
|
|
3418
3399
|
if (installUxSchema.domain_hints.includes('uiux') || installUxSlotIds.includes('VISUAL_REGRESSION_REQUIRED')) throw new Error('selftest failed: CLI UX install prompt should not ask visual UI questions');
|
|
@@ -3424,9 +3405,8 @@ async function selftest() {
|
|
|
3424
3405
|
const { id, dir, mission } = await createMission(tmp, { mode: 'goal', prompt: '발표자료 만들어줘' });
|
|
3425
3406
|
const schema = buildQuestionSchema(mission.prompt);
|
|
3426
3407
|
await writeQuestions(dir, schema);
|
|
3427
|
-
if (validateAnswers(schema, {}).ok) throw new Error('selftest failed: empty
|
|
3428
|
-
const answers = {};
|
|
3429
|
-
for (const s of schema.slots) answers[s.id] = s.options ? (s.type === 'array' ? [s.options[0]] : s.options[0]) : (s.type.includes('array') ? ['selftest'] : (s.id === 'DB_MAX_BLAST_RADIUS' ? 'no_live_dml' : 'selftest'));
|
|
3408
|
+
if (!validateAnswers(schema, {}).ok || schema.slots.length !== 0) throw new Error('selftest failed: inferred empty answer set should be valid after prequestion removal');
|
|
3409
|
+
const answers = { ...(schema.inferred_answers || {}) };
|
|
3430
3410
|
await writeJsonAtomic(path.join(dir, 'answers.json'), answers);
|
|
3431
3411
|
const sealed = await sealContract(dir, mission);
|
|
3432
3412
|
if (!sealed.ok) throw new Error('selftest failed: answers rejected');
|
|
@@ -15,7 +15,7 @@ import { renderCartridge, validateCartridge, driftCartridge, snapshotCartridge }
|
|
|
15
15
|
import { DEFAULT_EVAL_THRESHOLDS, compareEvaluationReports, runEvaluationBenchmark } from '../core/evaluation.mjs';
|
|
16
16
|
import { contextCapsule } from '../core/triwiki-attention.mjs';
|
|
17
17
|
import { rgbaKey, rgbaToWikiCoord, validateWikiCoordinateIndex } from '../core/wiki-coordinate.mjs';
|
|
18
|
-
import { ALLOWED_REASONING_EFFORTS, CODEX_COMPUTER_USE_ONLY_POLICY, 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, RECOMMENDED_SKILLS, ROUTES, hasFromChatImgSignal, routePrompt, routeReasoning, stackCurrentDocsPolicy, triwikiContextTracking } from '../core/routes.mjs';
|
|
18
|
+
import { ALLOWED_REASONING_EFFORTS, CODEX_COMPUTER_USE_ONLY_POLICY, 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, RECOMMENDED_SKILLS, ROUTES, hasFromChatImgSignal, routePrompt, routeReasoning, stackCurrentDocsPolicy, stripVisibleDecisionAnswerBlocks, triwikiContextTracking } from '../core/routes.mjs';
|
|
19
19
|
import { TEAM_DECOMPOSITION_ARTIFACT, TEAM_GRAPH_ARTIFACT, TEAM_INBOX_DIR, TEAM_RUNTIME_TASKS_ARTIFACT, teamRuntimePlanMetadata, teamRuntimeRequiredArtifacts, writeTeamRuntimeArtifacts } from '../core/team-dag.mjs';
|
|
20
20
|
import { appendTeamEvent, formatAgentReasoning, formatRoleCounts, initTeamLive, normalizeTeamSpec, parseTeamSpecArgs, readTeamControl, readTeamDashboard, readTeamLive, readTeamTranscriptTail, renderTeamAgentLane, renderTeamCleanupSummary, renderTeamWatch, requestTeamSessionCleanup, teamCleanupRequested, teamReasoningPolicy } from '../core/team-live.mjs';
|
|
21
21
|
import { evaluateTeamReviewPolicyGate, MIN_TEAM_REVIEWER_LANES, MIN_TEAM_REVIEW_POLICY_TEXT, teamReviewPolicy } from '../core/team-review-policy.mjs';
|
|
@@ -281,21 +281,38 @@ function qaRoute() {
|
|
|
281
281
|
async function qaLoopPrepare(args) {
|
|
282
282
|
const root = await sksRoot();
|
|
283
283
|
if (!(await exists(path.join(root, '.sneakoscope')))) await initProject(root, {});
|
|
284
|
-
const prompt = promptOf(args);
|
|
284
|
+
const prompt = stripVisibleDecisionAnswerBlocks(promptOf(args));
|
|
285
285
|
if (!prompt) throw new Error('Missing QA target prompt.');
|
|
286
286
|
const { id, dir } = await createMission(root, { mode: 'qaloop', prompt });
|
|
287
287
|
const schema = buildQaLoopQuestionSchema(prompt);
|
|
288
288
|
const route = qaRoute();
|
|
289
289
|
await writeQuestions(dir, schema);
|
|
290
290
|
await writeJsonAtomic(path.join(dir, 'route-context.json'), { route: 'QALoop', command: '$QA-LOOP', mode: 'QALOOP', task: prompt, required_skills: route?.requiredSkills || [], context7_required: false, original_stop_gate: 'qa-gate.json', clarification_gate: true });
|
|
291
|
+
if (schema.slots.length === 0) {
|
|
292
|
+
await writeJsonAtomic(path.join(dir, 'answers.json'), schema.inferred_answers || {});
|
|
293
|
+
const result = await sealContract(dir, { id, prompt, mode: 'qaloop' });
|
|
294
|
+
if (!result.ok) {
|
|
295
|
+
console.error('Inferred QA-LOOP answers failed validation.');
|
|
296
|
+
console.error(JSON.stringify(result.validation, null, 2));
|
|
297
|
+
process.exitCode = 2;
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
const artifactResult = await writeQaLoopArtifacts(dir, { id, prompt, mode: 'qaloop' }, result.contract);
|
|
301
|
+
await appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'qaloop.prepare.auto_sealed', slots: 0, hash: result.contract.sealed_hash, checklist_count: artifactResult.checklist_count });
|
|
302
|
+
await setCurrent(root, { mission_id: id, route: 'QALoop', route_command: '$QA-LOOP', mode: 'QALOOP', phase: 'QALOOP_CLARIFICATION_CONTRACT_SEALED', questions_allowed: false, implementation_allowed: true, clarification_required: false, clarification_passed: true, ambiguity_gate_required: true, ambiguity_gate_passed: true, stop_gate: 'qa-gate.json', qa_loop_artifacts_ready: true, qa_report_file: artifactResult.report_file, qa_checklist_count: artifactResult.checklist_count, reasoning_effort: 'high', reasoning_profile: 'sks-logic-high', reasoning_temporary: true });
|
|
303
|
+
console.log(`QA-LOOP mission created: ${id}`);
|
|
304
|
+
console.log('QA-LOOP contract auto-sealed from prompt, TriWiki/current-code defaults, and conservative safety policy.');
|
|
305
|
+
console.log(`Checklist: ${artifactResult.checklist_count} cases`);
|
|
306
|
+
console.log(`Report: ${path.relative(root, path.join(dir, artifactResult.report_file))}`);
|
|
307
|
+
console.log(`Run: sks qa-loop run ${id} --max-cycles ${schema.inferred_answers?.MAX_QA_CYCLES || 1}`);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
291
310
|
await appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'qaloop.prepare.questions_created', slots: schema.slots.length });
|
|
292
311
|
await setCurrent(root, { mission_id: id, route: 'QALoop', route_command: '$QA-LOOP', mode: 'QALOOP', phase: 'QALOOP_CLARIFICATION_AWAITING_ANSWERS', questions_allowed: true, implementation_allowed: false, clarification_required: true, ambiguity_gate_required: true, stop_gate: 'clarification-gate', reasoning_effort: 'high', reasoning_profile: 'sks-logic-high', reasoning_temporary: true });
|
|
293
312
|
console.log(`QA-LOOP mission created: ${id}`);
|
|
294
|
-
console.log('QA-LOOP
|
|
295
|
-
console.log(`Questions: ${path.relative(root, path.join(dir, 'questions.md'))}`);
|
|
313
|
+
console.log('QA-LOOP could not auto-seal because required safe defaults were unavailable.');
|
|
296
314
|
console.log(`Answer schema: ${path.relative(root, path.join(dir, 'required-answers.schema.json'))}`);
|
|
297
|
-
console.log('
|
|
298
|
-
console.log(formatQuestionsForCli(schema));
|
|
315
|
+
console.log('Inspect the schema and provide answers with: sks qa-loop answer <mission-id> answers.json');
|
|
299
316
|
}
|
|
300
317
|
|
|
301
318
|
async function qaLoopAnswer(args) {
|
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.58';
|
|
9
9
|
export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
|
|
10
10
|
export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
|
|
11
11
|
|
|
@@ -7,6 +7,7 @@ import { checkHarnessModification, harnessGuardBlockReason } from './harness-gua
|
|
|
7
7
|
import { activeRouteContext, evaluateStop, prepareRoute, promptPipelineContext as routePipelineContext, recordContext7Evidence, recordSubagentEvidence, routePrompt } from './pipeline.mjs';
|
|
8
8
|
import { classifyToolError } from './evaluation.mjs';
|
|
9
9
|
import { REQUIRED_CODEX_MODEL, isForbiddenCodexModel } from './codex-model-guard.mjs';
|
|
10
|
+
import { stripVisibleDecisionAnswerBlocks } from './routes.mjs';
|
|
10
11
|
|
|
11
12
|
const TEAM_DIGEST_MAX_EVENTS = 4;
|
|
12
13
|
const TEAM_DIGEST_MESSAGE_CHARS = 180;
|
|
@@ -143,7 +144,7 @@ function clientModelCandidates(value, depth = 0) {
|
|
|
143
144
|
|
|
144
145
|
async function hookUserPrompt(root, state, payload, noQuestion) {
|
|
145
146
|
if (!noQuestion) {
|
|
146
|
-
const prompt = extractUserPrompt(payload);
|
|
147
|
+
const prompt = stripVisibleDecisionAnswerBlocks(extractUserPrompt(payload));
|
|
147
148
|
const madSksConfirmation = await handleMadSksUserConfirmation(root, state, prompt);
|
|
148
149
|
if (madSksConfirmation?.handled) {
|
|
149
150
|
const teamDigest = await teamLiveDigest(root, state);
|
|
@@ -863,7 +864,7 @@ function visibleHookMessage(name, text = '') {
|
|
|
863
864
|
if (body.includes('SKS wiki pipeline active')) return 'SKS: wiki refresh context injected.';
|
|
864
865
|
if (body.includes('$Goal route prepared')) return 'SKS: Goal workflow bridge prepared for native Codex /goal continuation.';
|
|
865
866
|
if (body.includes('Computer Use fast lane active')) return 'SKS: Computer Use fast lane injected; defer TriWiki/Honest Mode to final closeout.';
|
|
866
|
-
if (body.includes('MANDATORY ambiguity-removal gate') || body.includes('VISIBLE RESPONSE CONTRACT') || body.includes('Required questions still pending')) return 'SKS: clarification
|
|
867
|
+
if (body.includes('MANDATORY ambiguity-removal gate') || body.includes('VISIBLE RESPONSE CONTRACT') || body.includes('Required questions still pending')) return 'SKS: stale clarification gate detected; continue from inferred route contract.';
|
|
867
868
|
if (body.includes('$Team route prepared') || body.includes('Team route')) return 'SKS: Team route, live transcript, and subagent plan injected.';
|
|
868
869
|
if (body.includes('$QA-LOOP route prepared') || body.includes('QA-LOOP')) return 'SKS: QA-LOOP route and safety checklist injected.';
|
|
869
870
|
if (body.includes('Subagent policy: REQUIRED')) return 'SKS: route context injected; subagent execution gate is active.';
|
|
@@ -871,7 +872,7 @@ function visibleHookMessage(name, text = '') {
|
|
|
871
872
|
}
|
|
872
873
|
if (name === 'post-tool') return 'SKS: tool result inspected; Context7/subagent/DB evidence updated when relevant.';
|
|
873
874
|
if (name === 'stop') {
|
|
874
|
-
if (body.includes('Required questions')) return 'SKS: clarification
|
|
875
|
+
if (body.includes('Required questions')) return 'SKS: stale clarification wording detected; route should auto-seal from inferred defaults.';
|
|
875
876
|
return body ? 'SKS: stop gate checked; continuing until route evidence passes.' : 'SKS: stop gate checked.';
|
|
876
877
|
}
|
|
877
878
|
if (name === 'permission-request') return body ? 'SKS: permission request evaluated by harness guards.' : 'SKS: permission request inspected.';
|
package/src/core/init.mjs
CHANGED
|
@@ -725,7 +725,7 @@ function codexAppQuickReference(scope, commandPrefix) {
|
|
|
725
725
|
'dollar-commands:',
|
|
726
726
|
...DOLLAR_COMMANDS.map((c) => `- \`${c.command}\`: ${c.route}`),
|
|
727
727
|
`Picker skills: ${DOLLAR_COMMAND_ALIASES.map((x) => x.app_skill).join(', ')}.`,
|
|
728
|
-
'Routing: Answer direct, DFix ultralight no-record, execution routes
|
|
728
|
+
'Routing: Answer direct, DFix ultralight no-record, execution routes infer scope/safety/behavior/acceptance answers from prompt, TriWiki/current-code defaults, and conservative policy before sealing contracts.',
|
|
729
729
|
getdesignReferencePolicyText(),
|
|
730
730
|
CODEX_IMAGEGEN_REQUIRED_POLICY,
|
|
731
731
|
`Full routes write reflection.md, record lessons to ${REFLECTION_MEMORY_PATH}, refresh/pack TriWiki, validate, then final-answer with a user-visible completion summary plus Honest Mode.`,
|
|
@@ -746,10 +746,10 @@ export async function installSkills(root) {
|
|
|
746
746
|
'answer': `---\nname: answer\ndescription: Answer-only research route for ordinary questions that should not start implementation.\n---\n\nUse for explanations, comparisons, status, facts, source-backed research, or docs guidance. Use repo/TriWiki first for project-local facts; hydrate low-trust claims from source. Browse or use Context7 for current external package/API/framework/MCP docs. End with a concise answer summary plus Honest Mode; do not create missions, subagents, or file edits.\n`,
|
|
747
747
|
'sks': `---\nname: sks\ndescription: General Sneakoscope Codex command route for $SKS or $sks usage, setup, status, and workflow help.\n---\n\nUse local SKS commands: bootstrap, deps, commands, quickstart, codex-app, context7, guard, conflicts, reasoning, wiki, pipeline status, pipeline plan, skill-dream. Promote code-changing work to Team unless Answer/DFix/Help/Wiki/safety route fits. Surface route/guard/scope, use TriWiki, do not edit installed harness files outside this engine repo, and require human-approved conflict cleanup. ${skillDreamPolicyText()}\n`,
|
|
748
748
|
'wiki': `---\nname: wiki\ndescription: Dollar-command route for $Wiki TriWiki refresh, pack, validate, and prune commands.\n---\n\nUse for $Wiki or Korean wiki-refresh requests. Refresh/update/갱신: run sks wiki refresh, then validate .sneakoscope/wiki/context-pack.json. Pack: run sks wiki pack, then validate. Prune/clean/정리: use sks wiki refresh --prune, or sks wiki prune --dry-run for inspection. Report claims, anchors, trust, attention.use_first/hydrate_first, validation, and blockers. Do not start ambiguity-gated implementation, subagents, or unrelated work.\n`,
|
|
749
|
-
'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.
|
|
749
|
+
'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. Auto-seal the route contract from prompt, TriWiki/current-code defaults, and conservative policy; do not surface a prequestion sheet. 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. ${MIN_TEAM_REVIEW_POLICY_TEXT} 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 in one tmux window using split panes when tmux is available. $Team/$team plus sks --mad uses the MAD-SKS permission gate module: live server work, normal DB writes, Supabase MCP writes, direct SQL, schema cleanup, and needed migrations are open for the active invocation; only catastrophic DB wipe/all-row/project-management guards remain. 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`,
|
|
750
750
|
'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`,
|
|
751
|
-
'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.
|
|
752
|
-
'ppt': `---\nname: ppt\ndescription: $PPT information-first HTML/PDF presentation pipeline with STP, audience, pain-point, format, research, design-system, and verification
|
|
751
|
+
'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. Infer scope, target, mutation policy, and login boundary from the prompt plus TriWiki/current-code defaults; do not surface a prequestion sheet. Credentials are runtime-only; never save secrets. UI-level E2E needs official 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`,
|
|
752
|
+
'ppt': `---\nname: ppt\ndescription: $PPT information-first HTML/PDF presentation pipeline with inferred STP, audience, pain-point, format, research, design-system, and verification contract.\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, auto-seal presentation-specific answers from prompt, TriWiki/current-code defaults, and conservative policy: 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. Do not surface a prequestion sheet. 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. ${pptPipelineAllowlistPolicyText()} 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 or slide visual critique are needed, use Codex App $imagegen/gpt-image-2 only when that asset/review need is explicitly sealed in the $PPT contract; direct API fallback, placeholder files, and prose-only substitutes do not satisfy the route gate. ${CODEX_IMAGEGEN_REQUIRED_POLICY} Use web or Context7 evidence only when external facts/libraries/current docs are required by the PPT contract, record verified claims in ppt-fact-ledger.json, record generated image asset plans/results/blockers in ppt-image-asset-ledger.json, 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, run the bounded ppt-review-policy/ppt-review-ledger/ppt-iteration-report loop, and verify readability, overlap, format fit, source coverage, export state, unsupported-claim status, image-asset completion, review-loop termination, and temporary build files cleanup. Finish with reflection and Honest Mode.\n`,
|
|
753
753
|
'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`,
|
|
754
754
|
'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`,
|
|
755
755
|
'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`,
|
|
@@ -760,7 +760,7 @@ export async function installSkills(root) {
|
|
|
760
760
|
'mad-sks': `---\nname: mad-sks\ndescription: Explicit high-risk authorization modifier for $MAD-SKS scoped Supabase MCP DB permission widening.\n---\n\nUse only when the user explicitly invokes $MAD-SKS or top-level sks --mad. It can be combined with another route, such as $MAD-SKS $Team or $DB ... $MAD-SKS; in that case the other command remains the primary workflow and MAD-SKS is only the temporary permission grant. The widened permission applies only while the active mission gate is open, must be deactivated when the task ends, and opens live server work, Supabase MCP database writes, column/schema cleanup, direct execute SQL, migration application when required, and normal targeted DB writes. Keep only catastrophic safeguards: whole database/schema/table removal, truncate, all-row delete/update, reset, dangerous project/branch management, credential exfiltration, persistent security weakening, and unrequested fallback implementation remain blocked. Do not carry MAD-SKS permission into later prompts or routes. The permission profile is centralized in src/core/permission-gates.mjs so skill/hook/MCP-style gates share one decision function.\n`,
|
|
761
761
|
'gx': `---\nname: gx\ndescription: Dollar-command route for $GX or $gx deterministic GX visual context cartridges.\n---\n\nUse when the user invokes $GX/$gx or asks for architecture/context visualization through SKS. Prefer sks gx init, render, validate, drift, and snapshot. vgraph.json remains the source of truth.\n`,
|
|
762
762
|
'help': `---\nname: help\ndescription: Dollar-command route for $Help or $help explaining installed SKS commands and workflows.\n---\n\nUse when the user invokes $Help/$help or asks what commands exist. Prefer concise output from sks commands, sks usage <topic>, sks quickstart, sks aliases, and sks codex-app.\n`,
|
|
763
|
-
'prompt-pipeline': `---\nname: prompt-pipeline\ndescription: Default SKS prompt optimization pipeline for execution prompts; Answer and DFix bypass it.\n---\n\nClassify intent: Answer only for real questions; question-shaped implicit instructions, complaints, and mandatory-policy statements route to Team. DFix handles Direct Fix work: tiny copy/config/docs/labels/spacing/translation/simple mechanical edits; code and broad implementation default to Team unless safety/research/GX route fits. Infer goal, target, constraints, acceptance, risk, and smallest safe route
|
|
763
|
+
'prompt-pipeline': `---\nname: prompt-pipeline\ndescription: Default SKS prompt optimization pipeline for execution prompts; Answer and DFix bypass it.\n---\n\nClassify intent: Answer only for real questions; question-shaped implicit instructions, complaints, and mandatory-policy statements route to Team. DFix handles Direct Fix work: tiny copy/config/docs/labels/spacing/translation/simple mechanical edits; code and broad implementation default to Team unless safety/research/GX route fits. Infer goal, target, constraints, acceptance, risk, and smallest safe route from prompt, TriWiki/current-code defaults, and conservative SKS policy. Do not surface a prequestion sheet. Materialize pipeline-plan.json for the runtime lane, kept/skipped stages, no-fallback invariant, and verification; inspect with sks pipeline plan, adding --proof-field when changed files are known. Code work surfaces route/guard/scopes, materializes team-roster.json from default or explicit counts before implementation, compiles concrete Team runtime graph/inbox artifacts after consensus, and parent owns integration/tests/Context7/Honest Mode. ${outcomeRubricPolicyText()} ${speedLanePolicyText()} ${skillDreamPolicyText()}\n\n${chatCaptureIntakeText()}\n\nDesign: non-PPT UI/UX reads design.md; if missing use design-system-builder; use imagegen for image/logo/raster, and imagegen must prefer Codex App built-in image generation (${CODEX_APP_IMAGE_GENERATION_DOC_URL}) before API generation. ${CODEX_IMAGEGEN_REQUIRED_POLICY} For UI/UX review/audit requests that mention image generation, gpt-image-2, callouts, or annotated review images, route to $Image-UX-Review/$UX-Review and require generated annotated review image evidence before issue extraction; do not satisfy that route with text-only critique. For $PPT, ${pptPipelineAllowlistPolicyText()} ${getdesignReferencePolicyText()} TriWiki context-tracking SSOT: .sneakoscope/wiki/context-pack.json; read only the latest coordinate+voxel overlay pack before every route stage, run sks wiki refresh/pack after changes, validate before handoffs/final.\n`,
|
|
764
764
|
'reasoning-router': `---\nname: reasoning-router\ndescription: Temporary SKS reasoning-effort routing for every command and pipeline route.\n---\n\nmedium: simple copy/color/discovery/setup/mechanical edits. high: logic, safety, architecture, DB, orchestration, refactor, multi-file work. xhigh: research, AutoResearch, falsification, benchmarks, SEO/GEO, open-ended discovery, and From-Chat-IMG image work-order analysis. Routing is temporary; return to default after the gate. Inspect with sks reasoning and sks pipeline status.\n`,
|
|
765
765
|
'pipeline-runner': `---\nname: pipeline-runner\ndescription: Execute SKS dollar-command routes as stateful pipelines with mission artifacts, route gates, Context7 evidence, temporary reasoning routing, reflection, and Honest Mode.\n---\n\nEvery $ command is a route. Use current.json, mission artifacts, and pipeline-plan.json as the execution plan: it records the lane, skipped stages, kept stages, verification, and no-unrequested-fallback invariant. Use temporary reasoning, TriWiki before stages, source hydration, Context7 when required, Team cleanup before reflection, reflection for full routes, and completion summary plus Honest Mode before final. Surface guard/scopes, record evidence, refresh/pack/validate TriWiki, and check sks pipeline status/resume/plan. ${speedLanePolicyText()} ${skillDreamPolicyText()}\n`,
|
|
766
766
|
'context7-docs': `---\nname: context7-docs\ndescription: Enforce Context7 MCP documentation evidence for SKS routes that depend on external libraries, frameworks, APIs, MCPs, package managers, DB SDKs, or generated docs.\n---\n\nWhen required, resolve-library-id, then query-docs for the resolved id. Legacy get-library-docs evidence is accepted. Prefer sks context7 tools/resolve/docs/evidence and finish only after both evidence stages exist. Check setup with sks context7 check.\n`,
|
|
@@ -781,7 +781,7 @@ export async function installSkills(root) {
|
|
|
781
781
|
'ux-review': imageUxReviewSkill('ux-review'),
|
|
782
782
|
'visual-review': imageUxReviewSkill('visual-review'),
|
|
783
783
|
'ui-ux-review': imageUxReviewSkill('ui-ux-review'),
|
|
784
|
-
'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.
|
|
784
|
+
'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. Use 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. Direct API fallback does not satisfy SKS route evidence unless a separate non-Codex API task is explicitly requested. ${CODEX_IMAGEGEN_REQUIRED_POLICY} Do not substitute placeholder SVG/HTML/CSS for requested raster assets; follow design.md when relevant.\n`,
|
|
785
785
|
'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`,
|
|
786
786
|
'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. ${CODEX_IMAGEGEN_REQUIRED_POLICY}\n`,
|
|
787
787
|
'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. ${CODEX_IMAGEGEN_REQUIRED_POLICY} If missing, use design-system-builder first.\n`,
|