sneakoscope 0.7.78 → 0.8.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
@@ -40,6 +40,25 @@ sks selftest --mock
40
40
 
41
41
  `sks` adds a tmux Codex CLI runtime, Codex App `$` commands, Team/QA/PPT/Research/DB/GX/Wiki routes, OpenClaw skill generation, Context7-gated current docs, TriWiki context packs, DB safety, design SSOT policy, skill dreaming, release checks, and Honest Mode.
42
42
 
43
+ ## 0.8.0 Massive Upgrade
44
+
45
+ Sneakoscope 0.8.0 introduces the RecallPulse planning spine: a report-only active-recall layer that records what the pipeline should remember before a stage proceeds. RecallPulse maps TriWiki into L1/L2/L3 cache behavior, writes durable status ledgers instead of relying on ephemeral hook text, suppresses duplicate reminder loops, and emits RouteProofCapsule plus EvidenceEnvelope artifacts for later gate comparison. These artifacts are evidence surfaces first; speed or accuracy gains remain benchmark-gated until scored evals prove them.
46
+
47
+ Inspect the new report-only artifacts with:
48
+
49
+ ```sh
50
+ sks recallpulse run latest
51
+ sks recallpulse status latest --json
52
+ sks recallpulse eval latest --json
53
+ sks recallpulse governance latest --json
54
+ sks recallpulse checklist latest --json
55
+ sks recallpulse checklist latest --task T001 --apply --evidence src/core/recallpulse.mjs
56
+ ```
57
+
58
+ Research scouts now use named persona-inspired cognitive lenses: Einstein Scout, Feynman Scout, Turing Scout, von Neumann Scout, and Skeptic Scout. They are not impersonations; each scout ledger row must carry `display_name`, `persona`, `persona_boundary`, `reasoning_effort=xhigh`, a literal `Eureka!` idea, falsifiers, cheap probes, and debate participation evidence.
59
+
60
+ For existing 0.7.x users, the visible change is new report-only evidence, not a route personality rewrite. Team still feels like Team, DFix stays ultralight, DB remains conservative, QA-LOOP still dogfoods, PPT stays information-first, imagegen still requires real raster evidence, and Honest Mode remains the final truth pass. The original strong reminder idea became neutral RecallPulse so user-facing prompts stay short, professional, and non-repetitive; hook messages can point at status, but `mission-status-ledger.json` is the durable source when app-visible text disappears. The planning source is `docs/RECALLPULSE_0_8_0_TASKS.md`, and implementation is designed to land in safe task-sized slices before any enforcement promotion.
61
+
43
62
  ## Requirements
44
63
 
45
64
  - Node.js `>=20.11`
@@ -195,6 +214,10 @@ sks goal create "persist this migration workflow"
195
214
  sks research prepare "evaluate this approach"
196
215
  sks research run latest --max-cycles 3 --cycle-timeout-minutes 120
197
216
  sks research status latest
217
+ sks recallpulse run latest
218
+ sks recallpulse status latest --json
219
+ sks recallpulse governance latest --json
220
+ sks recallpulse checklist latest --json
198
221
  sks db scan --json
199
222
  sks wiki refresh
200
223
  sks wiki sweep latest --json
@@ -212,7 +235,9 @@ sks skill-dream run --json
212
235
  sks code-structure scan --json
213
236
  ```
214
237
 
215
- `sks research` prepares a genius-lens scout council, requires every scout to run at `xhigh`, records one literal `Eureka!` idea per scout, runs an evidence-bound debate, and now creates `research-source-skill.md` as a route-local source collection skill before synthesis. Normal Research is intentionally allowed to take one or two hours when the problem needs it; `--mock` is only for selftests or dry harness checks, and a real run blocks with `research-blocker.json` instead of silently substituting mock output when the Codex execution path is unavailable. The source layer contract separates latest papers, official/government or leading-institution sources, standards/primary docs, current news such as BBC/CNN/GDELT-style sources, public discourse such as X/Reddit, developer/practitioner knowledge such as Stack Overflow/GitHub, and counterevidence/fact-checking; `source-ledger.json` must record layer coverage, source quality, blockers, citations, and cross-layer triangulation. Context7 is optional for `$Research` and only becomes relevant when the research topic specifically depends on package, API, framework, or SDK documentation. Research runs require `research-report.md`, `research-paper.md`, `genius-opinion-summary.md`, `research-source-skill.md`, `source-ledger.json`, `scout-ledger.json`, `debate-ledger.json`, `novelty-ledger.json`, `falsification-ledger.json`, and `research-gate.json` so they stay source-backed, adversarially checked, falsifiable, paper-ready, and clear about every scout lens opinion. `research status` reports source entries, source-layer coverage, triangulation checks, counterevidence, xhigh scout count, Eureka moments, debate exchanges, paper presence/sections, genius-opinion summary coverage, scout findings, and falsification cases alongside the gate.
238
+ `sks research` prepares a named genius-lens scout council, requires every scout to run at `xhigh`, records one literal `Eureka!` idea per scout, runs an evidence-bound debate, and now creates `research-source-skill.md` as a route-local source collection skill before synthesis. The required Research persona lenses are Einstein Scout, Feynman Scout, Turing Scout, von Neumann Scout, and Skeptic Scout; they are cognitive roles, not impersonations, and `scout-ledger.json` must include `display_name`, `persona`, `persona_boundary`, `reasoning_effort`, falsifiers, cheap probes, and `challenge_or_response`. Normal Research is intentionally allowed to take one or two hours when the problem needs it; `--mock` is only for selftests or dry harness checks, and a real run blocks with `research-blocker.json` instead of silently substituting mock output when the Codex execution path is unavailable. The source layer contract separates latest papers, official/government or leading-institution sources, standards/primary docs, current news such as BBC/CNN/GDELT-style sources, public discourse such as X/Reddit, developer/practitioner knowledge such as Stack Overflow/GitHub, and counterevidence/fact-checking; `source-ledger.json` must record layer coverage, source quality, blockers, citations, and cross-layer triangulation. Context7 is optional for `$Research` and only becomes relevant when the research topic specifically depends on package, API, framework, or SDK documentation. Research runs require `research-report.md`, `research-paper.md`, `genius-opinion-summary.md`, `research-source-skill.md`, `source-ledger.json`, `scout-ledger.json`, `debate-ledger.json`, `novelty-ledger.json`, `falsification-ledger.json`, and `research-gate.json` so they stay source-backed, adversarially checked, falsifiable, paper-ready, and clear about every scout lens opinion. `research status` reports source entries, source-layer coverage, triangulation checks, counterevidence, xhigh scout count, Eureka moments, debate exchanges, paper presence/sections, genius-opinion summary coverage, scout findings, and falsification cases alongside the gate.
239
+
240
+ `sks recallpulse` is the 0.8.0 report-only RecallPulse utility. It writes `recallpulse-decision.json`, `mission-status-ledger.json`, `route-proof-capsule.json`, `evidence-envelope.json`, `recallpulse-governance-report.json`, `recallpulse-task-goal-ledger.json`, and `recallpulse-eval-report.json` for the current mission. RecallPulse does not replace route gates, Honest Mode, DB safety, imagegen evidence, or TriWiki validation; it records cache hits, hydration needs, duplicate suppression, route-governance risks, and final-summary-ready durable status so later releases can promote only measured improvements. Checklist updates are sequential: every `Txxx` row is treated as a child `$Goal` checkpoint, and `sks recallpulse checklist ... --task T001 --apply` refuses out-of-order checks unless explicitly overridden.
216
241
 
217
242
  `sks pipeline plan` shows the active route lane, kept/skipped stages, verification commands, and no-unrequested-fallback invariant. `sks proof-field scan` is the lightweight rubric for small changes; risky or broad signals return to the full Team/Honest path.
218
243
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "0.7.78",
4
+ "version": "0.8.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
@@ -23,6 +23,7 @@ import { rustInfo } from '../core/rust-accelerator.mjs';
23
23
  import { renderCartridge, validateCartridge, driftCartridge, snapshotCartridge } from '../core/gx-renderer.mjs';
24
24
  import { defaultEvaluationScenario, runEvaluationBenchmark } from '../core/evaluation.mjs';
25
25
  import { evaluateResearchGate, writeMockResearchResult, writeResearchPlan } from '../core/research.mjs';
26
+ import { evaluateRecallPulseFixtures, readMissionStatusLedger, writeRecallPulseArtifacts } from '../core/recallpulse.mjs';
26
27
  import {
27
28
  PPT_AUDIENCE_STRATEGY_ARTIFACT,
28
29
  PPT_CLEANUP_REPORT_ARTIFACT,
@@ -81,6 +82,7 @@ import { context7Command } from './context7-command.mjs';
81
82
  import { askPostinstallQuestion, checkCodexLbResponseChain, checkContext7, checkRequiredSkills, codexLbStatus, configureCodexLb, ensureCodexCliTool, ensureGlobalCodexFastModeDuringInstall, ensureGlobalCodexSkillsDuringInstall, ensureProjectContext7Config, ensureRelatedCliTools, ensureSksCommandDuringInstall, ensureTmuxCliTool, globalCodexSkillsRoot, maybePromptCodexLbSetupForLaunch, maybePromptCodexUpdateForLaunch, postinstall, postinstallBootstrapDecision, repairCodexLbAuth, selftestCodexLb, shouldAutoApproveInstall } from './install-helpers.mjs';
82
83
  import { buildTeamPlan, codeStructureCommand, dbCommand, defaultBeta, defaultVGraph, evalCommand, gcCommand, goalCommand, gxCommand, harnessCommand, hproofCommand, madHighCommand as runMadHighCommand, memoryCommand, migrateWikiContextPack, parseTeamCreateArgs, perfCommand, profileCommand, projectWikiClaims, proofFieldCommand, qaLoopCommand, quickstartCommand, researchCommand, skillDreamCommand, statsCommand, team, teamWorkflowMarkdown, validateArtifactsCommand, wikiCommand, wikiVoxelRowCount, writeWikiContextPack } from './maintenance-commands.mjs';
83
84
  import { openClawCommand } from './openclaw-command.mjs';
85
+ import { recallPulseCommand } from './recallpulse-command.mjs';
84
86
 
85
87
  const flag = (args, name) => args.includes(name);
86
88
  const promptOf = (args) => args.filter((x) => !String(x).startsWith('--')).join(' ').trim();
@@ -109,7 +111,7 @@ export async function main(args) {
109
111
  if (String(cmd).toLowerCase() === 'dfix') return dfixHelp();
110
112
  const handlers = {
111
113
  postinstall: () => postinstall({ bootstrap }), wizard: () => wizard(tail), ui: () => wizard(tail), 'update-check': () => updateCheck(tail), help: () => help(tail), commands: () => commands(tail), usage: () => usage(tail), root: () => rootCommand(tail), quickstart: () => quickstartCommand(), 'codex-app': () => codexAppHelp(tail), 'codex-lb': () => codexLbCommand(sub, rest), auth: () => codexLbCommand(sub, rest), openclaw: () => openClawCommand(tail), bootstrap: () => bootstrap(tail), deps: () => deps(sub, rest),
112
- 'qa-loop': () => qaLoopCommand(sub, rest), ppt: () => pptCommand(sub, rest), 'image-ux-review': () => imageUxReviewCommand(sub, rest), 'ux-review': () => imageUxReviewCommand(sub, rest), 'visual-review': () => imageUxReviewCommand(sub, rest), 'ui-ux-review': () => imageUxReviewCommand(sub, rest), context7: () => context7Command(sub, rest), pipeline: () => pipeline(sub, rest), guard: () => guard(sub, rest), conflicts: () => conflicts(sub, rest), versioning: () => versioning(sub, rest), reasoning: () => reasoningCommand(tail), aliases: () => aliases(), setup: () => setup(tail), 'fix-path': () => fixPath(tail), doctor: () => doctor(tail), init: () => init(tail), selftest: () => selftest(tail),
114
+ 'qa-loop': () => qaLoopCommand(sub, rest), ppt: () => pptCommand(sub, rest), 'image-ux-review': () => imageUxReviewCommand(sub, rest), 'ux-review': () => imageUxReviewCommand(sub, rest), 'visual-review': () => imageUxReviewCommand(sub, rest), 'ui-ux-review': () => imageUxReviewCommand(sub, rest), context7: () => context7Command(sub, rest), recallpulse: () => recallPulseCommand(sub, rest), pipeline: () => pipeline(sub, rest), guard: () => guard(sub, rest), conflicts: () => conflicts(sub, rest), versioning: () => versioning(sub, rest), reasoning: () => reasoningCommand(tail), aliases: () => aliases(), setup: () => setup(tail), 'fix-path': () => fixPath(tail), doctor: () => doctor(tail), init: () => init(tail), selftest: () => selftest(tail),
113
115
  goal: () => goalCommand(sub, rest), research: () => researchCommand(sub, rest), hook: () => emitHook(sub), profile: () => profileCommand(sub, rest), hproof: () => hproofCommand(sub, rest), 'validate-artifacts': () => validateArtifactsCommand(tail), perf: () => perfCommand(sub, rest), 'proof-field': () => proofFieldCommand(sub, rest), 'skill-dream': () => skillDreamCommand(sub, rest), 'code-structure': () => codeStructureCommand(sub, rest), memory: () => memoryCommand(sub, rest), gx: () => gxCommand(sub, rest),
114
116
  team: () => team(tail), db: () => dbCommand(sub, rest), eval: () => evalCommand(sub, rest), harness: () => harnessCommand(sub, rest), wiki: () => wikiCommand(sub, rest), gc: () => gcCommand(tail), stats: () => statsCommand(tail)
115
117
  };
@@ -195,6 +197,7 @@ Usage:
195
197
  sks ppt build <mission-id|latest> [--json]
196
198
  sks ppt status <mission-id|latest> [--json]
197
199
  sks context7 check|setup|tools|resolve|docs|evidence ...
200
+ sks recallpulse run|status|eval|governance|checklist <mission-id|latest>
198
201
  sks pipeline status|resume|plan [--json] [--proof-field]
199
202
  sks pipeline answer <mission-id|latest> <answers.json|--stdin|--text "...">
200
203
  sks guard check [--json]
@@ -3905,9 +3908,28 @@ async function selftest() {
3905
3908
  await writeJsonAtomic(path.join(path.dirname(dryRunPack.file), 'low-trust-artifact.json'), { trust_summary: { avg: 0.1 }, wiki: { anchors: [] } });
3906
3909
  const wikiPruneDryRun = await pruneWikiArtifacts(tmp, { dryRun: true });
3907
3910
  if (wikiPruneDryRun.candidates < 1 || !wikiPruneDryRun.actions.some((action) => action.reason === 'low_wiki_trust')) throw new Error('selftest: wiki prune did not flag low-trust artifact');
3911
+ await writeJsonAtomic(path.join(tmp, '.sneakoscope', 'wiki', 'context-pack.json'), wikiPack);
3912
+ const recallPulseRun = await writeRecallPulseArtifacts(tmp, {
3913
+ missionId: recallMission.id,
3914
+ state: { mission_id: recallMission.id, mode: 'team', route: 'team', phase: 'implementation', prompt: recallPrompt },
3915
+ stageId: 'before_implementation'
3916
+ });
3917
+ if (!recallPulseRun.decision?.report_only || !recallPulseRun.decision?.l1?.selected?.length || recallPulseRun.decision?.l2?.tier !== 'L2' || recallPulseRun.decision?.l3?.tier !== 'L3') throw new Error('selftest: RecallPulse did not write L1/L2/L3 report-only decision');
3918
+ if (!recallPulseRun.capsule?.report_only || !recallPulseRun.envelope?.claim_ids_supported?.includes('durable_status_ledger')) throw new Error('selftest: RecallPulse proof capsule/evidence envelope incomplete');
3919
+ const recallPulseStatusLedger = await readMissionStatusLedger(tmp, recallMission.id);
3920
+ if (!recallPulseStatusLedger?.entries?.length || !recallPulseStatusLedger.final_summary_projection?.last_user_visible) throw new Error('selftest: RecallPulse durable status ledger missing');
3921
+ const repeatedRecallPulseRun = await writeRecallPulseArtifacts(tmp, {
3922
+ missionId: recallMission.id,
3923
+ state: { mission_id: recallMission.id, mode: 'team', route: 'team', phase: 'implementation', prompt: recallPrompt },
3924
+ stageId: 'before_implementation'
3925
+ });
3926
+ if (repeatedRecallPulseRun.decision?.recommended_action !== 'suppress' || !repeatedRecallPulseRun.decision?.duplicate_suppression?.repeated) throw new Error('selftest: RecallPulse duplicate reminder suppression missing');
3927
+ const recallPulseEval = await evaluateRecallPulseFixtures(tmp, { missionId: recallMission.id, write: true });
3928
+ if (!recallPulseEval.passed || recallPulseEval.metrics.route_gate_agreement < 1 || recallPulseEval.metrics.unsupported_performance_claims !== 0) throw new Error('selftest: RecallPulse fixture eval failed');
3908
3929
  const { dir: researchDir, mission: researchMission } = await createMission(tmp, { mode: 'research', prompt: '새로운 코드 리뷰 방법론 연구' });
3909
3930
  const researchPlan = await writeResearchPlan(researchDir, researchMission.prompt, {});
3910
3931
  if (researchPlan.methodology !== 'genius-scout-council-frontier-discovery-loop' || researchPlan.web_research_policy?.mode !== 'layered_source_retrieval_and_triangulation') throw new Error('selftest: research plan contract');
3932
+ if (!researchPlan.research_council?.scouts?.every((scout) => scout.display_name && scout.persona && scout.persona_boundary && scout.reasoning_effort === 'xhigh')) throw new Error('selftest: research scout persona contract missing from plan');
3911
3933
  const rArts = researchPlan.required_artifacts || [];
3912
3934
  for (const a of [rss, 'source-ledger.json', 'scout-ledger.json', 'debate-ledger.json', 'falsification-ledger.json']) if (!rArts.includes(a) || !(await exists(path.join(researchDir, a)))) throw new Error('selftest: research artifact');
3913
3935
  if (!rArts.includes('research-paper.md') || !rArts.includes(gos)) throw new Error('selftest: research paper');
@@ -3916,6 +3938,7 @@ async function selftest() {
3916
3938
  const researchGate = await writeMockResearchResult(researchDir, researchPlan);
3917
3939
  if (!researchGate.passed) throw new Error('selftest: mock research gate did not pass');
3918
3940
  const rm = researchGate.metrics || {};
3941
+ if (rm.scout_persona_contract_ok !== true || (rm.scout_persona_issues || []).length) throw new Error('selftest: research scout persona contract did not pass');
3919
3942
  if (['independent_scouts', 'xhigh_scouts', 'eureka_moments', 'debate_participants', 'genius_opinion_summaries'].some((m) => rm[m] < 5) || ['counterevidence_sources', 'falsification_cases', 'triangulation_checks'].some((m) => rm[m] < 1) || rm.paper_sections < 8 || rm.citation_coverage !== true || rm.source_layers_covered < 7) throw new Error('selftest: research metrics');
3920
3943
  await writeJsonAtomic(path.join(dir, 'done-gate.json'), { passed: true, unsupported_critical_claims: 0, database_safety_violation: false, database_safety_reviewed: true, visual_drift: 'low', wiki_drift: 'low', tests_required: false });
3921
3944
  const gate = await evaluateDoneGate(tmp, id);
@@ -0,0 +1,157 @@
1
+ import path from 'node:path';
2
+ import { readJson, sksRoot } from '../core/fsx.mjs';
3
+ import { findLatestMission, missionDir, stateFile } from '../core/mission.mjs';
4
+ import {
5
+ EVIDENCE_ENVELOPE_ARTIFACT,
6
+ MISSION_STATUS_LEDGER_ARTIFACT,
7
+ RECALLPULSE_DECISION_ARTIFACT,
8
+ RECALLPULSE_EVAL_ARTIFACT,
9
+ RECALLPULSE_GOVERNANCE_ARTIFACT,
10
+ RECALLPULSE_POLICY,
11
+ RECALLPULSE_TASK_GOAL_LEDGER_ARTIFACT,
12
+ RECALLPULSE_TASKS_FILE,
13
+ ROUTE_PROOF_CAPSULE_ARTIFACT,
14
+ buildRecallPulseGovernanceReport,
15
+ buildRecallPulseTaskGoalLedger,
16
+ completeRecallPulseTaskGoal,
17
+ evaluateRecallPulseFixtures,
18
+ readMissionStatusLedger,
19
+ writeRecallPulseArtifacts
20
+ } from '../core/recallpulse.mjs';
21
+
22
+ function flag(args, name) {
23
+ return args.includes(name);
24
+ }
25
+
26
+ export async function recallPulseCommand(sub = 'status', args = []) {
27
+ const root = await sksRoot();
28
+ const action = sub || 'status';
29
+ if (action === 'help' || action === '--help' || action === '-h') return help();
30
+ const missionArg = args.find((arg) => !String(arg).startsWith('--')) || 'latest';
31
+ const id = await resolveMissionId(root, missionArg);
32
+ if (!id) throw new Error('Usage: sks recallpulse run|status|eval|governance|checklist <mission-id|latest> [--json]');
33
+ const state = await readJson(stateFile(root), {});
34
+ if (action === 'run') {
35
+ const result = await writeRecallPulseArtifacts(root, { missionId: id, state, stageId: readOption(args, '--stage', null) });
36
+ if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
37
+ console.log('SKS RecallPulse report-only run\n');
38
+ printSummary(root, id, result.decision);
39
+ return;
40
+ }
41
+ if (action === 'status') {
42
+ const status = await recallPulseStatus(root, id);
43
+ if (flag(args, '--json')) return console.log(JSON.stringify(status, null, 2));
44
+ console.log('SKS RecallPulse status\n');
45
+ printSummary(root, id, status.decision);
46
+ console.log(`Status ledger: ${path.relative(root, path.join(missionDir(root, id), MISSION_STATUS_LEDGER_ARTIFACT))}${status.status_ledger ? '' : ' (missing)'}`);
47
+ console.log(`Proof capsule: ${path.relative(root, path.join(missionDir(root, id), ROUTE_PROOF_CAPSULE_ARTIFACT))}${status.route_proof_capsule ? '' : ' (missing)'}`);
48
+ console.log(`Evidence: ${path.relative(root, path.join(missionDir(root, id), EVIDENCE_ENVELOPE_ARTIFACT))}${status.evidence_envelope ? '' : ' (missing)'}`);
49
+ return;
50
+ }
51
+ if (action === 'eval') {
52
+ const report = await evaluateRecallPulseFixtures(root, { missionId: id, write: true });
53
+ if (flag(args, '--json')) return console.log(JSON.stringify(report, null, 2));
54
+ console.log('SKS RecallPulse fixture eval\n');
55
+ console.log(`Mission: ${id}`);
56
+ console.log(`Passed: ${report.passed ? 'yes' : 'no'}`);
57
+ console.log(`File: ${path.relative(root, path.join(missionDir(root, id), RECALLPULSE_EVAL_ARTIFACT))}`);
58
+ console.log(`Caveat: ${report.caveat}`);
59
+ return;
60
+ }
61
+ if (action === 'governance') {
62
+ const report = await buildRecallPulseGovernanceReport(root, { missionId: id, writeDecisions: !flag(args, '--no-samples') });
63
+ if (flag(args, '--json')) return console.log(JSON.stringify(report, null, 2));
64
+ console.log('SKS RecallPulse governance report\n');
65
+ console.log(`Mission: ${id}`);
66
+ console.log(`Routes inventoried: ${report.route_gate_inventory.length}`);
67
+ console.log(`Recorded samples: ${report.rollout.requested_samples.filter((sample) => sample.report_only_decision_recorded).length}/${report.rollout.requested_samples.length}`);
68
+ console.log(`Enforcement: ${report.shadow_eval.enforcement_decision}`);
69
+ console.log(`File: ${path.relative(root, path.join(missionDir(root, id), RECALLPULSE_GOVERNANCE_ARTIFACT))}`);
70
+ return;
71
+ }
72
+ if (action === 'checklist') {
73
+ const taskId = readOption(args, '--task', null) || readOption(args, '--id', null);
74
+ const apply = flag(args, '--apply');
75
+ if (taskId && apply) {
76
+ const result = await completeRecallPulseTaskGoal(root, id, taskId, {
77
+ allowOutOfOrder: flag(args, '--allow-out-of-order'),
78
+ evidence: readListOption(args, '--evidence'),
79
+ verification: readListOption(args, '--verification'),
80
+ notes: readOption(args, '--notes', '')
81
+ });
82
+ if (flag(args, '--json')) return console.log(JSON.stringify({ ok: true, applied: true, ...result }, null, 2));
83
+ console.log(`Checked ${result.task.task_id} as a child $Goal checkpoint.`);
84
+ console.log(`Ledger: ${path.relative(root, path.join(missionDir(root, id), RECALLPULSE_TASK_GOAL_LEDGER_ARTIFACT))}`);
85
+ return;
86
+ }
87
+ const ledger = await buildRecallPulseTaskGoalLedger(root, id);
88
+ const result = { ok: true, applied: false, file: path.join(root, RECALLPULSE_TASKS_FILE), ledger_file: path.join(root, '.sneakoscope', 'missions', id, RECALLPULSE_TASK_GOAL_LEDGER_ARTIFACT), next_task: ledger.next_task, counts: ledger.counts };
89
+ if (flag(args, '--json')) return console.log(JSON.stringify(result, null, 2));
90
+ console.log(`RecallPulse sequential task-goal ledger: ${ledger.counts.checked}/${ledger.counts.total} checked.`);
91
+ console.log(`Next: ${ledger.next_task?.id || 'none'} ${ledger.next_task?.title || ''}`.trim());
92
+ console.log(`Run only after evidence: sks recallpulse checklist ${id} --task ${ledger.next_task?.id || 'T001'} --apply --evidence <path>`);
93
+ return;
94
+ }
95
+ throw new Error(`Unknown recallpulse command: ${action}`);
96
+ }
97
+
98
+ async function recallPulseStatus(root, id) {
99
+ const dir = missionDir(root, id);
100
+ return {
101
+ mission_id: id,
102
+ policy: RECALLPULSE_POLICY,
103
+ decision: await readJson(path.join(dir, RECALLPULSE_DECISION_ARTIFACT), null),
104
+ status_ledger: await readMissionStatusLedger(root, id),
105
+ route_proof_capsule: await readJson(path.join(dir, ROUTE_PROOF_CAPSULE_ARTIFACT), null),
106
+ evidence_envelope: await readJson(path.join(dir, EVIDENCE_ENVELOPE_ARTIFACT), null),
107
+ eval_report: await readJson(path.join(dir, RECALLPULSE_EVAL_ARTIFACT), null)
108
+ };
109
+ }
110
+
111
+ function printSummary(root, id, decision) {
112
+ console.log(`Mission: ${id}`);
113
+ if (!decision) {
114
+ console.log(`Decision: missing (${path.relative(root, path.join(missionDir(root, id), RECALLPULSE_DECISION_ARTIFACT))})`);
115
+ console.log(`Run: sks recallpulse run ${id}`);
116
+ return;
117
+ }
118
+ console.log(`Decision: ${decision.recommended_action}`);
119
+ console.log(`Stage: ${decision.stage_id}`);
120
+ console.log(`L1: ${(decision.l1?.selected || []).map((item) => item.id).join(', ') || 'none'}`);
121
+ console.log(`L3: ${(decision.l3?.hydration_requests || []).length} hydration request(s)`);
122
+ console.log(`Status: ${decision.user_visible_status_projection?.message || 'report-only decision written'}`);
123
+ }
124
+
125
+ async function resolveMissionId(root, value = 'latest') {
126
+ if (!value || value === 'latest') return findLatestMission(root);
127
+ return value;
128
+ }
129
+
130
+ function readOption(args = [], name, fallback = null) {
131
+ const index = args.indexOf(name);
132
+ if (index < 0 || index + 1 >= args.length) return fallback;
133
+ return args[index + 1];
134
+ }
135
+
136
+ function readListOption(args = [], name) {
137
+ const values = [];
138
+ for (let i = 0; i < args.length; i += 1) {
139
+ if (args[i] === name && args[i + 1]) values.push(args[i + 1]);
140
+ }
141
+ return values;
142
+ }
143
+
144
+ function help() {
145
+ console.log(`SKS RecallPulse
146
+
147
+ Report-only active recall, durable status, RouteProofCapsule, and EvidenceEnvelope utilities.
148
+
149
+ Commands:
150
+ sks recallpulse run <mission-id|latest> [--json] [--stage before_final]
151
+ sks recallpulse status <mission-id|latest> [--json]
152
+ sks recallpulse eval <mission-id|latest> [--json]
153
+ sks recallpulse governance <mission-id|latest> [--json] [--no-samples]
154
+ sks recallpulse checklist <mission-id|latest> [--json]
155
+ sks recallpulse checklist <mission-id|latest> --task T001 --apply --evidence <path>
156
+ `);
157
+ }
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.78';
8
+ export const PACKAGE_VERSION = '0.8.0';
9
9
  export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
10
10
  export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
11
11
 
@@ -8,6 +8,7 @@ import { activeRouteContext, evaluateStop, prepareRoute, promptPipelineContext a
8
8
  import { classifyToolError } from './evaluation.mjs';
9
9
  import { REQUIRED_CODEX_MODEL, isForbiddenCodexModel } from './codex-model-guard.mjs';
10
10
  import { dollarCommand, stripVisibleDecisionAnswerBlocks } from './routes.mjs';
11
+ import { appendMissionStatus } from './recallpulse.mjs';
11
12
 
12
13
  const TEAM_DIGEST_MAX_EVENTS = 4;
13
14
  const TEAM_DIGEST_MESSAGE_CHARS = 180;
@@ -541,6 +542,18 @@ async function finalizationRepeatDecision(root, state = {}, payload = {}, reason
541
542
  }
542
543
  };
543
544
  await writeJsonAtomic(guardPath, record).catch(() => null);
545
+ if (state.mission_id) {
546
+ await appendMissionStatus(root, state.mission_id, {
547
+ category: repeatCount >= limit ? 'warning' : 'blocker',
548
+ audience: ['user', 'route', 'final-summary'],
549
+ stage_id: 'before_final',
550
+ message: repeatCount >= limit
551
+ ? `Repeated ${kind} stop prompt was suppressed; route completion is still unclaimed until evidence passes.`
552
+ : reason,
553
+ dedupe_key: key,
554
+ evidence: [STOP_REPEAT_GUARD_ARTIFACT]
555
+ }).catch(() => null);
556
+ }
544
557
  if (repeatCount < limit) return null;
545
558
  return {
546
559
  continue: true,
package/src/core/init.mjs CHANGED
@@ -874,7 +874,7 @@ export async function installSkills(root) {
874
874
  '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`,
875
875
  '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`,
876
876
  'goal': `---\nname: goal\ndescription: Fast $Goal/$goal bridge overlay for Codex native persisted /goal workflows.\n---\n\nUse when the user invokes $Goal/$goal or asks to persist a workflow with Codex native /goal continuation. Prepare with sks goal create or the $Goal route, write only the lightweight bridge artifacts, then use native Codex /goal create, pause, resume, and clear controls where available. Goal does not replace Team, QA, DB, or other SKS execution routes; continue implementation through the selected route and use Context7 only when external API/library docs are involved. Do not recreate the old no-question loop.\n`,
877
- 'research': `---\nname: research\ndescription: Dollar-command route for $Research or $research frontier discovery workflows.\n---\n\nUse when the user invokes $Research/$research or asks for research, hypotheses, new mechanisms, falsification, or testable predictions. Prefer sks research prepare and sks research run. Run the genius-lens scout council with Einstein/Feynman/Turing/von Neumann-inspired cognitive roles plus a skeptic lens; do not impersonate the historical people. Every Research scout must run with effort=xhigh, record one literal "Eureka!" idea, and participate in a vigorous evidence-bound debate before synthesis. Create research-source-skill.md as a route-local Skill Creator artifact, then maximize layered public web/source search across papers, official/government or leading-institution data, standards/primary docs, current news, public discourse, developer/practitioner sources, and counterevidence before synthesis. Record research-source-skill.md, source-ledger.json, scout-ledger.json, debate-ledger.json, novelty-ledger.json, falsification-ledger.json, research-report.md, research-paper.md, genius-opinion-summary.md, and research-gate.json. Context7 is optional and only needed when the research topic depends on external package/API/framework docs; do not use it as the default research evidence layer. Normal Research may take one or two hours when needed; favor real source collection, cross-layer comparison, falsification, and a concise paper manuscript over speed. Do not use --mock except for selftests or dry harness checks; if live source execution is unavailable, record a blocker and keep the gate unpassed. Do not use for ordinary code edits.\n`,
877
+ 'research': `---\nname: research\ndescription: Dollar-command route for $Research or $research frontier discovery workflows.\n---\n\nUse when the user invokes $Research/$research or asks for research, hypotheses, new mechanisms, falsification, or testable predictions. Prefer sks research prepare and sks research run. Run the genius-lens scout council with named persona-inspired cognitive roles: Einstein Scout, Feynman Scout, Turing Scout, von Neumann Scout, and Skeptic Scout. These are lenses only; do not impersonate the historical people. Every Research scout ledger row must include display_name, persona, persona_boundary, effort=xhigh, reasoning_effort=xhigh, service_tier when available, one literal "Eureka!" idea, falsifiers, cheap_probes, and challenge_or_response before synthesis. Create research-source-skill.md as a route-local Skill Creator artifact, then maximize layered public web/source search across papers, official/government or leading-institution data, standards/primary docs, current news, public discourse, developer/practitioner sources, and counterevidence before synthesis. Record research-source-skill.md, source-ledger.json, scout-ledger.json, debate-ledger.json, novelty-ledger.json, falsification-ledger.json, research-report.md, research-paper.md, genius-opinion-summary.md, and research-gate.json. Context7 is optional and only needed when the research topic depends on external package/API/framework docs; do not use it as the default research evidence layer. Normal Research may take one or two hours when needed; favor real source collection, cross-layer comparison, falsification, and a concise paper manuscript over speed. Do not use --mock except for selftests or dry harness checks; if live source execution is unavailable, record a blocker and keep the gate unpassed. Do not use for ordinary code edits.\n`,
878
878
  'autoresearch': `---\nname: autoresearch\ndescription: Dollar-command route for $AutoResearch or $autoresearch iterative experiment loops.\n---\n\nUse for $AutoResearch, iterative improvement, SEO/GEO, ranking, workflow, benchmark, or experiments. Define program, hypothesis, experiment, metric, keep/discard, falsification, next step, and Honest Mode. Load seo-geo-optimizer for README/npm/GitHub/schema/AI-search work.\n`,
879
879
  'db': `---\nname: db\ndescription: Dollar-command route for $DB or $db database and Supabase safety checks.\n---\n\nUse when the user invokes $DB/$db or the task touches SQL, Supabase, Postgres, migrations, Prisma, Drizzle, Knex, MCP database tools, or production data. Run or follow sks db policy, sks db scan, sks db classify, and sks db check. Destructive database operations remain forbidden.\n`,
880
880
  '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`,
@@ -896,7 +896,7 @@ export async function installSkills(root) {
896
896
  'gx-visual-read': `---\nname: gx-visual-read\ndescription: Read a Sneakoscope Codex deterministic visual sheet and produce context notes.\n---\n\nExtract nodes, edges, invariants, tests, risks, uncertainties, and RGBA anchors from source/render/snapshot. Do not infer hidden nodes.\n`,
897
897
  'gx-visual-validate': `---\nname: gx-visual-validate\ndescription: Validate render metadata against vgraph.json and beta.json.\n---\n\nRun sks gx validate and drift; fail stale or incomplete hashes, nodes, edges, invariants, or anchors.\n`,
898
898
  'turbo-context-pack': `---\nname: turbo-context-pack\ndescription: Build ultra-low-token context packet with Q4 bits, Q3 tags, top-K claims, and minimal evidence.\n---\n\nDefault to Q4/Q3 plus TriWiki RGBA anchors and attention.use_first. Add Q2/Q1 only when needed or when attention.hydrate_first says source hydration is required. Keep id, hash, path, and coordinate tuple for hydration.\n`,
899
- 'research-discovery': `---\nname: research-discovery\ndescription: Run SKS Research Mode for frontier-style research, hypotheses, novelty ledgers, falsification, and experiments.\n---\n\nFrame criteria, map assumptions, run maximum available web/source search, generate xhigh scout findings through Einstein/Feynman/Turing/von Neumann-inspired lenses plus a skeptic lens, require each scout to record a literal "Eureka!" idea, run evidence-bound debate, falsify, keep surviving insights, and record source ids, novelty/confidence/falsifiers/next experiments. Do not overclaim.\n`,
899
+ 'research-discovery': `---\nname: research-discovery\ndescription: Run SKS Research Mode for frontier-style research, hypotheses, novelty ledgers, falsification, and experiments.\n---\n\nFrame criteria, map assumptions, run maximum available web/source search, generate xhigh scout findings through Einstein Scout, Feynman Scout, Turing Scout, von Neumann Scout, and Skeptic Scout persona-inspired lenses, require each scout to record display_name/persona/persona_boundary plus a literal "Eureka!" idea, run evidence-bound debate, falsify, keep surviving insights, and record source ids, novelty/confidence/falsifiers/next experiments. Do not impersonate historical people and do not overclaim.\n`,
900
900
  'performance-evaluator': `---\nname: performance-evaluator\ndescription: Evaluate SKS performance, token-saving, accuracy-proxy, context-compression, or workflow improvements.\n---\n\nUse sks eval run/compare before claims. Report token_savings_pct, accuracy_delta/proxy, required_recall, support, and meaningful_improvement.\n`,
901
901
  'image-ux-review': imageUxReviewSkill('image-ux-review'),
902
902
  'ux-review': imageUxReviewSkill('ux-review'),