sneakoscope 0.9.13 → 0.9.14
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 +30 -39
- package/crates/sks-core/Cargo.lock +99 -1
- package/crates/sks-core/Cargo.toml +2 -1
- package/crates/sks-core/src/main.rs +77 -43
- package/package.json +8 -5
- package/src/cli/command-registry.mjs +73 -114
- package/src/cli/feature-commands.mjs +44 -5
- package/src/cli/install-helpers.mjs +2 -2
- package/src/cli/router.mjs +2 -3
- package/src/commands/aliases.mjs +2 -0
- package/src/commands/auto-review.mjs +5 -0
- package/src/commands/autoresearch.mjs +5 -0
- package/src/commands/bootstrap.mjs +2 -0
- package/src/commands/code-structure.mjs +5 -0
- package/src/commands/codex-lb.mjs +61 -3
- package/src/commands/commands.mjs +5 -0
- package/src/commands/commit-and-push.mjs +5 -0
- package/src/commands/commit.mjs +5 -0
- package/src/commands/computer-use.mjs +31 -0
- package/src/commands/conflicts.mjs +13 -0
- package/src/commands/context7.mjs +5 -0
- package/src/commands/db.mjs +1 -1
- package/src/commands/deps.mjs +5 -0
- package/src/commands/dfix.mjs +2 -0
- package/src/commands/doctor.mjs +2 -2
- package/src/commands/dollar-commands.mjs +2 -0
- package/src/commands/eval.mjs +5 -0
- package/src/commands/fix-path.mjs +2 -0
- package/src/commands/gc.mjs +2 -0
- package/src/commands/goal.mjs +5 -0
- package/src/commands/guard.mjs +10 -0
- package/src/commands/gx.mjs +5 -0
- package/src/commands/harness.mjs +5 -0
- package/src/commands/help.mjs +3 -74
- package/src/commands/hook.mjs +8 -0
- package/src/commands/hproof.mjs +5 -0
- package/src/commands/image-ux-review.mjs +38 -0
- package/src/commands/init.mjs +2 -0
- package/src/commands/mad-sks.mjs +14 -0
- package/src/commands/memory.mjs +5 -0
- package/src/commands/openclaw.mjs +2 -0
- package/src/commands/perf.mjs +2 -2
- package/src/commands/pipeline.mjs +25 -0
- package/src/commands/postinstall.mjs +2 -0
- package/src/commands/ppt.mjs +44 -0
- package/src/commands/profile.mjs +5 -0
- package/src/commands/proof-field.mjs +5 -0
- package/src/commands/proof.mjs +22 -1
- package/src/commands/qa-loop.mjs +5 -0
- package/src/commands/quickstart.mjs +2 -0
- package/src/commands/reasoning.mjs +2 -0
- package/src/commands/recallpulse.mjs +5 -0
- package/src/commands/research.mjs +5 -0
- package/src/commands/selftest.mjs +2 -0
- package/src/commands/setup.mjs +2 -0
- package/src/commands/skill-dream.mjs +5 -0
- package/src/commands/stats.mjs +2 -0
- package/src/commands/team.mjs +2 -0
- package/src/commands/tmux.mjs +5 -0
- package/src/commands/update-check.mjs +2 -0
- package/src/commands/usage.mjs +2 -0
- package/src/commands/validate-artifacts.mjs +2 -0
- package/src/commands/versioning.mjs +16 -0
- package/src/commands/wiki.mjs +2 -2
- package/src/core/codex-lb-circuit.mjs +18 -0
- package/src/core/commands/basic-cli.mjs +315 -0
- package/src/{cli/maintenance-commands.mjs → core/commands/route-cli.mjs} +37 -37
- package/src/core/feature-fixture-runner.mjs +109 -0
- package/src/core/feature-fixtures.mjs +1 -1
- package/src/core/feature-registry.mjs +19 -7
- package/src/core/fsx.mjs +1 -1
- package/src/core/git-simple.mjs +118 -0
- package/src/core/pipeline.mjs +1 -1
- package/src/core/proof/route-finalizer-fixtures.mjs +21 -0
- package/src/core/proof/route-finalizer-policy.mjs +13 -0
- package/src/core/proof/route-finalizer.mjs +82 -0
- package/src/core/proof-field.mjs +2 -2
- package/src/core/routes.mjs +31 -1
- package/src/core/rust-accelerator.mjs +8 -3
- package/src/core/version.mjs +1 -1
- package/src/core/wiki-image/before-after-relation.mjs +1 -0
- package/src/core/wiki-image/computer-use-evidence.mjs +1 -0
- package/src/core/wiki-image/generated-review-parser.mjs +1 -0
- package/src/core/wiki-image/image-ux-evidence.mjs +1 -0
- package/src/core/wiki-image/image-voxel-ledger.mjs +10 -3
- package/src/core/wiki-image/ppt-image-evidence.mjs +1 -0
- package/src/core/wiki-image/route-image-evidence.mjs +107 -0
- package/src/cli/legacy-main.mjs +0 -4147
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { projectRoot, readJson, writeJsonAtomic } from '../core/fsx.mjs';
|
|
3
|
+
import { findLatestMission, loadMission } from '../core/mission.mjs';
|
|
4
|
+
import { flag } from '../cli/args.mjs';
|
|
5
|
+
import { printJson } from '../cli/output.mjs';
|
|
6
|
+
import { writePptBuildArtifacts, writePptRouteArtifacts } from '../core/ppt.mjs';
|
|
7
|
+
import { finalizeRouteWithProof } from '../core/proof/route-finalizer.mjs';
|
|
8
|
+
|
|
9
|
+
export async function run(_command, args = []) {
|
|
10
|
+
const root = await projectRoot();
|
|
11
|
+
const action = args[0] || 'status';
|
|
12
|
+
const missionArg = args[1] && !String(args[1]).startsWith('--') ? args[1] : 'latest';
|
|
13
|
+
const missionId = missionArg === 'latest' ? await findLatestMission(root) : missionArg;
|
|
14
|
+
if (!missionId) {
|
|
15
|
+
const result = { schema: 'sks.ppt-status.v1', ok: false, status: 'missing_mission' };
|
|
16
|
+
if (flag(args, '--json')) return printJson(result);
|
|
17
|
+
console.error('No mission found.');
|
|
18
|
+
process.exitCode = 1;
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const { dir, mission } = await loadMission(root, missionId);
|
|
22
|
+
const contract = await readJson(path.join(dir, 'decision-contract.json'), { prompt: mission.prompt, answers: {}, sealed_hash: null });
|
|
23
|
+
if (action === 'build') {
|
|
24
|
+
await writePptRouteArtifacts(dir, contract);
|
|
25
|
+
const build = await writePptBuildArtifacts(dir, contract);
|
|
26
|
+
const proof = await finalizeRouteWithProof(root, { missionId, route: '$PPT', mock: flag(args, '--mock'), artifacts: build.files || [], claims: [{ id: 'ppt-build-fixture', status: 'verified_partial' }] });
|
|
27
|
+
const result = { schema: 'sks.ppt-build.v1', ok: proof.ok, mission_id: missionId, build, proof: proof.validation };
|
|
28
|
+
if (flag(args, '--json')) return printJson(result);
|
|
29
|
+
console.log(`PPT build: ${proof.ok ? 'ok' : 'blocked'} ${missionId}`);
|
|
30
|
+
if (!proof.ok) process.exitCode = 1;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (action === 'status') {
|
|
34
|
+
const gate = await readJson(path.join(dir, 'ppt-gate.json'), null);
|
|
35
|
+
const result = { schema: 'sks.ppt-status.v1', ok: true, mission_id: missionId, gate };
|
|
36
|
+
if (flag(args, '--json')) return printJson(result);
|
|
37
|
+
console.log(`PPT mission: ${missionId}`);
|
|
38
|
+
console.log(`Gate: ${gate?.passed ? 'passed' : gate ? 'present' : 'missing'}`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
await writeJsonAtomic(path.join(dir, 'ppt-command-error.json'), { action, args });
|
|
42
|
+
console.error('Usage: sks ppt build|status <mission-id|latest> [--json] [--mock]');
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
}
|
package/src/commands/proof.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { collectProofEvidence } from '../core/proof/evidence-collector.mjs';
|
|
|
5
5
|
import { findLatestMission } from '../core/mission.mjs';
|
|
6
6
|
import { readLatestProof, readLatestProofMarkdown, readRouteProof } from '../core/proof/proof-reader.mjs';
|
|
7
7
|
import { writeRouteCompletionProof } from '../core/proof/route-adapter.mjs';
|
|
8
|
+
import { finalizeRouteWithProof } from '../core/proof/route-finalizer.mjs';
|
|
8
9
|
import { renderProofMarkdown, writeCompletionProof } from '../core/proof/proof-writer.mjs';
|
|
9
10
|
import { validateCompletionProof } from '../core/proof/validation.mjs';
|
|
10
11
|
|
|
@@ -41,6 +42,26 @@ export async function run(_command, args = []) {
|
|
|
41
42
|
if (!result.ok) process.exitCode = 1;
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
45
|
+
if (action === 'finalize') {
|
|
46
|
+
const missionArg = rest.find((arg) => !String(arg).startsWith('--')) || 'latest';
|
|
47
|
+
const missionId = missionArg === 'latest' ? await findLatestMission(root) : missionArg;
|
|
48
|
+
const routeIndex = args.indexOf('--route');
|
|
49
|
+
const route = routeIndex >= 0 && args[routeIndex + 1] ? args[routeIndex + 1] : '$SKS';
|
|
50
|
+
const result = await finalizeRouteWithProof(root, {
|
|
51
|
+
missionId,
|
|
52
|
+
route,
|
|
53
|
+
strict: flag(args, '--strict'),
|
|
54
|
+
mock: flag(args, '--mock'),
|
|
55
|
+
requireRelation: flag(args, '--require-relation'),
|
|
56
|
+
statusHint: flag(args, '--strict') ? 'verified_partial' : 'verified_partial',
|
|
57
|
+
claims: [{ id: 'proof-finalize', status: 'supported', evidence: `.sneakoscope/missions/${missionId}/completion-proof.json` }],
|
|
58
|
+
unverified: flag(args, '--mock') ? ['Finalizer ran in mock fixture mode.'] : []
|
|
59
|
+
});
|
|
60
|
+
if (flag(args, '--json')) return printJson({ schema: 'sks.completion-proof-finalize.v1', ok: result.ok, mission_id: missionId, validation: result.validation, files: result.files, proof: result.proof });
|
|
61
|
+
console.log(`Completion proof finalized: ${result.files.latest_json}`);
|
|
62
|
+
if (!result.ok) process.exitCode = 1;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
44
65
|
if (action === 'export' && (flag(rest, '--md') || flag(args, '--md'))) {
|
|
45
66
|
process.stdout.write(await readLatestProofMarkdown(root));
|
|
46
67
|
return;
|
|
@@ -86,7 +107,7 @@ export async function run(_command, args = []) {
|
|
|
86
107
|
console.log(`Completion proof written: ${result.files.latest_json}`);
|
|
87
108
|
return;
|
|
88
109
|
}
|
|
89
|
-
console.error('Usage: sks proof show|latest|validate|route <mission-id|latest>|export --md|repair latest|smoke [--json]');
|
|
110
|
+
console.error('Usage: sks proof show|latest|validate|route <mission-id|latest>|finalize <mission-id|latest> [--route route] [--strict] [--mock] [--json]|export --md|repair latest|smoke [--json]');
|
|
90
111
|
process.exitCode = 1;
|
|
91
112
|
}
|
|
92
113
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { projectRoot } from '../core/fsx.mjs';
|
|
2
|
+
import { bumpProjectVersion, disableVersionGitHook, versioningStatus } from '../core/version-manager.mjs';
|
|
3
|
+
import { flag } from '../cli/args.mjs';
|
|
4
|
+
import { printJson } from '../cli/output.mjs';
|
|
5
|
+
export async function run(_command, args = []) {
|
|
6
|
+
const root = await projectRoot();
|
|
7
|
+
const action = args[0] || 'status';
|
|
8
|
+
const result = action === 'bump'
|
|
9
|
+
? await bumpProjectVersion(root, { force: true })
|
|
10
|
+
: ['disable', 'off', 'remove-hook', 'unhook'].includes(action)
|
|
11
|
+
? await disableVersionGitHook(root)
|
|
12
|
+
: await versioningStatus(root);
|
|
13
|
+
if (flag(args, '--json')) return printJson(result);
|
|
14
|
+
console.log(JSON.stringify(result, null, 2));
|
|
15
|
+
if (result.ok === false) process.exitCode = 1;
|
|
16
|
+
}
|
package/src/commands/wiki.mjs
CHANGED
|
@@ -85,8 +85,8 @@ export async function run(_command, args = []) {
|
|
|
85
85
|
if (!result.ok) process.exitCode = 1;
|
|
86
86
|
return;
|
|
87
87
|
}
|
|
88
|
-
const
|
|
89
|
-
return
|
|
88
|
+
const { wikiCommand } = await import('../core/commands/route-cli.mjs');
|
|
89
|
+
return wikiCommand(action, args.slice(1));
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
function parseBbox(raw) {
|
|
@@ -99,6 +99,24 @@ export function codexLbMetrics(circuit = emptyCircuit()) {
|
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
export async function codexLbProofEvidence(root = packageRoot()) {
|
|
103
|
+
const circuit = await readCodexLbCircuit(root);
|
|
104
|
+
const metrics = codexLbMetrics(circuit);
|
|
105
|
+
return {
|
|
106
|
+
schema: 'sks.codex-lb-proof-evidence.v1',
|
|
107
|
+
ok: metrics.ok,
|
|
108
|
+
status: circuit.state === 'open' ? 'blocked' : 'verified_partial',
|
|
109
|
+
circuit_state: circuit.state,
|
|
110
|
+
report_path: codexLbReportPath(root),
|
|
111
|
+
last_ok_at: circuit.last_ok_at,
|
|
112
|
+
last_failure_at: circuit.last_failure_at,
|
|
113
|
+
last_warning_at: circuit.last_warning_at,
|
|
114
|
+
recent_failures: circuit.recent_failures?.length || 0,
|
|
115
|
+
recent_warnings: circuit.recent_warnings?.length || 0,
|
|
116
|
+
policy: metrics.policy
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
102
120
|
function emptyCircuit() {
|
|
103
121
|
return {
|
|
104
122
|
schema: CODEX_LB_CIRCUIT_SCHEMA,
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { COMMANDS } from '../../cli/command-registry.mjs';
|
|
4
|
+
import { flag } from '../../cli/args.mjs';
|
|
5
|
+
import { printJson, sksTextLogo } from '../../cli/output.mjs';
|
|
6
|
+
import { PACKAGE_VERSION, ensureDir, exists, nowIso, projectRoot, readJson, runProcess, sksRoot, tmpdir, writeJsonAtomic } from '../fsx.mjs';
|
|
7
|
+
import { COMMAND_CATALOG, DOLLAR_COMMAND_ALIASES, DOLLAR_COMMANDS, USAGE_TOPICS, routePrompt, routeReasoning, reasoningInstruction } from '../routes.mjs';
|
|
8
|
+
import { initProject, normalizeInstallScope, sksCommandPrefix } from '../init.mjs';
|
|
9
|
+
import { buildFeatureRegistry, validateFeatureRegistry } from '../feature-registry.mjs';
|
|
10
|
+
import { hooksExplainReport } from '../../cli/feature-commands.mjs';
|
|
11
|
+
import { writeSelftestRouteProof } from '../proof/selftest-proof-fixtures.mjs';
|
|
12
|
+
import { createMission } from '../mission.mjs';
|
|
13
|
+
|
|
14
|
+
export async function helpCommand(args = []) {
|
|
15
|
+
const topic = args[0];
|
|
16
|
+
if (topic) return usageCommand([topic]);
|
|
17
|
+
console.log(`${sksTextLogo()}\n\nUsage\n`);
|
|
18
|
+
console.log(' sks');
|
|
19
|
+
console.log(' sks help [topic]');
|
|
20
|
+
console.log(' sks commands [--json]');
|
|
21
|
+
console.log(' sks dollar-commands [--json]');
|
|
22
|
+
console.log(' sks proof show --json');
|
|
23
|
+
console.log('');
|
|
24
|
+
for (const row of commandRows().filter((entry) => entry.maturity !== 'labs')) {
|
|
25
|
+
console.log(` ${row.usage.padEnd(58)} ${row.description}`);
|
|
26
|
+
}
|
|
27
|
+
console.log('\nThree core promises: Completion Proof for serious routes, Image Voxel TriWiki for visual routes, and release-gated Codex App/codex-lb/hooks/Rust evidence.');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function commandsCommand(args = []) {
|
|
31
|
+
const commands = commandRows();
|
|
32
|
+
if (flag(args, '--json')) {
|
|
33
|
+
return printJson({
|
|
34
|
+
schema: 'sks.command-registry.v1',
|
|
35
|
+
aliases: ['sks', 'sneakoscope'],
|
|
36
|
+
commands
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
console.log(`${sksTextLogo()}\n\nCommands\n`);
|
|
40
|
+
const width = Math.max(...commands.map((entry) => entry.usage.length));
|
|
41
|
+
for (const entry of commands) console.log(`${entry.usage.padEnd(width)} ${entry.description}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function dollarCommandsCommand(args = []) {
|
|
45
|
+
const out = { dollar_commands: DOLLAR_COMMANDS, app_skill_aliases: DOLLAR_COMMAND_ALIASES };
|
|
46
|
+
if (flag(args, '--json')) return printJson(out);
|
|
47
|
+
console.log(`${sksTextLogo()}\n\n$ Commands\n`);
|
|
48
|
+
const width = Math.max(...DOLLAR_COMMANDS.map((entry) => entry.command.length));
|
|
49
|
+
for (const entry of DOLLAR_COMMANDS) console.log(`${entry.command.padEnd(width)} ${entry.route}: ${entry.description}`);
|
|
50
|
+
console.log(`\nCanonical Codex App picker skills: ${DOLLAR_COMMAND_ALIASES.map((entry) => entry.app_skill).join(', ')}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function aliasesCommand() {
|
|
54
|
+
console.log('Aliases');
|
|
55
|
+
console.log('- sks, sneakoscope');
|
|
56
|
+
console.log('- $ aliases:');
|
|
57
|
+
for (const entry of DOLLAR_COMMAND_ALIASES) console.log(` ${entry.app_skill} -> ${entry.canonical}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function dfixCommand() {
|
|
61
|
+
console.log(`SKS Direct Fix Mode
|
|
62
|
+
|
|
63
|
+
Prompt command:
|
|
64
|
+
$DFix <tiny direct fix request>
|
|
65
|
+
|
|
66
|
+
Rules:
|
|
67
|
+
Apply only the requested tiny copy/config/docs/labels/spacing/translation/simple mechanical edit.
|
|
68
|
+
Keep verification cheap and explicit.
|
|
69
|
+
Finish with a DFix completion summary and one Honest check line.`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function usageCommand(args = []) {
|
|
73
|
+
const topic = args[0] || 'overview';
|
|
74
|
+
if (topic === 'overview') {
|
|
75
|
+
console.log(`Usage topics: ${USAGE_TOPICS}`);
|
|
76
|
+
console.log('Try: sks usage goal, sks usage team, sks usage image-ux-review');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const row = commandRows().find((entry) => entry.name === topic);
|
|
80
|
+
if (row) {
|
|
81
|
+
console.log(`${row.name}\n`);
|
|
82
|
+
console.log(`Usage: ${row.usage}`);
|
|
83
|
+
console.log(row.description);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const route = DOLLAR_COMMANDS.find((entry) => entry.command.toLowerCase() === `$${topic}`.toLowerCase());
|
|
87
|
+
if (route) {
|
|
88
|
+
console.log(`${route.command}\n`);
|
|
89
|
+
console.log(`${route.route}: ${route.description}`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
console.log(`Unknown usage topic: ${topic}`);
|
|
93
|
+
console.log(`Known topics: ${USAGE_TOPICS}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function quickstartCommand() {
|
|
97
|
+
console.log(`Sneakoscope Codex Quickstart
|
|
98
|
+
|
|
99
|
+
sks setup --local-only
|
|
100
|
+
sks doctor
|
|
101
|
+
sks commands
|
|
102
|
+
sks dollar-commands
|
|
103
|
+
sks all-features selftest --mock --execute-fixtures --strict-artifacts --json
|
|
104
|
+
|
|
105
|
+
For implementation work, use Codex App prompt routes such as $Team, $Goal, $QA-LOOP, $Image-UX-Review, and $Computer-Use.`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function updateCheckCommand(args = []) {
|
|
109
|
+
const latest = await npmViewVersion('sneakoscope');
|
|
110
|
+
const result = {
|
|
111
|
+
package: 'sneakoscope',
|
|
112
|
+
current: PACKAGE_VERSION,
|
|
113
|
+
runtime_current: PACKAGE_VERSION,
|
|
114
|
+
latest: latest.version,
|
|
115
|
+
update_available: latest.version ? compareVersions(latest.version, PACKAGE_VERSION) > 0 : false,
|
|
116
|
+
error: latest.error || null
|
|
117
|
+
};
|
|
118
|
+
if (flag(args, '--json')) return printJson(result);
|
|
119
|
+
console.log(`${sksTextLogo()}\n\nUpdate Check`);
|
|
120
|
+
console.log(`Current: ${result.current}`);
|
|
121
|
+
console.log(`Latest: ${result.latest || 'unknown'}`);
|
|
122
|
+
console.log(`Update: ${result.update_available ? 'available' : 'not needed'}`);
|
|
123
|
+
if (result.error) console.log(`Error: ${result.error}`);
|
|
124
|
+
if (result.update_available) console.log(`Run: npm i -g sneakoscope@${result.latest}`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export async function setupCommand(args = []) {
|
|
128
|
+
const root = await projectRoot();
|
|
129
|
+
const installScope = installScopeFromArgs(args);
|
|
130
|
+
const res = await initProject(root, {
|
|
131
|
+
force: flag(args, '--force'),
|
|
132
|
+
installScope,
|
|
133
|
+
localOnly: flag(args, '--local-only'),
|
|
134
|
+
globalCommand: 'sks'
|
|
135
|
+
});
|
|
136
|
+
const result = {
|
|
137
|
+
schema: 'sks.setup.v1',
|
|
138
|
+
ok: true,
|
|
139
|
+
root,
|
|
140
|
+
install_scope: installScope,
|
|
141
|
+
command_prefix: sksCommandPrefix(installScope, { globalCommand: 'sks' }),
|
|
142
|
+
created: res.created || [],
|
|
143
|
+
local_only: flag(args, '--local-only')
|
|
144
|
+
};
|
|
145
|
+
if (flag(args, '--json')) return printJson(result);
|
|
146
|
+
console.log(`Setup complete: ${root}`);
|
|
147
|
+
console.log(`Install scope: ${installScope}`);
|
|
148
|
+
for (const file of result.created) console.log(`- ${file}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export async function bootstrapCommand(args = []) {
|
|
152
|
+
return setupCommand(['--local-only', ...args]);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export async function initCommand(args = []) {
|
|
156
|
+
return setupCommand(args);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export async function fixPathCommand(args = []) {
|
|
160
|
+
const root = await projectRoot();
|
|
161
|
+
const installScope = installScopeFromArgs(args);
|
|
162
|
+
await initProject(root, { installScope, localOnly: flag(args, '--local-only'), globalCommand: 'sks', force: true });
|
|
163
|
+
const result = {
|
|
164
|
+
schema: 'sks.fix-path.v1',
|
|
165
|
+
ok: true,
|
|
166
|
+
root,
|
|
167
|
+
install_scope: installScope,
|
|
168
|
+
hook_command_prefix: sksCommandPrefix(installScope, { globalCommand: 'sks' }),
|
|
169
|
+
hooks: path.join(root, '.codex', 'hooks.json')
|
|
170
|
+
};
|
|
171
|
+
if (flag(args, '--json')) return printJson(result);
|
|
172
|
+
console.log(`SKS hook path refreshed: ${path.relative(root, result.hooks)}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export async function depsCommand(sub = 'check', args = []) {
|
|
176
|
+
const action = sub || 'check';
|
|
177
|
+
if (action !== 'check' && action !== 'status') {
|
|
178
|
+
console.error('Usage: sks deps check [--json]');
|
|
179
|
+
process.exitCode = 1;
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const npm = whichSync('npm');
|
|
183
|
+
const nodeOk = Number(process.versions.node.split('.')[0]) >= 20;
|
|
184
|
+
const root = await sksRoot();
|
|
185
|
+
const result = {
|
|
186
|
+
schema: 'sks.deps-status.v1',
|
|
187
|
+
root,
|
|
188
|
+
ready: Boolean(nodeOk && npm),
|
|
189
|
+
node: { ok: nodeOk, version: process.version },
|
|
190
|
+
npm: { ok: Boolean(npm), bin: npm },
|
|
191
|
+
next_actions: [
|
|
192
|
+
...(!nodeOk ? ['Install Node.js 20.11+.'] : []),
|
|
193
|
+
...(!npm ? ['Install npm or a Node.js distribution that includes npm.'] : [])
|
|
194
|
+
]
|
|
195
|
+
};
|
|
196
|
+
if (flag(args, '--json')) return printJson(result);
|
|
197
|
+
console.log('SKS Dependencies');
|
|
198
|
+
console.log(`Node: ${result.node.ok ? 'ok' : 'missing'} ${result.node.version}`);
|
|
199
|
+
console.log(`npm: ${result.npm.ok ? 'ok' : 'missing'} ${result.npm.bin || ''}`.trim());
|
|
200
|
+
if (!result.ready) process.exitCode = 1;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export async function postinstallCommand(args = []) {
|
|
204
|
+
const { postinstall } = await import('../../cli/install-helpers.mjs');
|
|
205
|
+
return postinstall({ bootstrap: flag(args, '--bootstrap') });
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export async function selftestCommand(args = []) {
|
|
209
|
+
process.env.CI = 'true';
|
|
210
|
+
const root = await projectRoot();
|
|
211
|
+
const tmp = tmpdir();
|
|
212
|
+
await ensureDir(tmp);
|
|
213
|
+
const registry = await buildFeatureRegistry({ root });
|
|
214
|
+
const coverage = validateFeatureRegistry(registry);
|
|
215
|
+
if (!coverage.ok) throw new Error(`selftest: feature registry blocked: ${coverage.blockers.join(', ')}`);
|
|
216
|
+
const mission = await createMission(tmp, { mode: 'team', prompt: 'selftest route proof fixture' });
|
|
217
|
+
await writeSelftestRouteProof(tmp, { missionId: mission.id, kind: 'team_gate' });
|
|
218
|
+
const proof = await readJson(path.join(tmp, '.sneakoscope', 'missions', mission.id, 'completion-proof.json'), null);
|
|
219
|
+
if (!proof?.mission_id) throw new Error('selftest: completion proof fixture missing');
|
|
220
|
+
const hookExplain = hooksExplainReport();
|
|
221
|
+
if (!hookExplain.events.includes('Stop')) throw new Error('selftest: hook explain missing Stop');
|
|
222
|
+
const result = {
|
|
223
|
+
schema: 'sks.selftest.v1',
|
|
224
|
+
ok: true,
|
|
225
|
+
version: PACKAGE_VERSION,
|
|
226
|
+
generated_at: nowIso(),
|
|
227
|
+
checks: ['feature_registry', 'route_completion_proof_fixture', 'hooks_policy_surface'],
|
|
228
|
+
tmp_root: tmp
|
|
229
|
+
};
|
|
230
|
+
if (flag(args, '--json')) return printJson(result);
|
|
231
|
+
console.log('SKS selftest passed');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export async function reasoningCommand(args = []) {
|
|
235
|
+
const prompt = args.filter((arg) => !String(arg).startsWith('--')).join(' ').trim();
|
|
236
|
+
const route = routePrompt(prompt || '$SKS');
|
|
237
|
+
const info = routeReasoning(route, prompt);
|
|
238
|
+
const result = {
|
|
239
|
+
route: route?.command || '$SKS',
|
|
240
|
+
effort: info.effort,
|
|
241
|
+
profile: info.profile,
|
|
242
|
+
reason: info.reason,
|
|
243
|
+
temporary: true,
|
|
244
|
+
instruction: reasoningInstruction(info)
|
|
245
|
+
};
|
|
246
|
+
if (flag(args, '--json')) return printJson(result);
|
|
247
|
+
console.log('SKS Reasoning Route');
|
|
248
|
+
console.log(`Route: ${result.route}`);
|
|
249
|
+
console.log(`Effort: ${result.effort}`);
|
|
250
|
+
console.log(`Profile: ${result.profile}`);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export async function tmuxCommand(sub = 'check', args = []) {
|
|
254
|
+
const { runTmuxStatus, tmuxReadiness } = await import('../tmux-ui.mjs');
|
|
255
|
+
const action = sub || 'check';
|
|
256
|
+
if (action === 'status' || action === 'banner') return runTmuxStatus(action === 'banner' ? ['--once', ...args] : args);
|
|
257
|
+
const status = await tmuxReadiness().catch((err) => ({ ok: false, error: err.message }));
|
|
258
|
+
if (flag(args, '--json')) return printJson({ schema: 'sks.tmux-status.v1', ...status });
|
|
259
|
+
console.log(`tmux: ${status.ok ? 'ok' : 'missing'} ${status.version || status.error || ''}`.trim());
|
|
260
|
+
if (!status.ok) process.exitCode = 1;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export async function autoReviewCommand(sub = 'status', args = []) {
|
|
264
|
+
const { autoReviewStatus, enableAutoReview, disableAutoReview } = await import('../auto-review.mjs');
|
|
265
|
+
const action = sub || 'status';
|
|
266
|
+
const result = action === 'enable' || action === 'start'
|
|
267
|
+
? await enableAutoReview({ high: flag(args, '--high') })
|
|
268
|
+
: action === 'disable'
|
|
269
|
+
? await disableAutoReview()
|
|
270
|
+
: await autoReviewStatus();
|
|
271
|
+
if (flag(args, '--json')) return printJson(result);
|
|
272
|
+
console.log(JSON.stringify(result, null, 2));
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function commandRows() {
|
|
276
|
+
const registry = new Map(Object.entries(COMMANDS).map(([name, meta]) => [name, meta]));
|
|
277
|
+
return COMMAND_CATALOG.map((entry) => ({
|
|
278
|
+
name: entry.name,
|
|
279
|
+
usage: entry.usage,
|
|
280
|
+
description: entry.description,
|
|
281
|
+
maturity: registry.get(entry.name)?.maturity || entry.maturity || 'labs'
|
|
282
|
+
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function installScopeFromArgs(args = [], fallback = 'global') {
|
|
286
|
+
if (flag(args, '--project')) return 'project';
|
|
287
|
+
if (flag(args, '--global')) return 'global';
|
|
288
|
+
const index = args.indexOf('--install-scope');
|
|
289
|
+
return normalizeInstallScope(index >= 0 && args[index + 1] ? args[index + 1] : fallback);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async function npmViewVersion(name) {
|
|
293
|
+
const npm = whichSync('npm');
|
|
294
|
+
if (!npm) return { version: null, error: 'npm not found on PATH' };
|
|
295
|
+
const result = await runProcess(npm, ['view', name, 'version', '--silent'], { timeoutMs: 15000, maxOutputBytes: 4096 }).catch((err) => ({ code: 1, stdout: '', stderr: err.message }));
|
|
296
|
+
if (result.code !== 0) return { version: null, error: (result.stderr || result.stdout || 'npm view failed').trim() };
|
|
297
|
+
return { version: String(result.stdout || '').trim().split(/\s+/).pop() || null };
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function compareVersions(a, b) {
|
|
301
|
+
const pa = String(a || '').split('.').map((x) => Number.parseInt(x, 10) || 0);
|
|
302
|
+
const pb = String(b || '').split('.').map((x) => Number.parseInt(x, 10) || 0);
|
|
303
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i += 1) {
|
|
304
|
+
if ((pa[i] || 0) !== (pb[i] || 0)) return (pa[i] || 0) - (pb[i] || 0);
|
|
305
|
+
}
|
|
306
|
+
return 0;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function whichSync(command) {
|
|
310
|
+
const result = spawnSync(process.platform === 'win32' ? 'where' : 'command', process.platform === 'win32' ? [command] : ['-v', command], {
|
|
311
|
+
encoding: 'utf8',
|
|
312
|
+
shell: process.platform !== 'win32'
|
|
313
|
+
});
|
|
314
|
+
return result.status === 0 ? String(result.stdout || '').trim().split(/\r?\n/)[0] : null;
|
|
315
|
+
}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import fsp from 'node:fs/promises';
|
|
3
3
|
import { createHash } from 'node:crypto';
|
|
4
|
-
import { readJson, readText, writeJsonAtomic, writeTextAtomic, appendJsonlBounded, nowIso, exists, ensureDir, packageRoot, dirSize, formatBytes, PACKAGE_VERSION, sksRoot, readStdin, runProcess } from '../
|
|
5
|
-
import { initProject } from '../
|
|
6
|
-
import { getCodexInfo, runCodexExec } from '../
|
|
7
|
-
import { createMission, loadMission, findLatestMission, missionDir, setCurrent, stateFile } from '../
|
|
8
|
-
import { buildQuestionSchema, writeQuestions } from '../
|
|
9
|
-
import { sealContract } from '../
|
|
10
|
-
import { buildQaLoopQuestionSchema, buildQaLoopPrompt, evaluateQaGate, qaStatus, writeMockQaResult, writeQaLoopArtifacts } from '../
|
|
11
|
-
import { containsUserQuestion, noQuestionContinuationReason } from '../
|
|
12
|
-
import { RESEARCH_GENIUS_SUMMARY_ARTIFACT, RESEARCH_SOURCE_SKILL_ARTIFACT, countGeniusOpinionSummaries, countResearchPaperSections, buildResearchPrompt, evaluateResearchGate, findResearchPaperArtifact, researchPaperArtifactForPlan, writeMockResearchResult, writeResearchPlan } from '../
|
|
13
|
-
import { storageReport, enforceRetention, pruneWikiArtifacts } from '../
|
|
14
|
-
import { evaluateDoneGate } from '../
|
|
15
|
-
import { renderCartridge, validateCartridge, driftCartridge, snapshotCartridge } from '../
|
|
16
|
-
import { DEFAULT_EVAL_THRESHOLDS, compareEvaluationReports, runEvaluationBenchmark } from '../
|
|
17
|
-
import { contextCapsule } from '../
|
|
18
|
-
import { rgbaKey, rgbaToWikiCoord, validateWikiCoordinateIndex } from '../
|
|
19
|
-
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, reflectionRequiredForRoute, routeNeedsContext7, routePrompt, routeReasoning, routeRequiresSubagents, stackCurrentDocsPolicy, stripVisibleDecisionAnswerBlocks, triwikiContextTracking } from '../
|
|
20
|
-
import { TEAM_DECOMPOSITION_ARTIFACT, TEAM_GRAPH_ARTIFACT, TEAM_INBOX_DIR, TEAM_RUNTIME_TASKS_ARTIFACT, teamRuntimePlanMetadata, teamRuntimeRequiredArtifacts, writeTeamRuntimeArtifacts } from '../
|
|
21
|
-
import { appendTeamEvent, formatAgentReasoning, formatRoleCounts, initTeamLive, isTerminalTeamAgentStatus, normalizeTeamSpec, parseTeamSpecArgs, readTeamControl, readTeamDashboard, readTeamLive, readTeamTranscriptTail, renderTeamAgentLane, renderTeamCleanupSummary, renderTeamWatch, requestTeamSessionCleanup, teamCleanupRequested, teamReasoningPolicy } from '../
|
|
22
|
-
import { evaluateTeamReviewPolicyGate, MIN_TEAM_REVIEWER_LANES, MIN_TEAM_REVIEW_POLICY_TEXT, teamReviewPolicy } from '../
|
|
23
|
-
import { ARTIFACT_FILES, writeValidationReport } from '../
|
|
24
|
-
import { writeEffortDecision } from '../
|
|
25
|
-
import { createWorkOrderLedger, writeWorkOrderLedger } from '../
|
|
26
|
-
import { writeFromChatImgArtifacts } from '../
|
|
27
|
-
import { renderTeamDashboardState, writeTeamDashboardState } from '../
|
|
28
|
-
import { runPerfBench, runWorkflowPerfBench } from '../
|
|
29
|
-
import { writeProofFieldReport } from '../
|
|
30
|
-
import { PIPELINE_PLAN_ARTIFACT, validatePipelinePlan, writePipelinePlan } from '../
|
|
31
|
-
import { GOAL_BRIDGE_ARTIFACT, GOAL_WORKFLOW_ARTIFACT, updateGoalWorkflow, writeGoalWorkflow } from '../
|
|
32
|
-
import { scanCodeStructure, writeCodeStructureReport } from '../
|
|
33
|
-
import { writeMemorySweepReport } from '../
|
|
34
|
-
import { cleanupTmuxTeamView, defaultTmuxSessionName, launchMadTmuxUi, launchTmuxTeamView, reconcileTmuxTeamCockpit, sanitizeTmuxSessionName } from '../
|
|
35
|
-
import { loadSkillDreamState, recordSkillDreamEvent, runSkillDream, writeSkillForgeReport } from '../
|
|
36
|
-
import { writeMistakeMemoryReport } from '../
|
|
37
|
-
import { checkDbOperation, checkSqlFile, classifyCommand, classifySql, loadDbSafetyPolicy, safeSupabaseMcpConfig, scanDbSafety } from '../
|
|
38
|
-
import { harnessGrowthReport, writeHarnessGrowthReport } from '../
|
|
39
|
-
import { enableMadHighProfile, madHighProfileName } from '../
|
|
40
|
-
import { permissionGateSummary } from '../
|
|
4
|
+
import { readJson, readText, writeJsonAtomic, writeTextAtomic, appendJsonlBounded, nowIso, exists, ensureDir, packageRoot, dirSize, formatBytes, PACKAGE_VERSION, sksRoot, readStdin, runProcess } from '../fsx.mjs';
|
|
5
|
+
import { initProject } from '../init.mjs';
|
|
6
|
+
import { getCodexInfo, runCodexExec } from '../codex-adapter.mjs';
|
|
7
|
+
import { createMission, loadMission, findLatestMission, missionDir, setCurrent, stateFile } from '../mission.mjs';
|
|
8
|
+
import { buildQuestionSchema, writeQuestions } from '../questions.mjs';
|
|
9
|
+
import { sealContract } from '../decision-contract.mjs';
|
|
10
|
+
import { buildQaLoopQuestionSchema, buildQaLoopPrompt, evaluateQaGate, qaStatus, writeMockQaResult, writeQaLoopArtifacts } from '../qa-loop.mjs';
|
|
11
|
+
import { containsUserQuestion, noQuestionContinuationReason } from '../no-question-guard.mjs';
|
|
12
|
+
import { RESEARCH_GENIUS_SUMMARY_ARTIFACT, RESEARCH_SOURCE_SKILL_ARTIFACT, countGeniusOpinionSummaries, countResearchPaperSections, buildResearchPrompt, evaluateResearchGate, findResearchPaperArtifact, researchPaperArtifactForPlan, writeMockResearchResult, writeResearchPlan } from '../research.mjs';
|
|
13
|
+
import { storageReport, enforceRetention, pruneWikiArtifacts } from '../retention.mjs';
|
|
14
|
+
import { evaluateDoneGate } from '../hproof.mjs';
|
|
15
|
+
import { renderCartridge, validateCartridge, driftCartridge, snapshotCartridge } from '../gx-renderer.mjs';
|
|
16
|
+
import { DEFAULT_EVAL_THRESHOLDS, compareEvaluationReports, runEvaluationBenchmark } from '../evaluation.mjs';
|
|
17
|
+
import { contextCapsule } from '../triwiki-attention.mjs';
|
|
18
|
+
import { rgbaKey, rgbaToWikiCoord, validateWikiCoordinateIndex } from '../wiki-coordinate.mjs';
|
|
19
|
+
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, reflectionRequiredForRoute, routeNeedsContext7, routePrompt, routeReasoning, routeRequiresSubagents, stackCurrentDocsPolicy, stripVisibleDecisionAnswerBlocks, triwikiContextTracking } from '../routes.mjs';
|
|
20
|
+
import { TEAM_DECOMPOSITION_ARTIFACT, TEAM_GRAPH_ARTIFACT, TEAM_INBOX_DIR, TEAM_RUNTIME_TASKS_ARTIFACT, teamRuntimePlanMetadata, teamRuntimeRequiredArtifacts, writeTeamRuntimeArtifacts } from '../team-dag.mjs';
|
|
21
|
+
import { appendTeamEvent, formatAgentReasoning, formatRoleCounts, initTeamLive, isTerminalTeamAgentStatus, normalizeTeamSpec, parseTeamSpecArgs, readTeamControl, readTeamDashboard, readTeamLive, readTeamTranscriptTail, renderTeamAgentLane, renderTeamCleanupSummary, renderTeamWatch, requestTeamSessionCleanup, teamCleanupRequested, teamReasoningPolicy } from '../team-live.mjs';
|
|
22
|
+
import { evaluateTeamReviewPolicyGate, MIN_TEAM_REVIEWER_LANES, MIN_TEAM_REVIEW_POLICY_TEXT, teamReviewPolicy } from '../team-review-policy.mjs';
|
|
23
|
+
import { ARTIFACT_FILES, writeValidationReport } from '../artifact-schemas.mjs';
|
|
24
|
+
import { writeEffortDecision } from '../effort-orchestrator.mjs';
|
|
25
|
+
import { createWorkOrderLedger, writeWorkOrderLedger } from '../work-order-ledger.mjs';
|
|
26
|
+
import { writeFromChatImgArtifacts } from '../from-chat-img-forensics.mjs';
|
|
27
|
+
import { renderTeamDashboardState, writeTeamDashboardState } from '../team-dashboard-renderer.mjs';
|
|
28
|
+
import { runPerfBench, runWorkflowPerfBench } from '../perf-bench.mjs';
|
|
29
|
+
import { writeProofFieldReport } from '../proof-field.mjs';
|
|
30
|
+
import { PIPELINE_PLAN_ARTIFACT, validatePipelinePlan, writePipelinePlan } from '../pipeline.mjs';
|
|
31
|
+
import { GOAL_BRIDGE_ARTIFACT, GOAL_WORKFLOW_ARTIFACT, updateGoalWorkflow, writeGoalWorkflow } from '../goal-workflow.mjs';
|
|
32
|
+
import { scanCodeStructure, writeCodeStructureReport } from '../code-structure.mjs';
|
|
33
|
+
import { writeMemorySweepReport } from '../memory-governor.mjs';
|
|
34
|
+
import { cleanupTmuxTeamView, defaultTmuxSessionName, launchMadTmuxUi, launchTmuxTeamView, reconcileTmuxTeamCockpit, sanitizeTmuxSessionName } from '../tmux-ui.mjs';
|
|
35
|
+
import { loadSkillDreamState, recordSkillDreamEvent, runSkillDream, writeSkillForgeReport } from '../skill-forge.mjs';
|
|
36
|
+
import { writeMistakeMemoryReport } from '../mistake-memory.mjs';
|
|
37
|
+
import { checkDbOperation, checkSqlFile, classifyCommand, classifySql, loadDbSafetyPolicy, safeSupabaseMcpConfig, scanDbSafety } from '../db-safety.mjs';
|
|
38
|
+
import { harnessGrowthReport, writeHarnessGrowthReport } from '../evaluation.mjs';
|
|
39
|
+
import { enableMadHighProfile, madHighProfileName } from '../auto-review.mjs';
|
|
40
|
+
import { permissionGateSummary } from '../permission-gates.mjs';
|
|
41
41
|
|
|
42
42
|
const flag = (args, name) => args.includes(name);
|
|
43
43
|
const promptOf = (args) => args.filter((x) => !String(x).startsWith('--')).join(' ').trim();
|