sneakoscope 0.6.98 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![](https://github.com/mandarange/Sneakoscope-Codex/raw/dev/docs/assets/sneakoscope-codex-logo.png)
4
4
 
5
- Sneakoscope Codex (`sks`, displayed as `ㅅㅋㅅ`) is a Codex CLI/App harness for repeatable agent workflows. It adds terminal commands, Codex App `$` prompt commands, warp-native CLI workspaces, Team/QA/Research routes, a maximum-speed Computer Use lane, a fast Goal bridge for native `/goal` persistence, Context7 evidence checks, DB safety, TriWiki context tracking, Honest Mode, and release-readiness gates.
5
+ Sneakoscope Codex (`sks`, displayed as `ㅅㅋㅅ`) is a Codex CLI/App harness for repeatable agent workflows. It adds terminal commands, Codex App `$` prompt commands, warp-native CLI workspaces, Team/QA/Research routes, inspectable pipeline plans, a maximum-speed Computer Use lane, a fast Goal bridge for native `/goal` persistence, Context7 evidence checks, DB safety, TriWiki context tracking, lightweight skill dreaming, Honest Mode, and release-readiness gates.
6
6
 
7
7
  ## Quick Start
8
8
 
@@ -45,7 +45,9 @@ sks selftest --mock
45
45
  | --- | --- |
46
46
  | CLI runtime | `sks warp open` and `sks --mad` explicitly launch Codex CLI with Warp; bare `sks` only prints help/readiness surfaces. |
47
47
  | Codex App commands | Installs generated skills so `$Team`, `$From-Chat-IMG`, `$DFix`, `$QA-LOOP`, `$Goal`, `$DB`, `$Wiki`, `$Help`, and related routes are visible in prompt workflows. |
48
- | Team orchestration | Runs substantial work through ambiguity handling, scouts, TriWiki refresh, debate, runtime task graphs, worker inboxes, implementation, review, cleanup, reflection, and Honest Mode. |
48
+ | Pipeline plans | Writes `pipeline-plan.json` for stateful routes so the runtime lane, kept stages, skipped stages, verification commands, and no-unrequested-fallback invariant are visible with `sks pipeline plan`. |
49
+ | Team orchestration | Runs substantial work through ambiguity handling, scouts, TriWiki refresh, debate, runtime task graphs, worker inboxes, implementation, review, cleanup, reflection, and Honest Mode; narrow work should use Proof Field evidence to skip unrelated pipeline work instead of expanding Team. |
50
+ | Skill dreaming | Records cheap generated-skill usage counters in JSON and only periodically scans `.agents/skills` for keep, merge, prune, and improvement candidates. Reports are recommendation-only and never delete skills automatically. |
49
51
  | From-Chat-IMG | Turns chat screenshots plus original attachments into source-bound work orders, then requires scoped QA evidence before completion. |
50
52
  | QA loop | Dogfoods UI/API behavior with safety gates, Codex Computer Use-only UI evidence, safe fixes, and rechecks. |
51
53
  | Computer Use fast lane | Uses `$Computer-Use` / `$CU` for UI/browser/visual work that needs maximum speed: skip Team debate and upfront TriWiki loops, use Codex Computer Use directly, then refresh/validate TriWiki and run Honest Mode at final closeout. |
@@ -217,12 +219,21 @@ sks harness fixture --json
217
219
  sks gx init homepage
218
220
  sks gx render homepage --format html
219
221
  sks validate-artifacts latest --json
222
+ sks pipeline plan latest --proof-field --json
220
223
  sks perf run --json
221
224
  sks perf workflow --json --intent "small CLI change" --changed src/cli/main.mjs,src/core/routes.mjs
222
225
  sks proof-field scan --json --intent "small CLI change"
226
+ sks skill-dream status
227
+ sks skill-dream run --json
223
228
  sks code-structure scan --json
224
229
  ```
225
230
 
231
+ `sks pipeline plan` is the 0.7 runtime map. It reads or refreshes `.sneakoscope/missions/<id>/pipeline-plan.json`, then shows which lane is active, which stages are kept or skipped, which verification commands are required, and whether the no-unrequested-fallback invariant is present.
232
+
233
+ `sks proof-field scan` is SKS's lightweight outcome rubric: it maps the goal to proof cones, records unrelated work that can be skipped with evidence, reports a simplicity score, and names escalation triggers for when the route must return to the full Team/Honest proof path. When `execution_lane.lane` is `proof_field_fast_lane`, SKS can keep the parent-owned minimal patch plus listed verification and skip Team debate, fresh executor teams, broad route rework, and unrelated checks. Database, security, visual-forensic, unknown, broad, failed, or unsupported-claim signals fail closed to the normal Team/Honest path. Use `sks pipeline plan --proof-field` after changed files are known to bind that Proof Field decision to the mission plan.
234
+
235
+ `sks skill-dream` keeps generated skill complexity bounded without doing a heavy evaluation on every prompt. Route use writes compact counters to `.sneakoscope/skills/dream-state.json`; after the configured count/cooldown threshold, or when you run `sks skill-dream run`, SKS scans `.agents/skills` and writes `.sneakoscope/reports/skill-dream-latest.json` with keep, merge, prune, and improvement candidates. The report is intentionally advisory: deleting or merging skills requires explicit approval.
236
+
226
237
  `sks goal` and `$Goal` only prepare/control the native `/goal` persistence bridge. They do not replace Team, QA, DB, or other implementation routes; use the selected execution route for the actual work and verification. Context7 is only needed for Goal when external API/library documentation becomes relevant.
227
238
 
228
239
  Use `$Computer-Use` or `$CU` inside Codex App when the task specifically needs Codex Computer Use speed for UI/browser/visual work. This lane intentionally skips Team debate, QA-LOOP clarification, subagents, and upfront TriWiki refresh. It still requires Codex Computer Use as the evidence source, and it defers TriWiki refresh/validate plus Honest Mode to the final closeout.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "0.6.98",
4
+ "version": "0.7.0",
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
@@ -25,8 +25,8 @@ import { defaultEvaluationScenario, runEvaluationBenchmark } from '../core/evalu
25
25
  import { buildResearchPrompt, evaluateResearchGate, writeMockResearchResult, writeResearchPlan } from '../core/research.mjs';
26
26
  import { contextCapsule } from '../core/triwiki-attention.mjs';
27
27
  import { rgbaKey, rgbaToWikiCoord, validateWikiCoordinateIndex } from '../core/wiki-coordinate.mjs';
28
- import { ALLOWED_REASONING_EFFORTS, 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, RECOMMENDED_SKILLS, ROUTES, USAGE_TOPICS, context7ConfigToml, hasContext7ConfigText, hasFromChatImgSignal, looksLikeAnswerOnlyRequest, noUnrequestedFallbackCodePolicyText, reflectionRequiredForRoute, reasoningInstruction, routePrompt, routeReasoning, routeRequiresSubagents, stackCurrentDocsPolicy, triwikiContextTracking } from '../core/routes.mjs';
29
- import { context7Evidence, evaluateStop, recordContext7Evidence, recordSubagentEvidence } from '../core/pipeline.mjs';
28
+ import { ALLOWED_REASONING_EFFORTS, 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, RECOMMENDED_SKILLS, ROUTES, USAGE_TOPICS, context7ConfigToml, hasContext7ConfigText, hasFromChatImgSignal, looksLikeAnswerOnlyRequest, noUnrequestedFallbackCodePolicyText, reflectionRequiredForRoute, reasoningInstruction, routePrompt, routeReasoning, routeRequiresSubagents, speedLanePolicyText, stackCurrentDocsPolicy, triwikiContextTracking } from '../core/routes.mjs';
29
+ import { PIPELINE_PLAN_ARTIFACT, buildPipelinePlan, context7Evidence, evaluateStop, recordContext7Evidence, recordSubagentEvidence, validatePipelinePlan, writePipelinePlan } from '../core/pipeline.mjs';
30
30
  import { TEAM_DECOMPOSITION_ARTIFACT, TEAM_GRAPH_ARTIFACT, TEAM_INBOX_DIR, TEAM_RUNTIME_TASKS_ARTIFACT, validateTeamRuntimeArtifacts, writeTeamRuntimeArtifacts } from '../core/team-dag.mjs';
31
31
  import { appendTeamEvent, initTeamLive, parseTeamSpecText, readTeamDashboard, readTeamLive, readTeamTranscriptTail, renderTeamAgentLane } from '../core/team-live.mjs';
32
32
  import { ARTIFACT_FILES, validateDogfoodReport, validateEffortDecision, validateFromChatImgVisualMap, validateSkillCandidate, validateSkillInjectionDecision, validateTeamDashboardState, validateWorkOrderLedger } from '../core/artifact-schemas.mjs';
@@ -34,10 +34,10 @@ import { selectEffort, writeEffortDecision } from '../core/effort-orchestrator.m
34
34
  import { createWorkOrderLedger } from '../core/work-order-ledger.mjs';
35
35
  import { buildFromChatImgVisualMap } from '../core/from-chat-img-forensics.mjs';
36
36
  import { classifyDogfoodFinding, createDogfoodReport, writeDogfoodReport } from '../core/dogfood-loop.mjs';
37
- import { createSkillCandidate, decideSkillInjection, writeSkillCandidate, writeSkillForgeReport, writeSkillInjectionDecision } from '../core/skill-forge.mjs';
37
+ import { createSkillCandidate, decideSkillInjection, skillDreamFixture, writeSkillCandidate, writeSkillForgeReport, writeSkillInjectionDecision } from '../core/skill-forge.mjs';
38
38
  import { classifyToolError, harnessGrowthReport } from '../core/evaluation.mjs';
39
39
  import { runWorkflowPerfBench, validateWorkflowPerfReport } from '../core/perf-bench.mjs';
40
- import { proofFieldFixture, validateProofFieldReport } from '../core/proof-field.mjs';
40
+ import { buildProofField, proofFieldFixture, validateProofFieldReport } from '../core/proof-field.mjs';
41
41
  import { recordMistake, writeMistakeMemoryReport } from '../core/mistake-memory.mjs';
42
42
  import { buildPromptContext } from '../core/prompt-context-builder.mjs';
43
43
  import { renderTeamDashboardState, writeTeamDashboardState } from '../core/team-dashboard-renderer.mjs';
@@ -45,7 +45,7 @@ import { GOAL_WORKFLOW_ARTIFACT } from '../core/goal-workflow.mjs';
45
45
  import { CODEX_APP_DOCS_URL, codexAppIntegrationStatus, formatCodexAppStatus } from '../core/codex-app.mjs';
46
46
  import { buildWarpLaunchConfigYaml, buildWarpLaunchPlan, buildWarpOpenArgs, isWarpShellSession, runWarpLaunchConfigSyntaxCheck, warpOpenLaunchDecision, warpReadiness, warpStatusKind, defaultWarpWorkspaceName, formatWarpBanner, launchWarpTeamView, launchWarpUi, platformWarpInstallHint, runWarpStatus, sanitizeWarpWorkspaceName, teamLaneStyle, writeWarpLaunchConfig } from '../core/warp-ui.mjs';
47
47
  import { autoReviewProfileName, autoReviewStatus, autoReviewSummary, enableAutoReview, disableAutoReview, enableMadHighProfile, madHighProfileName } from '../core/auto-review.mjs';
48
- import { buildTeamPlan, codeStructureCommand, dbCommand, defaultBeta, defaultVGraph, evalCommand, gcCommand, goalCommand, gxCommand, harnessCommand, hproofCommand, memoryCommand, migrateWikiContextPack, parseTeamCreateArgs, perfCommand, profileCommand, projectWikiClaims, proofFieldCommand, qaLoopCommand, quickstartCommand, researchCommand, statsCommand, team, teamWorkflowMarkdown, validateArtifactsCommand, wikiCommand, wikiVoxelRowCount, writeWikiContextPack } from './maintenance-commands.mjs';
48
+ import { buildTeamPlan, codeStructureCommand, dbCommand, defaultBeta, defaultVGraph, evalCommand, gcCommand, goalCommand, gxCommand, harnessCommand, hproofCommand, memoryCommand, migrateWikiContextPack, parseTeamCreateArgs, perfCommand, profileCommand, projectWikiClaims, proofFieldCommand, qaLoopCommand, quickstartCommand, researchCommand, skillDreamCommand, statsCommand, team, teamWorkflowMarkdown, validateArtifactsCommand, wikiCommand, wikiVoxelRowCount, writeWikiContextPack } from './maintenance-commands.mjs';
49
49
 
50
50
  const flag = (args, name) => args.includes(name);
51
51
  const promptOf = (args) => args.filter((x) => !String(x).startsWith('--')).join(' ').trim();
@@ -104,6 +104,7 @@ export async function main(args) {
104
104
  if (cmd === 'validate-artifacts') return validateArtifactsCommand(tail);
105
105
  if (cmd === 'perf') return perfCommand(sub, rest);
106
106
  if (cmd === 'proof-field') return proofFieldCommand(sub, rest);
107
+ if (cmd === 'skill-dream') return skillDreamCommand(sub, rest);
107
108
  if (cmd === 'code-structure') return codeStructureCommand(sub, rest);
108
109
  if (cmd === 'memory') return memoryCommand(sub, rest);
109
110
  if (cmd === 'gx') return gxCommand(sub, rest);
@@ -148,7 +149,7 @@ Usage:
148
149
  sks qa-loop run <mission-id|latest> [--mock] [--max-cycles N]
149
150
  sks qa-loop status <mission-id|latest>
150
151
  sks context7 check|setup|tools|resolve|docs|evidence ...
151
- sks pipeline status|resume [--json]
152
+ sks pipeline status|resume|plan [--json] [--proof-field]
152
153
  sks pipeline answer <mission-id|latest> <answers.json>
153
154
  sks guard check [--json]
154
155
  sks conflicts check|prompt [--json]
@@ -182,6 +183,7 @@ Usage:
182
183
  sks eval compare --baseline old.json --candidate new.json [--json]
183
184
  sks perf run|workflow [--json] [--intent "task"] [--changed file1,file2]
184
185
  sks proof-field scan [--json] [--intent "task"]
186
+ sks skill-dream status|run|record [--json]
185
187
  sks harness fixture [--json]
186
188
  sks code-structure scan [--json]
187
189
  sks wiki coords --rgba 12,34,56,255
@@ -728,13 +730,16 @@ async function pipeline(sub = 'status', args = []) {
728
730
  const root = await sksRoot();
729
731
  const action = sub || 'status';
730
732
  if (action === 'answer') return pipelineAnswer(root, args);
733
+ if (action === 'plan') return pipelinePlan(root, args);
731
734
  const state = await readJson(stateFile(root), {});
732
735
  const evidence = await context7Evidence(root, state);
736
+ const plan = state.mission_id ? await readJson(path.join(missionDir(root, state.mission_id), PIPELINE_PLAN_ARTIFACT), null) : null;
733
737
  const stop = await evaluateStop(root, state, { last_assistant_message: 'SKS Honest Mode verification evidence gap' }, { noQuestion: false });
734
738
  const result = {
735
739
  root,
736
740
  state,
737
741
  context7: evidence,
742
+ plan: plan ? pipelinePlanSummary(plan, root, state.mission_id) : null,
738
743
  stop_gate: state.stop_gate || null,
739
744
  next_action: stop?.reason || 'No active blocking route gate detected.'
740
745
  };
@@ -745,12 +750,92 @@ async function pipeline(sub = 'status', args = []) {
745
750
  console.log(`Route: ${state.route_command || state.route || 'none'}`);
746
751
  console.log(`Phase: ${state.phase || 'IDLE'}`);
747
752
  console.log(`Mission: ${state.mission_id || 'none'}`);
753
+ if (plan) {
754
+ console.log(`Plan: ${path.relative(root, path.join(missionDir(root, state.mission_id), PIPELINE_PLAN_ARTIFACT))}`);
755
+ console.log(`Lane: ${plan.runtime_lane?.lane || 'unknown'} (${plan.runtime_lane?.source || 'unknown'})`);
756
+ console.log(`Stages: keep ${plan.stage_summary?.kept ?? '?'} / skip ${plan.stage_summary?.skipped ?? '?'}`);
757
+ }
748
758
  console.log(`Reasoning: ${state.reasoning_effort || 'medium'}${state.reasoning_profile ? ` (${state.reasoning_profile})` : ''}${state.reasoning_temporary ? ' temporary' : ''}`);
749
759
  console.log(`Stop gate: ${state.stop_gate || 'none'}`);
750
760
  console.log(`Context7: ${state.context7_required ? (evidence.ok ? 'ok' : 'required-missing') : 'optional'} (${evidence.count || 0} event(s))`);
751
761
  console.log(`Next: ${result.next_action}`);
752
762
  }
753
763
 
764
+ async function pipelinePlan(root, args = []) {
765
+ const state = await readJson(stateFile(root), {});
766
+ const missionArg = pipelineMissionArg(args);
767
+ const id = await resolveMissionId(root, missionArg);
768
+ let dir = null;
769
+ let mission = {};
770
+ let routeContext = {};
771
+ if (id) {
772
+ const loaded = await loadMission(root, id);
773
+ dir = loaded.dir;
774
+ mission = loaded.mission || {};
775
+ routeContext = await readJson(path.join(dir, 'route-context.json'), {});
776
+ const existing = await readJson(path.join(dir, PIPELINE_PLAN_ARTIFACT), null);
777
+ if (existing && !flag(args, '--refresh') && !flag(args, '--proof-field')) {
778
+ if (flag(args, '--json')) return console.log(JSON.stringify({ ok: validatePipelinePlan(existing).ok, plan_path: path.join(dir, PIPELINE_PLAN_ARTIFACT), plan: existing }, null, 2));
779
+ return printPipelinePlan(root, id, existing);
780
+ }
781
+ }
782
+ const intent = readOption(args, '--intent', routeContext.task || mission.prompt || state.prompt || '');
783
+ const route = ROUTES.find((candidate) => candidate.id === routeContext.route || candidate.command === routeContext.command || candidate.id === state.route || candidate.command === state.route_command)
784
+ || routePrompt(routeContext.command || state.route_command || intent || '$SKS');
785
+ const changedRaw = readOption(args, '--changed', '');
786
+ const proofField = flag(args, '--proof-field') ? await buildProofField(root, { intent, changedFiles: changedRaw ? changedRaw.split(',') : undefined }) : null;
787
+ const contract = dir ? await readJson(path.join(dir, 'decision-contract.json'), {}) : {};
788
+ const ambiguity = {
789
+ required: Boolean(routeContext.clarification_gate || state.ambiguity_gate_required),
790
+ passed: Boolean(state.ambiguity_gate_passed || state.clarification_passed),
791
+ status: state.clarification_required ? 'awaiting_answers' : (state.ambiguity_gate_passed ? 'contract_sealed' : undefined),
792
+ contract_hash: contract?.sealed_hash || null
793
+ };
794
+ const planInput = { missionId: id || null, route, task: intent, required: Boolean(routeContext.context7_required || state.context7_required), ambiguity, proofField };
795
+ const plan = dir ? await writePipelinePlan(dir, planInput) : buildPipelinePlan(planInput);
796
+ const validation = validatePipelinePlan(plan);
797
+ if (flag(args, '--json')) return console.log(JSON.stringify({ ok: validation.ok, validation, plan_path: dir ? path.join(dir, PIPELINE_PLAN_ARTIFACT) : null, plan }, null, 2));
798
+ printPipelinePlan(root, id || 'none', plan);
799
+ }
800
+
801
+ function pipelineMissionArg(args = []) {
802
+ const valueFlags = new Set(['--intent', '--changed']);
803
+ for (let i = 0; i < args.length; i++) {
804
+ const arg = String(args[i]);
805
+ if (valueFlags.has(arg)) {
806
+ i++;
807
+ continue;
808
+ }
809
+ if (!arg.startsWith('--')) return arg;
810
+ }
811
+ return 'latest';
812
+ }
813
+
814
+ function pipelinePlanSummary(plan, root, id) {
815
+ return {
816
+ path: id ? path.join(missionDir(root, id), PIPELINE_PLAN_ARTIFACT) : null,
817
+ validation: validatePipelinePlan(plan),
818
+ lane: plan.runtime_lane?.lane || null,
819
+ source: plan.runtime_lane?.source || null,
820
+ kept: plan.stage_summary?.kept ?? null,
821
+ skipped: plan.stage_summary?.skipped ?? null,
822
+ next_actions: plan.next_actions || []
823
+ };
824
+ }
825
+
826
+ function printPipelinePlan(root, id, plan) {
827
+ const validation = validatePipelinePlan(plan);
828
+ console.log('SKS Pipeline Plan\n');
829
+ console.log(`Mission: ${id}`);
830
+ console.log(`Route: ${plan.route?.command || plan.route?.id || 'unknown'}`);
831
+ console.log(`Lane: ${plan.runtime_lane?.lane || 'unknown'} (${plan.runtime_lane?.source || 'unknown'})`);
832
+ console.log(`Valid: ${validation.ok ? 'yes' : `no (${validation.issues.join(', ')})`}`);
833
+ if (id && id !== 'none') console.log(`Artifact: ${path.relative(root, path.join(missionDir(root, id), PIPELINE_PLAN_ARTIFACT))}`);
834
+ console.log(`Stages: keep ${plan.stage_summary?.kept ?? 0}, skip ${plan.stage_summary?.skipped ?? 0}, n/a ${plan.stage_summary?.not_applicable ?? 0}`);
835
+ console.log(`Verify: ${(plan.verification || []).join('; ')}`);
836
+ console.log(`Next: ${(plan.next_actions || []).join(' -> ')}`);
837
+ }
838
+
754
839
  async function pipelineAnswer(root, args = []) {
755
840
  const [missionArg, answerFile] = args;
756
841
  const id = await resolveMissionId(root, missionArg);
@@ -770,6 +855,7 @@ async function pipelineAnswer(root, args = []) {
770
855
  || routePrompt(routeContext.command || routeContext.route || '$SKS');
771
856
  await appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'pipeline.clarification.contract_sealed', route: route?.id || routeContext.route, hash: result.contract.sealed_hash });
772
857
  const materialized = await materializeAfterPipelineAnswer(root, id, dir, mission, route, routeContext, result.contract);
858
+ const pipelinePlan = await writePipelinePlan(dir, { missionId: id, route, task: materialized.prompt || routeContext.task || mission.prompt || '', required: Boolean(routeContext.context7_required), ambiguity: { required: true, passed: true, status: 'contract_sealed', contract_hash: result.contract.sealed_hash } });
773
859
  if (route?.id === 'QALoop') await writeQaLoopArtifacts(dir, mission, result.contract);
774
860
  await setCurrent(root, {
775
861
  mission_id: id,
@@ -791,16 +877,19 @@ async function pipelineAnswer(root, args = []) {
791
877
  ambiguity_gate_required: true,
792
878
  ambiguity_gate_passed: true,
793
879
  implementation_allowed: true,
880
+ pipeline_plan_ready: validatePipelinePlan(pipelinePlan).ok,
881
+ pipeline_plan_path: PIPELINE_PLAN_ARTIFACT,
794
882
  reasoning_effort: route ? routeReasoning(route, routeContext.task || mission.prompt || '').effort : 'medium',
795
883
  reasoning_profile: route ? routeReasoning(route, routeContext.task || mission.prompt || '').profile : 'sks-task-medium',
796
884
  reasoning_temporary: true,
797
885
  prompt: materialized.prompt || routeContext.task || mission.prompt || '',
798
886
  ...materialized.state
799
887
  });
800
- if (flag(args, '--json')) return console.log(JSON.stringify({ ok: true, mission_id: id, route: route?.id || routeContext.route, hash: result.contract.sealed_hash, validation: result.validation }, null, 2));
888
+ if (flag(args, '--json')) return console.log(JSON.stringify({ ok: true, mission_id: id, route: route?.id || routeContext.route, hash: result.contract.sealed_hash, validation: result.validation, pipeline_plan: path.join(dir, PIPELINE_PLAN_ARTIFACT) }, null, 2));
801
889
  console.log(`SKS ambiguity gate passed for ${id}`);
802
890
  console.log(`Route: ${route?.command || routeContext.command || '$SKS'}`);
803
891
  console.log(`Hash: ${result.contract.sealed_hash}`);
892
+ console.log(`Plan: ${path.relative(root, path.join(dir, PIPELINE_PLAN_ARTIFACT))}`);
804
893
  console.log('Next: continue the original route lifecycle using decision-contract.json.');
805
894
  }
806
895
 
@@ -1426,6 +1515,7 @@ function usage(args = []) {
1426
1515
  dollar: ['Dollar Commands', '', formatDollarCommandsCompact(' '), '', 'Terminal: sks dollar-commands [--json]'],
1427
1516
  wiki: ['TriWiki', '', ' sks wiki pack', ' sks wiki refresh [--prune]', ' sks wiki sweep latest --json', ' sks wiki validate .sneakoscope/wiki/context-pack.json', ' sks wiki prune --dry-run --json', '', 'Packs include attention.use_first and attention.hydrate_first for compact recall plus source hydration. Sweep records intentional forgetting and promotion candidates.'],
1428
1517
  harness: ['Harness Growth', '', ' sks harness fixture --json', ' sks harness review --json', '', 'Runs deterministic fixtures for deliberate forgetting, skill cards, harness experiments, tool error taxonomy, permission profiles, MultiAgentV2, and Warp cockpit views.'],
1518
+ 'skill-dream': ['Skill Dreaming', '', ' sks skill-dream status', ' sks skill-dream run --json', ' sks skill-dream record --route team --skills team,prompt-pipeline', '', 'Records cheap JSON usage counters in .sneakoscope/skills/dream-state.json and periodically writes recommendation-only keep/merge/prune/improve reports. It never deletes or merges skills automatically.'],
1429
1519
  'code-structure': ['Code Structure', '', ' sks code-structure scan', ' sks code-structure scan --json', '', 'Flags handwritten source files above 1000/2000/3000-line thresholds and records split-review exceptions.'],
1430
1520
  gx: ['GX', '', ' sks gx init architecture-atlas', ' sks gx render architecture-atlas --format all', ' sks gx validate architecture-atlas']
1431
1521
  };
@@ -2385,6 +2475,7 @@ async function selftest() {
2385
2475
  if (!hookTeamJson.hookSpecificOutput?.additionalContext?.includes('Codex plan-tool interaction')) throw new Error('selftest failed: $Team ambiguity gate did not inject plan-tool guidance');
2386
2476
  const hookTeamState = await readJson(stateFile(hookTeamTmp), {});
2387
2477
  if (hookTeamState.phase !== 'TEAM_CLARIFICATION_AWAITING_ANSWERS' || hookTeamState.implementation_allowed !== false) throw new Error('selftest failed: $Team hook did not lock execution behind ambiguity gate');
2478
+ if (!hookTeamState.pipeline_plan_ready || !(await exists(path.join(missionDir(hookTeamTmp, hookTeamState.mission_id), PIPELINE_PLAN_ARTIFACT)))) throw new Error('selftest failed: $Team hook did not write a pending pipeline plan');
2388
2479
  if (await exists(path.join(missionDir(hookTeamTmp, hookTeamState.mission_id), 'team-plan.json'))) throw new Error('selftest failed: Team plan was created before ambiguity gate passed');
2389
2480
  const hookTeamPendingResult = await runProcess(process.execPath, [hookBin, 'hook', 'user-prompt-submit'], { cwd: hookTeamTmp, input: JSON.stringify({ cwd: hookTeamTmp, prompt: '$Team 새 작업으로 넘어가' }), env: { SKS_DISABLE_UPDATE_CHECK: '1' }, timeoutMs: 15000, maxOutputBytes: 256 * 1024 });
2390
2481
  if (hookTeamPendingResult.code !== 0) throw new Error(`selftest failed: pending clarification hook exited ${hookTeamPendingResult.code}: ${hookTeamPendingResult.stderr}`);
@@ -2422,8 +2513,9 @@ async function selftest() {
2422
2513
  const pipelineAnswerResult = await runProcess(process.execPath, [hookBin, 'pipeline', 'answer', 'latest', hookTeamAnswersPath], { cwd: hookTeamTmp, env: { SKS_DISABLE_UPDATE_CHECK: '1' }, timeoutMs: 15000, maxOutputBytes: 64 * 1024 });
2423
2514
  if (pipelineAnswerResult.code !== 0) throw new Error(`selftest failed: pipeline answer exited ${pipelineAnswerResult.code}: ${pipelineAnswerResult.stderr}`);
2424
2515
  const answeredTeamState = await readJson(stateFile(hookTeamTmp), {});
2425
- if (answeredTeamState.phase !== 'TEAM_PARALLEL_ANALYSIS_SCOUTING' || !answeredTeamState.ambiguity_gate_passed || answeredTeamState.implementation_allowed !== true || !answeredTeamState.team_plan_ready) throw new Error('selftest failed: pipeline answer did not materialize Team after ambiguity gate');
2516
+ if (answeredTeamState.phase !== 'TEAM_PARALLEL_ANALYSIS_SCOUTING' || !answeredTeamState.ambiguity_gate_passed || answeredTeamState.implementation_allowed !== true || !answeredTeamState.team_plan_ready || !answeredTeamState.pipeline_plan_ready) throw new Error('selftest failed: pipeline answer did not materialize Team after ambiguity gate');
2426
2517
  if (!(await exists(path.join(missionDir(hookTeamTmp, hookTeamState.mission_id), 'decision-contract.json')))) throw new Error('selftest failed: pipeline answer did not seal decision contract');
2518
+ if (validatePipelinePlan(await readJson(path.join(missionDir(hookTeamTmp, hookTeamState.mission_id), PIPELINE_PLAN_ARTIFACT))).ok !== true) throw new Error('selftest failed: pipeline answer did not refresh a valid pipeline plan');
2427
2519
  if (!(await exists(path.join(missionDir(hookTeamTmp, hookTeamState.mission_id), 'team-plan.json'))) || !(await exists(path.join(missionDir(hookTeamTmp, hookTeamState.mission_id), 'team-live.md')))) throw new Error('selftest failed: Team artifacts missing after ambiguity gate passed');
2428
2520
  const honestLoopTmp = tmpdir();
2429
2521
  await initProject(honestLoopTmp, {});
@@ -2748,10 +2840,10 @@ async function selftest() {
2748
2840
  await writeJsonAtomic(path.join(fromChatCoverageDir, 'team-gate.json'), { ...passedTeamGate, from_chat_img_required: true, from_chat_img_request_coverage: true });
2749
2841
  const coveredFromChatStop = await evaluateStop(fromChatCoverageTmp, fromChatCoverageState, { last_assistant_message: 'SKS Honest Mode verification evidence gap' }, { noQuestion: false });
2750
2842
  if (coveredFromChatStop?.decision !== 'block' || String(coveredFromChatStop.reason || '').includes('from-chat-img') || !String(coveredFromChatStop.reason || '').includes(TEAM_SESSION_CLEANUP_ARTIFACT)) throw new Error('selftest failed: valid From-Chat-IMG artifacts did not hand off to session cleanup gate');
2751
- await recordContext7Evidence(routeGateTmp, gateState, { tool_name: 'resolve-library-id', library: 'react' });
2843
+ await recordContext7Evidence(routeGateTmp, gateState, { tool_name: 'mcp__context7__resolve_library_id', library: 'react' });
2752
2844
  const resolveOnlyStop = await evaluateStop(routeGateTmp, gateState, { last_assistant_message: 'SKS Honest Mode verification evidence gap' }, { noQuestion: false });
2753
2845
  if (resolveOnlyStop?.decision !== 'block') throw new Error('selftest failed: resolve-only Context7 evidence unblocked route');
2754
- await recordContext7Evidence(routeGateTmp, gateState, { tool_name: 'query-docs', library_id: '/facebook/react' });
2846
+ await recordContext7Evidence(routeGateTmp, gateState, { tool_name: 'mcp__context7__query_docs', library_id: '/facebook/react' });
2755
2847
  const missingCleanupStop = await evaluateStop(routeGateTmp, gateState, { last_assistant_message: 'SKS Honest Mode verification evidence gap' }, { noQuestion: false });
2756
2848
  if (missingCleanupStop?.decision !== 'block' || !String(missingCleanupStop.reason || '').includes(TEAM_SESSION_CLEANUP_ARTIFACT)) throw new Error('selftest failed: Team route did not block missing session cleanup gate');
2757
2849
  await writeJsonAtomic(path.join(gateDir, TEAM_SESSION_CLEANUP_ARTIFACT), passedTeamSessionCleanup);
@@ -2863,6 +2955,8 @@ async function selftest() {
2863
2955
  if (!validateSkillCandidate(skillCandidate).ok) throw new Error('selftest failed: active skill candidate rejected');
2864
2956
  const injection = decideSkillInjection({ route: 'from-chat-img', task_signature: 'reference images', skills: [skillCandidate, { ...skillCandidate, id: 'deprecated', status: 'deprecated' }] });
2865
2957
  if (!validateSkillInjectionDecision(injection).ok || injection.injected.length !== 1) throw new Error('selftest failed: skill injection did not respect active/top-K filtering');
2958
+ const skillDream = await skillDreamFixture(path.join(tmp, 'skill-dream-fixture'));
2959
+ if (!skillDream.passed) throw new Error('selftest failed: skill dreaming did not keep used skills, recommend unused generated skills, and preserve custom skills');
2866
2960
  const promptContext = buildPromptContext({ stable: ['stable'], policies: ['policy'], dynamic: ['dynamic'] });
2867
2961
  if (promptContext.blocks[0]?.cache_region !== 'stable_prefix' || promptContext.blocks.at(-1)?.cache_region !== 'dynamic_suffix') throw new Error('selftest failed: prompt context did not place dynamic context last');
2868
2962
  const repeatedMistake = await recordMistake(teamDir, { route: 'from-chat-img', gate: 'visual-map', reason: 'unmatched-reference' });
@@ -2961,13 +3055,19 @@ async function selftest() {
2961
3055
  if (!harnessReport.forgetting.fixture.passed || !harnessReport.warp.views.includes('Harness Experiments View') || !harnessReport.reliability.tool_error_taxonomy.includes('Unknown')) throw new Error('selftest failed: harness growth fixture incomplete');
2962
3056
  const proofField = await proofFieldFixture();
2963
3057
  if (!proofField.validation.ok || !validateProofFieldReport(proofField.report).ok) throw new Error('selftest failed: proof field report invalid');
2964
- if (!proofField.checks.route_cone_selected || !proofField.checks.cli_cone_selected || !proofField.checks.catastrophic_guard_present || !proofField.checks.negative_release_work_recorded) throw new Error('selftest failed: proof field fixture checks incomplete');
3058
+ 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.simplicity_score_usable || !proofField.checks.execution_fast_lane_selected) throw new Error('selftest failed: proof field fixture checks incomplete');
3059
+ 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');
3060
+ const fastPipelinePlan = buildPipelinePlan({ route: routePrompt('$Team small CLI help update'), task: 'small CLI help surface update', proofField: proofField.report });
3061
+ 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');
3062
+ 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'] });
3063
+ const broadPipelinePlan = buildPipelinePlan({ route: routePrompt('$Team database security route refactor'), task: 'database security route refactor', proofField: broadProofField });
3064
+ 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');
2965
3065
  const workflowPerf = await runWorkflowPerfBench(tmp, {
2966
3066
  iterations: 2,
2967
3067
  intent: 'small CLI help surface update',
2968
3068
  changedFiles: ['src/cli/maintenance-commands.mjs', 'src/core/routes.mjs']
2969
3069
  });
2970
- if (!validateWorkflowPerfReport(workflowPerf).ok || workflowPerf.metrics.decision_mode !== 'fast_lane' || !workflowPerf.metrics.fast_lane_eligible) throw new Error('selftest failed: workflow perf proof field did not produce a valid fast lane report');
3070
+ if (!validateWorkflowPerfReport(workflowPerf).ok || workflowPerf.metrics.decision_mode !== 'fast_lane' || workflowPerf.metrics.execution_lane !== 'proof_field_fast_lane' || workflowPerf.metrics.pipeline_lane !== 'proof_field_fast_lane' || !workflowPerf.metrics.fast_lane_eligible || !workflowPerf.metrics.fast_lane_allowed || Number(workflowPerf.metrics.simplicity_score) < 0.75 || Number(workflowPerf.metrics.outcome_criteria_passed) < 3) throw new Error('selftest failed: workflow perf proof field did not produce a valid outcome-scored fast lane report');
2971
3071
  if (classifyToolError({ message: 'operation timed out' }) !== 'Timeout' || classifyToolError({ message: 'unclassified weirdness' }) !== 'Unknown') throw new Error('selftest failed: tool error taxonomy classification');
2972
3072
  const coord = rgbaToWikiCoord({ r: 12, g: 34, b: 56, a: 255 });
2973
3073
  if (coord.schema !== 'sks.wiki-coordinate.v1' || coord.xyzw.length !== 4) throw new Error('selftest failed: RGBA wiki coordinate conversion');
@@ -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, 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, ROUTES, hasFromChatImgSignal, routePrompt, 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, stackCurrentDocsPolicy, 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, formatRoleCounts, initTeamLive, normalizeTeamSpec, parseTeamSpecArgs, readTeamControl, readTeamDashboard, readTeamLive, readTeamTranscriptTail, renderTeamAgentLane, renderTeamCleanupSummary, renderTeamWatch, requestTeamSessionCleanup, teamCleanupRequested } from '../core/team-live.mjs';
21
21
  import { ARTIFACT_FILES, writeValidationReport } from '../core/artifact-schemas.mjs';
@@ -25,11 +25,12 @@ import { writeFromChatImgArtifacts } from '../core/from-chat-img-forensics.mjs';
25
25
  import { renderTeamDashboardState, writeTeamDashboardState } from '../core/team-dashboard-renderer.mjs';
26
26
  import { runPerfBench, runWorkflowPerfBench } from '../core/perf-bench.mjs';
27
27
  import { writeProofFieldReport } from '../core/proof-field.mjs';
28
+ import { PIPELINE_PLAN_ARTIFACT, validatePipelinePlan, writePipelinePlan } from '../core/pipeline.mjs';
28
29
  import { GOAL_BRIDGE_ARTIFACT, GOAL_WORKFLOW_ARTIFACT, updateGoalWorkflow, writeGoalWorkflow } from '../core/goal-workflow.mjs';
29
30
  import { scanCodeStructure, writeCodeStructureReport } from '../core/code-structure.mjs';
30
31
  import { writeMemorySweepReport } from '../core/memory-governor.mjs';
31
32
  import { cleanupWarpTeamView, launchWarpTeamView } from '../core/warp-ui.mjs';
32
- import { writeSkillForgeReport } from '../core/skill-forge.mjs';
33
+ import { loadSkillDreamState, recordSkillDreamEvent, runSkillDream, writeSkillForgeReport } from '../core/skill-forge.mjs';
33
34
  import { writeMistakeMemoryReport } from '../core/mistake-memory.mjs';
34
35
  import { checkDbOperation, checkSqlFile, classifyCommand, classifySql, loadDbSafetyPolicy, safeSupabaseMcpConfig, scanDbSafety } from '../core/db-safety.mjs';
35
36
  import { harnessGrowthReport, writeHarnessGrowthReport } from '../core/evaluation.mjs';
@@ -573,6 +574,58 @@ export async function proofFieldCommand(sub, args = []) {
573
574
  console.log(`Report: ${path.relative(root, report.report_path)}`);
574
575
  }
575
576
 
577
+ export async function skillDreamCommand(sub, args = []) {
578
+ const action = sub && !String(sub).startsWith('--') ? sub : 'status';
579
+ const actionArgs = action === sub ? args : [sub, ...args].filter(Boolean);
580
+ if (!['status', 'run', 'record', 'help', '--help'].includes(action)) {
581
+ console.error('Usage: sks skill-dream status|run|record [--json]');
582
+ process.exitCode = 1;
583
+ return;
584
+ }
585
+ if (action === 'help' || action === '--help') {
586
+ console.log('Usage: sks skill-dream status|run|record [--json]');
587
+ console.log('Records cheap generated-skill usage counters and periodically reports keep, merge, prune, and improvement candidates. Reports never delete skills automatically.');
588
+ return;
589
+ }
590
+ const root = await sksRoot();
591
+ if (action === 'record') {
592
+ const skills = readFlagValue(actionArgs, '--skills', '').split(',').map((x) => x.trim()).filter(Boolean);
593
+ const result = await recordSkillDreamEvent(root, {
594
+ route: readFlagValue(actionArgs, '--route', positionalArgs(actionArgs).join(' ') || 'manual'),
595
+ command: readFlagValue(actionArgs, '--command', null),
596
+ required_skills: skills,
597
+ prompt_signature: readFlagValue(actionArgs, '--prompt-signature', null)
598
+ }, { known_skill_names: knownGeneratedSkillNames() });
599
+ if (flag(actionArgs, '--json')) return console.log(JSON.stringify(result, null, 2));
600
+ console.log('SKS Skill Dream Record');
601
+ console.log(`Events since last run: ${result.state.counters.events_since_last_run}`);
602
+ console.log(`Due: ${result.due.due ? 'yes' : 'no'} (${result.due.reason_codes.join(', ')})`);
603
+ if (result.report) console.log(`Report: ${path.relative(root, result.report.report_path)}`);
604
+ return;
605
+ }
606
+ if (action === 'run') {
607
+ const report = await runSkillDream(root, { force: true, known_skill_names: knownGeneratedSkillNames() });
608
+ if (flag(actionArgs, '--json')) return console.log(JSON.stringify(report, null, 2));
609
+ console.log('SKS Skill Dream');
610
+ console.log(`Inventory: ${report.inventory.total} skills (${report.inventory.generated} generated, ${report.inventory.unknown_or_user} unknown/user)`);
611
+ console.log(`Keep: ${report.keep.length}`);
612
+ console.log(`Merge candidates: ${report.merge_candidates.length}`);
613
+ console.log(`Prune candidates: ${report.prune_candidates.length}`);
614
+ console.log(`Improve candidates: ${report.improve_candidates.length}`);
615
+ console.log(`Apply mode: ${report.apply_mode}; no auto delete: ${report.no_auto_delete ? 'yes' : 'no'}`);
616
+ console.log(`Report: ${path.relative(root, report.report_path)}`);
617
+ return;
618
+ }
619
+ const state = await loadSkillDreamState(root);
620
+ if (flag(actionArgs, '--json')) return console.log(JSON.stringify(state, null, 2));
621
+ console.log('SKS Skill Dream Status');
622
+ console.log(`State: .sneakoscope/skills/dream-state.json`);
623
+ console.log(`Events since last run: ${state.counters.events_since_last_run}/${state.policy.min_events_between_runs}`);
624
+ console.log(`Cooldown: ${state.policy.min_interval_hours}h`);
625
+ console.log(`Last run: ${state.last_run_at || 'never'}`);
626
+ console.log(`Next: ${state.next_run?.due ? 'due' : (state.next_run?.reason_codes || ['not due']).join(', ')}`);
627
+ }
628
+
576
629
  export async function harnessCommand(sub, args = []) {
577
630
  const action = sub || 'fixture';
578
631
  if (!['fixture', 'review'].includes(action)) {
@@ -1249,7 +1302,7 @@ export async function statsCommand(args) {
1249
1302
 
1250
1303
  function positionalArgs(args = []) {
1251
1304
  const out = [];
1252
- const valueFlags = new Set(['--format', '--iterations', '--out', '--baseline', '--candidate', '--install-scope', '--max-cycles', '--depth', '--scope', '--transport', '--query', '--topic', '--tokens', '--timeout-ms', '--sql', '--command', '--project-ref', '--agent', '--phase', '--message', '--role', '--max-anchors', '--lines', '--intent', '--changed']);
1305
+ const valueFlags = new Set(['--format', '--iterations', '--out', '--baseline', '--candidate', '--install-scope', '--max-cycles', '--depth', '--scope', '--transport', '--query', '--topic', '--tokens', '--timeout-ms', '--sql', '--command', '--project-ref', '--agent', '--phase', '--message', '--role', '--max-anchors', '--lines', '--intent', '--changed', '--route', '--skills', '--prompt-signature']);
1253
1306
  for (let i = 0; i < args.length; i++) {
1254
1307
  const arg = String(args[i]);
1255
1308
  if (valueFlags.has(arg)) {
@@ -1266,6 +1319,10 @@ function readFlagValue(args, name, fallback) {
1266
1319
  return i >= 0 && args[i + 1] ? args[i + 1] : fallback;
1267
1320
  }
1268
1321
 
1322
+ function knownGeneratedSkillNames() {
1323
+ return Array.from(new Set([...DOLLAR_SKILL_NAMES, ...RECOMMENDED_SKILLS]));
1324
+ }
1325
+
1269
1326
  function cartridgeName(args, fallback = 'architecture-atlas') {
1270
1327
  const raw = positionalArgs(args)[0] || fallback;
1271
1328
  return String(raw).trim().replace(/[\\/]+/g, '-').replace(/[^A-Za-z0-9_.-]+/g, '-').replace(/^-+|-+$/g, '') || fallback;
@@ -1406,6 +1463,9 @@ export async function team(args) {
1406
1463
  let dashboardState = await writeTeamDashboardState(dir, { missionId: id, mission: { id, mode: 'team' }, effort: effortDecision.selected_effort, phase: 'intake', next_action: fromChatImgRequired ? 'complete visual source inventory and work-order mapping' : 'run Team analysis scouts' });
1407
1464
  await writeJsonAtomic(path.join(dir, 'team-gate.json'), { passed: false, team_roster_confirmed: true, analysis_artifact: false, triwiki_refreshed: false, triwiki_validated: false, consensus_artifact: false, ...runtime.gate_fields, implementation_team_fresh: false, review_artifact: false, integration_evidence: false, session_cleanup: false, context7_evidence: false, ...(fromChatImgRequired ? { from_chat_img_required: true, from_chat_img_request_coverage: false } : {}) });
1408
1465
  dashboardState = await writeTeamDashboardState(dir, { missionId: id, mission: { id, mode: 'team' }, effort: effortDecision.selected_effort, phase: 'intake', next_action: fromChatImgRequired ? 'complete visual source inventory and work-order mapping' : 'run Team analysis scouts' });
1466
+ const route = routePrompt(`$Team ${prompt}`) || ROUTES.find((candidate) => candidate.id === 'Team');
1467
+ const pipelinePlan = await writePipelinePlan(dir, { missionId: id, route, task: prompt, required: false, ambiguity: { required: false, status: 'team_cli_direct' } });
1468
+ await setCurrent(root, { mission_id: id, route: 'Team', route_command: '$Team', mode: 'TEAM', phase: 'TEAM_PARALLEL_ANALYSIS_SCOUTING', questions_allowed: false, implementation_allowed: true, context7_required: false, context7_verified: false, subagents_required: true, subagents_verified: false, reflection_required: true, visible_progress_required: true, context_tracking: 'triwiki', required_skills: route?.requiredSkills || ['team'], stop_gate: 'team-gate.json', reasoning_effort: 'high', reasoning_profile: 'sks-logic-high', reasoning_temporary: true, agent_sessions: agentSessions, role_counts: roleCounts, team_roster_confirmed: true, team_graph_ready: runtime.ok, team_live_ready: true, from_chat_img_required: fromChatImgRequired, pipeline_plan_ready: validatePipelinePlan(pipelinePlan).ok, pipeline_plan_path: PIPELINE_PLAN_ARTIFACT, prompt });
1409
1469
  const result = {
1410
1470
  mission_id: id,
1411
1471
  mission_dir: dir,
@@ -1421,6 +1481,7 @@ export async function team(args) {
1421
1481
  dashboard_state: path.join(dir, ARTIFACT_FILES.team_dashboard_state),
1422
1482
  effort_decision: path.join(dir, ARTIFACT_FILES.effort_decision),
1423
1483
  work_order_ledger: path.join(dir, ARTIFACT_FILES.work_order_ledger),
1484
+ pipeline_plan: path.join(dir, PIPELINE_PLAN_ARTIFACT),
1424
1485
  dashboard_state_valid: dashboardState.ok,
1425
1486
  context_pack: path.join(root, '.sneakoscope', 'wiki', 'context-pack.json'),
1426
1487
  agent_sessions: agentSessions,
@@ -1433,6 +1494,7 @@ export async function team(args) {
1433
1494
  if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
1434
1495
  console.log(`Team mission created: ${id}`);
1435
1496
  console.log(`Plan: ${path.relative(root, result.plan)}`);
1497
+ console.log(`Pipeline plan: ${path.relative(root, result.pipeline_plan)}`);
1436
1498
  console.log(`Agent sessions: ${agentSessions}`);
1437
1499
  console.log(`Role counts: ${formatRoleCounts(roleCounts)}`);
1438
1500
  console.log(`Workflow: ${path.relative(root, result.workflow)}`);
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.6.98';
8
+ export const PACKAGE_VERSION = '0.7.0';
9
9
  export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
10
10
  export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
11
11