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 +26 -1
- package/package.json +1 -1
- package/src/cli/main.mjs +24 -1
- package/src/cli/recallpulse-command.mjs +157 -0
- package/src/core/fsx.mjs +1 -1
- package/src/core/hooks-runtime.mjs +13 -0
- package/src/core/init.mjs +2 -2
- package/src/core/recallpulse.mjs +1215 -0
- package/src/core/research.mjs +35 -46
- package/src/core/routes.mjs +2 -1
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.
|
|
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.
|
|
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
|
|
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
|
|
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'),
|