sneakoscope 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli/main.mjs +43 -8
- package/src/core/fsx.mjs +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "ㅅㅋㅅ",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.1",
|
|
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
|
@@ -14,7 +14,7 @@ import { containsUserQuestion, noQuestionContinuationReason } from '../core/no-q
|
|
|
14
14
|
import { evaluateDoneGate, defaultDoneGate } from '../core/hproof.mjs';
|
|
15
15
|
import { emitHook } from '../core/hooks-runtime.mjs';
|
|
16
16
|
import { storageReport, enforceRetention, pruneWikiArtifacts } from '../core/retention.mjs';
|
|
17
|
-
import { classifySql, classifyCommand, checkDbOperation, handleMadSksUserConfirmation } from '../core/db-safety.mjs';
|
|
17
|
+
import { classifySql, classifyCommand, checkDbOperation, handleMadSksUserConfirmation, loadDbSafetyPolicy, scanDbSafety } from '../core/db-safety.mjs';
|
|
18
18
|
import { checkHarnessModification, harnessGuardStatus, isHarnessSourceProject } from '../core/harness-guard.mjs';
|
|
19
19
|
import { formatHarnessConflictReport, llmHarnessCleanupPrompt, scanHarnessConflicts } from '../core/harness-conflicts.mjs';
|
|
20
20
|
import { context7Docs, context7Resolve, context7Text, context7Tools } from '../core/context7-client.mjs';
|
|
@@ -1711,10 +1711,11 @@ async function doctor(args) {
|
|
|
1711
1711
|
let conflictScan = await scanHarnessConflicts(root);
|
|
1712
1712
|
let repairApplied = false;
|
|
1713
1713
|
let globalSkillsRepair = null;
|
|
1714
|
+
const globalCommand = await globalSksCommand();
|
|
1714
1715
|
if (flag(args, '--fix') && !conflictScan.hard_block) {
|
|
1715
|
-
const fixScope = requestedScope || 'global';
|
|
1716
1716
|
const existingManifest = await readJson(path.join(root, '.sneakoscope', 'manifest.json'), null);
|
|
1717
|
-
|
|
1717
|
+
const fixScope = requestedScope || normalizeInstallScope(existingManifest?.installation?.scope || 'global');
|
|
1718
|
+
await initProject(root, { installScope: fixScope, globalCommand, localOnly: flag(args, '--local-only') || Boolean(existingManifest?.git?.local_only), force: true, repair: true });
|
|
1718
1719
|
if (!flag(args, '--local-only')) globalSkillsRepair = await ensureGlobalCodexSkillsDuringInstall({ force: true });
|
|
1719
1720
|
repairApplied = true;
|
|
1720
1721
|
conflictScan = await scanHarnessConflicts(root);
|
|
@@ -1726,7 +1727,7 @@ async function doctor(args) {
|
|
|
1726
1727
|
const pkgBytes = await dirSize(packageRoot()).catch(() => 0);
|
|
1727
1728
|
const manifest = await readJson(path.join(root, '.sneakoscope', 'manifest.json'), null);
|
|
1728
1729
|
const installScope = requestedScope || normalizeInstallScope(manifest?.installation?.scope || 'global');
|
|
1729
|
-
const install = await installStatus(root, installScope);
|
|
1730
|
+
const install = await installStatus(root, installScope, { globalCommand });
|
|
1730
1731
|
const dbPolicyExists = await exists(path.join(root, '.sneakoscope', 'db-safety.json'));
|
|
1731
1732
|
const dbScan = await scanDbSafety(root).catch((err) => ({ ok: false, findings: [{ id: 'db_safety_scan_failed', severity: 'high', reason: err.message }] }));
|
|
1732
1733
|
const context7Status = await checkContext7(root);
|
|
@@ -1868,7 +1869,10 @@ async function installStatus(root, scope, opts = {}) {
|
|
|
1868
1869
|
const discoveredGlobalBin = await discoverGlobalSksCommand();
|
|
1869
1870
|
const configuredGlobalBin = await configuredSksBin(opts.globalCommand);
|
|
1870
1871
|
const globalBin = configuredGlobalBin || discoveredGlobalBin;
|
|
1871
|
-
const
|
|
1872
|
+
const sourceProject = await isHarnessSourceProject(root).catch(() => false);
|
|
1873
|
+
const sourceBin = path.join(root, 'bin', 'sks.mjs');
|
|
1874
|
+
const sourceBinExists = sourceProject && await exists(sourceBin);
|
|
1875
|
+
const commandPrefix = sourceBinExists ? 'node ./bin/sks.mjs' : sksCommandPrefix(scope, { globalCommand: globalBin || undefined });
|
|
1872
1876
|
const projectBin = path.join(root, 'node_modules', 'sneakoscope', 'bin', 'sks.mjs');
|
|
1873
1877
|
const projectBinExists = await exists(projectBin);
|
|
1874
1878
|
return {
|
|
@@ -1877,7 +1881,9 @@ async function installStatus(root, scope, opts = {}) {
|
|
|
1877
1881
|
command_prefix: commandPrefix,
|
|
1878
1882
|
global_bin: globalBin,
|
|
1879
1883
|
project_bin: projectBin,
|
|
1880
|
-
|
|
1884
|
+
source_project: sourceProject,
|
|
1885
|
+
source_bin: sourceBinExists ? sourceBin : null,
|
|
1886
|
+
ok: sourceBinExists || (scope === 'project' ? projectBinExists : Boolean(globalBin))
|
|
1881
1887
|
};
|
|
1882
1888
|
}
|
|
1883
1889
|
|
|
@@ -2038,18 +2044,47 @@ async function selftest() {
|
|
|
2038
2044
|
const guardStatus = await harnessGuardStatus(tmp);
|
|
2039
2045
|
if (!guardStatus.ok || !guardStatus.locked || guardStatus.source_exception) throw new Error('selftest failed: harness guard not locked in installed project');
|
|
2040
2046
|
const repairTmp = tmpdir();
|
|
2041
|
-
await
|
|
2047
|
+
await writeJsonAtomic(path.join(repairTmp, 'package.json'), { name: 'sneakoscope', version: '0.0.0', type: 'module' });
|
|
2048
|
+
await ensureDir(path.join(repairTmp, 'bin'));
|
|
2049
|
+
await writeTextAtomic(path.join(repairTmp, 'bin', 'sks.mjs'), '#!/usr/bin/env node\n');
|
|
2050
|
+
await ensureDir(path.join(repairTmp, 'src', 'core'));
|
|
2051
|
+
await writeTextAtomic(path.join(repairTmp, 'src', 'core', 'init.mjs'), '// source-project marker\n');
|
|
2052
|
+
await writeTextAtomic(path.join(repairTmp, 'src', 'core', 'hooks-runtime.mjs'), '// source-project marker\n');
|
|
2053
|
+
await initProject(repairTmp, { installScope: 'project', localOnly: true });
|
|
2042
2054
|
await writeTextAtomic(path.join(repairTmp, '.agents', 'skills', 'team', 'SKILL.md'), 'tampered\n');
|
|
2043
2055
|
await writeTextAtomic(path.join(repairTmp, '.agents', 'skills', 'agent-team', 'SKILL.md'), '---\nname: agent-team\ndescription: Fallback Codex App picker alias for $Team.\n---\n');
|
|
2044
2056
|
await ensureDir(path.join(repairTmp, '.agents', 'skills', 'custom-keep'));
|
|
2045
2057
|
await writeTextAtomic(path.join(repairTmp, '.agents', 'skills', 'custom-keep', 'SKILL.md'), '---\nname: custom-keep\ndescription: User custom skill, not generated by SKS.\n---\n');
|
|
2046
2058
|
await writeTextAtomic(path.join(repairTmp, '.codex', 'skills', 'team', 'SKILL.md'), 'legacy mirror\n');
|
|
2047
|
-
await
|
|
2059
|
+
await writeTextAtomic(path.join(repairTmp, '.codex', 'hooks.json'), '{ "hooks": { "Stop": [{ "hooks": [{ "type": "command", "command": "tampered hook" }] }] } }\n');
|
|
2060
|
+
await writeTextAtomic(path.join(repairTmp, '.codex', 'SNEAKOSCOPE.md'), 'tampered quick reference\n');
|
|
2061
|
+
await writeJsonAtomic(path.join(repairTmp, '.sneakoscope', 'policy.json'), { broken: true });
|
|
2062
|
+
const existingAgentsMd = await safeReadText(path.join(repairTmp, 'AGENTS.md'));
|
|
2063
|
+
await writeTextAtomic(path.join(repairTmp, 'AGENTS.md'), existingAgentsMd.replace(/<!-- BEGIN Sneakoscope Codex GX MANAGED BLOCK -->[\s\S]*?<!-- END Sneakoscope Codex GX MANAGED BLOCK -->\n?/, '<!-- BEGIN Sneakoscope Codex GX MANAGED BLOCK -->\ntampered managed block\n<!-- END Sneakoscope Codex GX MANAGED BLOCK -->\n'));
|
|
2064
|
+
const doctorRepair = await runProcess(process.execPath, [path.join(packageRoot(), 'bin', 'sks.mjs'), 'doctor', '--fix', '--local-only', '--json'], {
|
|
2065
|
+
cwd: repairTmp,
|
|
2066
|
+
env: { HOME: path.join(repairTmp, 'home'), SKS_DISABLE_UPDATE_CHECK: '1' },
|
|
2067
|
+
timeoutMs: 30000,
|
|
2068
|
+
maxOutputBytes: 1024 * 1024
|
|
2069
|
+
});
|
|
2070
|
+
if (doctorRepair.code !== 0) throw new Error(`selftest failed: doctor --fix exited ${doctorRepair.code}: ${doctorRepair.stderr}`);
|
|
2071
|
+
const doctorRepairJson = JSON.parse(doctorRepair.stdout || '{}');
|
|
2072
|
+
if (!doctorRepairJson.repair?.applied || doctorRepairJson.install?.scope !== 'project' || !doctorRepairJson.install?.ok || !doctorRepairJson.install?.source_project) throw new Error('selftest failed: doctor --fix did not preserve project source install scope');
|
|
2073
|
+
const repairedManifest = await readJson(path.join(repairTmp, '.sneakoscope', 'manifest.json'));
|
|
2074
|
+
if (repairedManifest.installation?.scope !== 'project' || repairedManifest.installation?.hook_command_prefix !== 'node ./bin/sks.mjs') throw new Error('selftest failed: doctor --fix rewrote project source install scope to the wrong command prefix');
|
|
2048
2075
|
const repairedTeamSkill = await safeReadText(path.join(repairTmp, '.agents', 'skills', 'team', 'SKILL.md'));
|
|
2049
2076
|
if (!repairedTeamSkill.includes('SKS Team orchestration') || repairedTeamSkill.includes('tampered')) throw new Error('selftest failed: doctor repair did not regenerate team skill');
|
|
2050
2077
|
if (await exists(path.join(repairTmp, '.agents', 'skills', 'agent-team', 'SKILL.md'))) throw new Error('selftest failed: doctor repair did not remove deprecated agent-team alias skill');
|
|
2051
2078
|
if (!(await exists(path.join(repairTmp, '.agents', 'skills', 'custom-keep', 'SKILL.md')))) throw new Error('selftest failed: doctor repair removed a user-owned custom skill');
|
|
2052
2079
|
if (await exists(path.join(repairTmp, '.codex', 'skills', 'team', 'SKILL.md'))) throw new Error('selftest failed: doctor repair did not remove legacy .codex/skills');
|
|
2080
|
+
const repairedQuickReference = await safeReadText(path.join(repairTmp, '.codex', 'SNEAKOSCOPE.md'));
|
|
2081
|
+
if (!repairedQuickReference.includes('Install scope: `project`') || repairedQuickReference.includes('tampered')) throw new Error('selftest failed: doctor --fix did not regenerate quick reference');
|
|
2082
|
+
const repairedHooks = await safeReadText(path.join(repairTmp, '.codex', 'hooks.json'));
|
|
2083
|
+
if (!repairedHooks.includes('node ./bin/sks.mjs hook stop') || repairedHooks.includes('tampered hook')) throw new Error('selftest failed: doctor --fix did not regenerate Codex hooks');
|
|
2084
|
+
const repairedPolicy = await readJson(path.join(repairTmp, '.sneakoscope', 'policy.json'));
|
|
2085
|
+
if (repairedPolicy.broken || repairedPolicy.installation?.scope !== 'project' || !repairedPolicy.prompt_pipeline?.dollar_commands?.includes('$Team')) throw new Error('selftest failed: doctor --fix did not regenerate policy');
|
|
2086
|
+
const repairedAgentsMd = await safeReadText(path.join(repairTmp, 'AGENTS.md'));
|
|
2087
|
+
if (!repairedAgentsMd.includes('Do not create unrequested fallback implementation code') || repairedAgentsMd.includes('tampered managed block')) throw new Error('selftest failed: doctor --fix did not repair AGENTS managed block');
|
|
2053
2088
|
const conflictTmp = tmpdir();
|
|
2054
2089
|
await ensureDir(path.join(conflictTmp, '.omx'));
|
|
2055
2090
|
const conflictScan = await scanHarnessConflicts(conflictTmp, { home: path.join(conflictTmp, 'home') });
|
package/src/core/fsx.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import os from 'node:os';
|
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
7
|
|
|
8
|
-
export const PACKAGE_VERSION = '0.7.
|
|
8
|
+
export const PACKAGE_VERSION = '0.7.1';
|
|
9
9
|
export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
|
|
10
10
|
export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
|
|
11
11
|
|