sneakoscope 10.5.4 → 10.5.5
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 +6 -1
- package/config/skills-hash-ledger.v1.json +1 -0
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/commands/doctor-console.js +6 -0
- package/dist/commands/doctor.js +30 -2
- package/dist/config/skills-manifest.json +3 -2
- package/dist/core/agent-guidance/harness-maintenance.js +185 -0
- package/dist/core/agent-guidance/official-guidance-client.js +82 -0
- package/dist/core/codex/deprecated-config.js +255 -0
- package/dist/core/codex-native/core-skill-manifest.js +5 -5
- package/dist/core/commands/align-command.js +13 -4
- package/dist/core/doctor/codex-config-syntax-repair.js +43 -19
- package/dist/core/doctor/doctor-codex-startup-repair.js +0 -8
- package/dist/core/doctor/supabase-mcp-repair.js +56 -38
- package/dist/core/init.js +18 -51
- package/dist/core/routes.js +3 -3
- package/dist/core/subagents/model-tiers.js +0 -9
- package/dist/core/update/update-migration-state/simple-stages.js +9 -0
- package/dist/core/update/update-migration-state.js +6 -1
- package/dist/core/version.js +1 -1
- package/package.json +1 -1
- package/dist/core/doctor/stale-subagent-default.js +0 -30
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
Sneakoscope Codex (`sks`) is an open-source trust layer for Codex CLI and ChatGPT Desktop. It coordinates bounded AI coding agents, records machine-verifiable evidence, preserves project memory, and blocks release claims that are not supported by current tests or artifacts. Search visibility outcomes are measured separately; SKS does not promise rankings or traffic.
|
|
18
18
|
<!-- END SKS SEARCH VISIBILITY MARKETING -->
|
|
19
19
|
|
|
20
|
-
Current package: **SKS 10.5.
|
|
20
|
+
Current package: **SKS 10.5.5**. Install the latest stable release from npm.
|
|
21
21
|
|
|
22
22
|
Sneakoscope Codex (`sks`) is a local trust layer for Codex CLI and ChatGPT Desktop. It keeps agent work bounded, preserves project context, records machine-verifiable evidence, and prevents release claims that current tests or artifacts cannot support.
|
|
23
23
|
|
|
@@ -66,6 +66,11 @@ The installer resolves the latest npm release, installs `sks`, runs setup and Do
|
|
|
66
66
|
| Recover safely | Doctor and update flows report a concrete recovery action when a check needs attention. |
|
|
67
67
|
| Operate locally | The CLI works without a hosted control plane; macOS users can also use SKS Center. |
|
|
68
68
|
|
|
69
|
+
`$sks-align` refreshes the thin managed guidance against current official Codex
|
|
70
|
+
references and rebuilds TriWiki. Update and user-run `sks doctor --fix` share
|
|
71
|
+
that maintenance and repair known ignored configuration settings. User text
|
|
72
|
+
and model choices are preserved. See [harness maintenance](docs/align-modernization.md).
|
|
73
|
+
|
|
69
74
|
## Everyday commands
|
|
70
75
|
|
|
71
76
|
Inside a Codex conversation:
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
{
|
|
16
16
|
"canonical_name": "sks-align",
|
|
17
17
|
"trusted_sha256": [
|
|
18
|
+
"c3073b4a10203e642dd1236902b01772ecff6a3a7464cdecde0aad21e3c12b80",
|
|
18
19
|
"9eef36214be7e07a963eb36bb1df2c025cd0578b7419ddf4fd307081a2b62093",
|
|
19
20
|
"b9db40d6e1dd2fc6e4665a2b30738d370da955cd4d6e86c88bd85059c7faa08c",
|
|
20
21
|
"c485f39d4873adb9793672f7dcf4e956595ffb9dcbb032b3ffb0515b5857d31d",
|
|
@@ -84,6 +84,12 @@ export function renderDoctorConsoleReport(result, extras) {
|
|
|
84
84
|
for (const warning of codexConfigSyntaxRepair.warnings || [])
|
|
85
85
|
line(` warning: ${warning}`);
|
|
86
86
|
}
|
|
87
|
+
if (result.harness_maintenance) {
|
|
88
|
+
const guidance = result.harness_maintenance;
|
|
89
|
+
line(`Official harness guidance: ${guidance.guidance_status}${guidance.fetched_at ? ` (${guidance.fetched_at})` : ''}`);
|
|
90
|
+
for (const warning of guidance.warnings || [])
|
|
91
|
+
line(` warning: ${warning}`);
|
|
92
|
+
}
|
|
87
93
|
line(` codex doctor: ${formatCodexDoctorConsoleStatus(result.codex_doctor)}`);
|
|
88
94
|
line(`Rust acc.: ${rust.mode || (rust.available ? 'rust_accelerated' : 'js_fallback')} ${rust.version || rust.status || ''}`);
|
|
89
95
|
line(`Codex App: ${codexApp.skipped === true ? DOCTOR_CONSOLE_NOT_MEASURED : ready.codex_app_ready ? 'ok' : 'optional_missing'}`);
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import os from 'node:os';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { projectRoot, exists, formatBytes, nowIso, writeJsonAtomic } from '../core/fsx.js';
|
|
3
|
+
import { projectRoot, exists, ensureDir, formatBytes, nowIso, writeJsonAtomic } from '../core/fsx.js';
|
|
4
4
|
import { flag } from '../cli/args.js';
|
|
5
5
|
import { printJson } from '../cli/output.js';
|
|
6
6
|
import { ui as cliUi } from '../cli/cli-theme.js';
|
|
@@ -27,6 +27,7 @@ import { detectImagegenCapability } from '../core/imagegen/imagegen-capability.j
|
|
|
27
27
|
import { formatHarnessConflictReport, scanHarnessConflicts } from '../core/harness-conflicts.js';
|
|
28
28
|
import { doctorArgWarnings as baseDoctorArgWarnings, doctorGlobalOnlySelection, doctorMenuBarInstallPolicy, doctorPhaseIdsForProfile, doctorProfileFromArgs, doctorProfileRequiresDesktopBridgeReadiness } from './doctor-profile.js';
|
|
29
29
|
import { renderDoctorConsoleReport } from './doctor-console.js';
|
|
30
|
+
import { isVerificationTestHarness } from '../core/verification-profile.js';
|
|
30
31
|
import { buildCodexAppUiDiagnosticFailure, buildRuntimeReadiness, captureCodexConfigSnapshot, deferredNativeRepair, fallbackCodexNativeFeatureMatrix, formatCodexDoctorConsoleStatus, installScopeFromArgs, isMigrationUserOwnedProjectConfigBlocker, mergeObservedCodexStartupWarnings, readOption, rebootstrapSksMenuBarLaunchdForDoctorFix, sksMenuBarRunningVersionConsoleLines, writeFixMigrationJournal, writeJsonReportFile } from './doctor-helpers.js';
|
|
31
32
|
export { doctorMenuBarInstallPolicy, doctorProfileFromArgs, doctorProfileRequiresDesktopBridgeReadiness } from './doctor-profile.js';
|
|
32
33
|
export { buildCodexAppUiDiagnosticFailure, buildRuntimeReadiness, formatCodexDoctorConsoleStatus, rebootstrapSksMenuBarLaunchdForDoctorFix, sksMenuBarRunningVersionConsoleLines };
|
|
@@ -202,6 +203,10 @@ export async function executeDoctorGlobalOnlyFix(args = [], root, deps = {}) {
|
|
|
202
203
|
error: err?.message || String(err)
|
|
203
204
|
}));
|
|
204
205
|
const doctorProfile = doctorProfileFromArgs(args, true);
|
|
206
|
+
const syntaxRepair = await (await import('../core/doctor/codex-config-syntax-repair.js')).runCodexConfigSyntaxRepair({
|
|
207
|
+
root: home, fix: true, codexHome: doctorEnv.CODEX_HOME || path.join(home, '.codex')
|
|
208
|
+
});
|
|
209
|
+
const harnessMaintenance = await doctorHarnessMaintenance(path.resolve(deps.globalRuntimeRoot || doctorEnv.SKS_GLOBAL_ROOT || path.join(home, '.sneakoscope-global')), doctorProfile, doctorEnv, deps);
|
|
205
210
|
const menuBarPolicy = doctorMenuBarInstallPolicy(args, true, doctorEnv);
|
|
206
211
|
const menuBar = menuBarPolicy.phase_enabled
|
|
207
212
|
? await installMenuBarImpl({
|
|
@@ -248,6 +253,8 @@ export async function executeDoctorGlobalOnlyFix(args = [], root, deps = {}) {
|
|
|
248
253
|
&& globalFastMode?.ok !== false;
|
|
249
254
|
const menuBarReady = menuBar?.ok !== false;
|
|
250
255
|
const migrationScopeBlockers = [...new Set([
|
|
256
|
+
...syntaxRepair.blockers,
|
|
257
|
+
...(harnessMaintenance?.blockers || []),
|
|
251
258
|
...(!globalSkillsReady ? [`global_skills_reconcile_failed:${globalSkills?.error || 'core_skill_integrity'}`] : []),
|
|
252
259
|
...(currentSurface?.ok !== true ? (currentSurface?.blockers || ['global_current_surface_reconcile_failed']) : []),
|
|
253
260
|
...(!globalFastModeReady ? [`global_fast_mode_repair_failed:${globalFastMode?.error || globalFastMode?.status || 'unknown'}`] : [])
|
|
@@ -291,6 +298,8 @@ export async function executeDoctorGlobalOnlyFix(args = [], root, deps = {}) {
|
|
|
291
298
|
...migrationReceiptBlockers
|
|
292
299
|
].map(String).filter(Boolean))];
|
|
293
300
|
const warnings = [...new Set([
|
|
301
|
+
...syntaxRepair.warnings,
|
|
302
|
+
...(harnessMaintenance?.warnings || []),
|
|
294
303
|
...(!bridgeReadinessRequired ? bridgeBlockers.map((blocker) => `migration_optional_blocker:${blocker}`) : []),
|
|
295
304
|
...(desktopBridgeRepair?.warnings || []),
|
|
296
305
|
...(desktopBridge?.warnings || [])
|
|
@@ -321,6 +330,8 @@ export async function executeDoctorGlobalOnlyFix(args = [], root, deps = {}) {
|
|
|
321
330
|
],
|
|
322
331
|
skills: { global: globalSkills, project: { skipped: true, reason: 'global_only_doctor' } },
|
|
323
332
|
current_public_surface: currentSurface,
|
|
333
|
+
codex_config_syntax_repair: syntaxRepair,
|
|
334
|
+
harness_maintenance: harnessMaintenance,
|
|
324
335
|
codex_app_fast_mode: globalFastMode,
|
|
325
336
|
openrouter_provider: desktopBridge.providers?.openrouter || null,
|
|
326
337
|
sks_menubar: menuBar,
|
|
@@ -569,6 +580,7 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
|
|
|
569
580
|
actions: []
|
|
570
581
|
})) : { ok: true, skipped: true, reason: 'doctor_without_fix', actions: [] };
|
|
571
582
|
const doctorProfile = doctorProfileFromArgs(args, doctorFix);
|
|
583
|
+
const harnessMaintenance = doctorFix ? await doctorHarnessMaintenance(root, doctorProfile, process.env, deps) : null;
|
|
572
584
|
const machineOnly = flag(args, '--machine-only');
|
|
573
585
|
const reportFile = readOption(args, '--report-file', null);
|
|
574
586
|
const argWarnings = doctorArgWarnings(args);
|
|
@@ -1467,6 +1479,7 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
|
|
|
1467
1479
|
}
|
|
1468
1480
|
const runtimeReadiness = buildRuntimeReadiness(codexNativeFeatureMatrix);
|
|
1469
1481
|
const resultBlockers = [
|
|
1482
|
+
...(harnessMaintenance?.blockers || []),
|
|
1470
1483
|
...(ready.ready
|
|
1471
1484
|
? []
|
|
1472
1485
|
: (Array.isArray(ready.blockers) && ready.blockers.length
|
|
@@ -1511,7 +1524,7 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
|
|
|
1511
1524
|
root,
|
|
1512
1525
|
arg_warnings: argWarnings,
|
|
1513
1526
|
blockers: [...new Set(resultBlockers.map(String))],
|
|
1514
|
-
warnings: [...oauthCallbackPortDiagnostic.warnings, ...(desktopBridge.warnings || [])],
|
|
1527
|
+
warnings: [...oauthCallbackPortDiagnostic.warnings, ...(desktopBridge.warnings || []), ...(harnessMaintenance?.warnings || [])],
|
|
1515
1528
|
operator_actions: [...new Set([
|
|
1516
1529
|
...oauthCallbackOperatorActions,
|
|
1517
1530
|
...(desktopBridge.ok === false ? desktopBridge.recovery_actions || [] : []),
|
|
@@ -1542,6 +1555,7 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
|
|
|
1542
1555
|
codex_startup_repair: codexStartupRepair,
|
|
1543
1556
|
startup_config_repair: startupConfigRepair,
|
|
1544
1557
|
codex_config_syntax_repair: codexConfigSyntaxRepair,
|
|
1558
|
+
harness_maintenance: harnessMaintenance,
|
|
1545
1559
|
context7_mcp_repair: context7McpRepair,
|
|
1546
1560
|
supabase_mcp_repair: supabaseMcpRepair,
|
|
1547
1561
|
doctor_fix_transaction: doctorFixTransaction,
|
|
@@ -1616,3 +1630,17 @@ async function runDoctor(args = [], root, doctorFix, deps = {}) {
|
|
|
1616
1630
|
if (!result.ok)
|
|
1617
1631
|
process.exitCode = 1;
|
|
1618
1632
|
}
|
|
1633
|
+
async function doctorHarnessMaintenance(root, profile, env, deps) {
|
|
1634
|
+
const duringUpdate = env.SKS_UPDATE_DEFER_MENUBAR_RESTART === '1';
|
|
1635
|
+
if (profile === 'migration' && !duringUpdate)
|
|
1636
|
+
return null;
|
|
1637
|
+
await ensureDir(root);
|
|
1638
|
+
const maintain = deps.maintainHarnessGuidanceImpl
|
|
1639
|
+
|| (await import('../core/agent-guidance/harness-maintenance.js')).maintainHarnessGuidance;
|
|
1640
|
+
const codexHome = deps.codexHome || deps.env?.CODEX_HOME
|
|
1641
|
+
|| (deps.home ? path.join(deps.home, '.codex') : !isVerificationTestHarness() ? env.CODEX_HOME : undefined);
|
|
1642
|
+
return maintain({
|
|
1643
|
+
root, trigger: duringUpdate ? 'update' : 'doctor', reuseRecent: duringUpdate,
|
|
1644
|
+
...(codexHome ? { codexHome } : {})
|
|
1645
|
+
});
|
|
1646
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "sks.skills-manifest.v1",
|
|
3
|
-
"package_version": "10.5.
|
|
3
|
+
"package_version": "10.5.5",
|
|
4
4
|
"skills": [
|
|
5
5
|
{
|
|
6
6
|
"canonical_name": "sks",
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
{
|
|
19
19
|
"canonical_name": "sks-align",
|
|
20
20
|
"type": "core",
|
|
21
|
-
"content_sha256": "
|
|
21
|
+
"content_sha256": "c3073b4a10203e642dd1236902b01772ecff6a3a7464cdecde0aad21e3c12b80",
|
|
22
22
|
"hash_history": [
|
|
23
|
+
"9eef36214be7e07a963eb36bb1df2c025cd0578b7419ddf4fd307081a2b62093",
|
|
23
24
|
"b9db40d6e1dd2fc6e4665a2b30738d370da955cd4d6e86c88bd85059c7faa08c",
|
|
24
25
|
"c485f39d4873adb9793672f7dcf4e956595ffb9dcbb032b3ffb0515b5857d31d",
|
|
25
26
|
"e98e1b67e228bec5c37d00c0206a2e01d2da698a83c80b527105bf04a19c136a"
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { readText, writeTextAtomic, writeJsonAtomic, mergeManagedBlock } from '../fsx.js';
|
|
5
|
+
import { ensureConfinedDirectory, inspectConfinedPath } from '../managed-path-safety.js';
|
|
6
|
+
import { withFileLock } from '../locks/file-lock.js';
|
|
7
|
+
import { isVerificationTestHarness } from '../verification-profile.js';
|
|
8
|
+
import { reconcileManagedProjectPromptGuidance } from '../doctor/current-project-guidance.js';
|
|
9
|
+
import { globalAgentsBlockText, GLOBAL_AGENTS_MARKER } from '../codex-hooks/codex-global-hooks.js';
|
|
10
|
+
export async function maintainHarnessGuidance(input) {
|
|
11
|
+
const root = path.resolve(input.root);
|
|
12
|
+
const codexHome = path.resolve(input.codexHome || process.env.CODEX_HOME || path.join(process.env.HOME || os.homedir(), '.codex'));
|
|
13
|
+
const dir = path.join(root, '.sneakoscope', 'guidance');
|
|
14
|
+
const report = {
|
|
15
|
+
schema: 'sks.harness-maintenance.v1', ok: true, trigger: input.trigger,
|
|
16
|
+
guidance_status: 'unavailable', fetched_at: null, source_urls: [], prompt_hints_updated: false, changed_files: [], warnings: [], blockers: [],
|
|
17
|
+
report_path: path.join(root, '.sneakoscope', 'reports', 'harness-maintenance.json')
|
|
18
|
+
};
|
|
19
|
+
try {
|
|
20
|
+
for (const file of [path.join(root, 'AGENTS.md'), path.join(root, '.codex', 'SNEAKOSCOPE.md')]) {
|
|
21
|
+
if ((await inspectConfinedPath(root, file)).leafSymlink)
|
|
22
|
+
throw new Error('managed_guidance_unsafe_path');
|
|
23
|
+
}
|
|
24
|
+
const refreshed = await reconcileManagedProjectPromptGuidance(root);
|
|
25
|
+
report.changed_files.push(...refreshed.refreshed.map(file => path.join(root, file)));
|
|
26
|
+
if (refreshed.errors)
|
|
27
|
+
report.blockers.push('managed_project_guidance_refresh_failed');
|
|
28
|
+
const globalFile = path.join(codexHome, 'AGENTS.md');
|
|
29
|
+
const codexHomeExists = await fs.lstat(codexHome).then(() => true).catch((error) => {
|
|
30
|
+
if (error.code === 'ENOENT')
|
|
31
|
+
return false;
|
|
32
|
+
throw error;
|
|
33
|
+
});
|
|
34
|
+
const useGlobal = codexHomeExists && (!isVerificationTestHarness() || input.codexHome !== undefined);
|
|
35
|
+
const globalPath = useGlobal ? await inspectConfinedPath(codexHome, globalFile) : null;
|
|
36
|
+
if (globalPath?.exists && !globalPath.leafSymlink && globalPath.stat?.isFile()) {
|
|
37
|
+
const before = await readText(globalFile, '');
|
|
38
|
+
if (before.includes(`<!-- BEGIN ${GLOBAL_AGENTS_MARKER} -->`)) {
|
|
39
|
+
const body = globalAgentsBlockText().trim();
|
|
40
|
+
const marker = `<!-- BEGIN ${GLOBAL_AGENTS_MARKER} -->`;
|
|
41
|
+
const end = `<!-- END ${GLOBAL_AGENTS_MARKER} -->`;
|
|
42
|
+
if (!before.includes(end))
|
|
43
|
+
throw new Error('global_guidance_managed_block_incomplete');
|
|
44
|
+
const current = before.slice(before.indexOf(marker) + marker.length, before.indexOf(end)).trim();
|
|
45
|
+
if (current !== body) {
|
|
46
|
+
await mergeManagedBlock(globalFile, GLOBAL_AGENTS_MARKER, globalAgentsBlockText());
|
|
47
|
+
report.changed_files.push(globalFile);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else if (globalPath?.exists)
|
|
52
|
+
report.blockers.push('global_guidance_unsafe_path');
|
|
53
|
+
await ensureConfinedDirectory(root, dir);
|
|
54
|
+
const cacheFile = path.join(dir, 'official-sources.json');
|
|
55
|
+
const readerFile = path.join(dir, 'current-codex.md');
|
|
56
|
+
const sharedDir = useGlobal ? path.join(codexHome, 'sks', 'official-guidance') : dir;
|
|
57
|
+
if (useGlobal)
|
|
58
|
+
await ensureConfinedDirectory(codexHome, sharedDir);
|
|
59
|
+
const sharedFile = path.join(sharedDir, 'official-sources.json');
|
|
60
|
+
if (useGlobal && (await inspectConfinedPath(codexHome, sharedFile)).leafSymlink)
|
|
61
|
+
throw new Error('official_guidance_cache_unsafe_path');
|
|
62
|
+
for (const file of [cacheFile, readerFile]) {
|
|
63
|
+
if ((await inspectConfinedPath(root, file)).leafSymlink)
|
|
64
|
+
throw new Error('official_guidance_unsafe_path');
|
|
65
|
+
}
|
|
66
|
+
await withFileLock({ lockPath: path.join(sharedDir, 'refresh.lock'), timeoutMs: 25_000, staleMs: 60_000 }, async () => {
|
|
67
|
+
const { retrieveOfficialGuidance, validOfficialGuidance } = await import('./official-guidance-client.js');
|
|
68
|
+
let snapshot = null;
|
|
69
|
+
try {
|
|
70
|
+
const cached = JSON.parse(await fs.readFile(sharedFile, 'utf8'));
|
|
71
|
+
if (validOfficialGuidance(cached))
|
|
72
|
+
snapshot = cached;
|
|
73
|
+
}
|
|
74
|
+
catch { }
|
|
75
|
+
const previousSnapshot = snapshot;
|
|
76
|
+
const recent = snapshot && Date.now() - Date.parse(snapshot.fetched_at) >= 0
|
|
77
|
+
&& Date.now() - Date.parse(snapshot.fetched_at) < 10 * 60_000;
|
|
78
|
+
if (input.reuseRecent && recent)
|
|
79
|
+
report.guidance_status = 'cached';
|
|
80
|
+
else if (!input.retrieve && isVerificationTestHarness()) {
|
|
81
|
+
report.warnings.push('official_guidance_network_not_requested_by_test_harness');
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
try {
|
|
85
|
+
const fetched = await (input.retrieve || retrieveOfficialGuidance)();
|
|
86
|
+
if (!validOfficialGuidance(fetched))
|
|
87
|
+
throw new Error('official_guidance_snapshot_invalid');
|
|
88
|
+
snapshot = fetched;
|
|
89
|
+
report.guidance_status = 'refreshed';
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
report.warnings.push(`official_guidance_refresh_unavailable:${error instanceof Error ? error.message.slice(0, 200) : 'unknown'}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (!snapshot)
|
|
96
|
+
return;
|
|
97
|
+
report.fetched_at = snapshot.fetched_at;
|
|
98
|
+
report.source_urls = snapshot.sources.map(source => source.url);
|
|
99
|
+
if (report.guidance_status === 'unavailable')
|
|
100
|
+
return;
|
|
101
|
+
const hints = officialPromptHints(snapshot);
|
|
102
|
+
if (!hints) {
|
|
103
|
+
report.guidance_status = 'unavailable';
|
|
104
|
+
report.fetched_at = previousSnapshot?.fetched_at || null;
|
|
105
|
+
report.source_urls = previousSnapshot?.sources.map(source => source.url) || [];
|
|
106
|
+
report.warnings.push('official_prompt_sections_changed_previous_hints_preserved');
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const json = `${JSON.stringify(snapshot, null, 2)}\n`;
|
|
110
|
+
const markdown = renderGuidanceReference(snapshot);
|
|
111
|
+
const writes = new Map([[sharedFile, json], [cacheFile, json], [readerFile, markdown]]);
|
|
112
|
+
for (const [file, content] of writes) {
|
|
113
|
+
if (await readText(file, '') !== content) {
|
|
114
|
+
await writeTextAtomic(file, content);
|
|
115
|
+
report.changed_files.push(file);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
for (const file of [path.join(root, 'AGENTS.md'), ...(useGlobal ? [globalFile] : [])]) {
|
|
119
|
+
const before = await readText(file, '');
|
|
120
|
+
if (!/<!-- BEGIN Sneakoscope Codex (?:GX|GLOBAL) MANAGED BLOCK -->/.test(before))
|
|
121
|
+
continue;
|
|
122
|
+
const marker = 'SKS CURRENT OFFICIAL GUIDANCE';
|
|
123
|
+
const begin = `<!-- BEGIN ${marker} -->`, end = `<!-- END ${marker} -->`;
|
|
124
|
+
if (before.includes(begin) && !before.includes(end))
|
|
125
|
+
throw new Error('official_prompt_block_incomplete');
|
|
126
|
+
const current = before.includes(begin) ? before.slice(before.indexOf(begin) + begin.length, before.indexOf(end)).trim() : '';
|
|
127
|
+
if (current === hints.trim())
|
|
128
|
+
continue;
|
|
129
|
+
await mergeManagedBlock(file, marker, hints);
|
|
130
|
+
report.changed_files.push(file);
|
|
131
|
+
report.prompt_hints_updated = true;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
report.blockers.push(`harness_maintenance_failed:${error instanceof Error ? error.message.slice(0, 200) : 'unknown'}`);
|
|
137
|
+
}
|
|
138
|
+
report.ok = report.blockers.length === 0;
|
|
139
|
+
report.changed_files = [...new Set(report.changed_files)];
|
|
140
|
+
try {
|
|
141
|
+
await ensureConfinedDirectory(root, path.dirname(report.report_path));
|
|
142
|
+
if ((await inspectConfinedPath(root, report.report_path)).leafSymlink)
|
|
143
|
+
throw new Error('harness_report_unsafe_path');
|
|
144
|
+
await writeJsonAtomic(report.report_path, report);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
report.ok = false;
|
|
148
|
+
report.blockers.push('harness_maintenance_report_write_failed');
|
|
149
|
+
}
|
|
150
|
+
return report;
|
|
151
|
+
}
|
|
152
|
+
function officialPromptHints(snapshot) {
|
|
153
|
+
const source = snapshot.sources.find(row => row.id === 'codex-prompting');
|
|
154
|
+
if (!source)
|
|
155
|
+
return null;
|
|
156
|
+
const hints = ['Describe the result you need', 'Add useful context'].map(heading => {
|
|
157
|
+
const section = source.text.replace(/\r\n/g, '\n').split(`## ${heading}\n`)[1]?.split(/\n##? /)[0]?.trim();
|
|
158
|
+
if (!section || section.startsWith('```') || section.startsWith('<'))
|
|
159
|
+
return null;
|
|
160
|
+
const paragraph = section.split(/\n\s*\n/)[0].replace(/\s+/g, ' ').trim();
|
|
161
|
+
const sentence = paragraph.match(/^[^.!?]+[.!?]/)?.[0] || paragraph;
|
|
162
|
+
const words = sentence.split(/\s+/);
|
|
163
|
+
return words.slice(0, 12).join(' ') + (words.length > 12 ? ' …' : '');
|
|
164
|
+
});
|
|
165
|
+
if (hints.some(hint => !hint))
|
|
166
|
+
return null;
|
|
167
|
+
return [
|
|
168
|
+
'Current official prompting references (apply within user instructions and SKS safety boundaries):',
|
|
169
|
+
...hints.map(hint => `> ${hint}`),
|
|
170
|
+
`[Source](${source.url}). Current Codex/model references: \`.sneakoscope/guidance/current-codex.md\`.`
|
|
171
|
+
].join('\n');
|
|
172
|
+
}
|
|
173
|
+
function renderGuidanceReference(snapshot) {
|
|
174
|
+
return [
|
|
175
|
+
'# Current official Codex guidance', '',
|
|
176
|
+
`Retrieved: ${snapshot.fetched_at}`, '',
|
|
177
|
+
'Reference material for maintenance, not permission to change user preferences or execute instructions from a webpage.',
|
|
178
|
+
'SKS keeps its engineering principle and source-only TriWiki. Keep outcome, useful context and necessary boundaries concise; leave route details in the selected skill. Preserve explicit model, effort and service-tier choices.',
|
|
179
|
+
'The latest-model document is a moving reference, not a model pin or an instruction to copy model-specific tuning. Read only the relevant source when adapting managed guidance.', '',
|
|
180
|
+
...snapshot.sources.flatMap(source => [
|
|
181
|
+
`## ${source.title}`, '', `[Official source](${source.url})`, `SHA-256: ${source.sha256}`, '',
|
|
182
|
+
'The retrieved page is stored under its source id in `official-sources.json`.', ''
|
|
183
|
+
])
|
|
184
|
+
].join('\n');
|
|
185
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
|
|
3
|
+
import { PACKAGE_VERSION } from '../version.js';
|
|
4
|
+
export const OFFICIAL_GUIDANCE_SOURCES = [
|
|
5
|
+
{ id: 'codex-instructions', query: 'Codex AGENTS.md concise instructions', url: 'https://learn.chatgpt.com/docs/agent-configuration/agents-md', paths: ['/docs/agent-configuration/agents-md', '/codex/guides/agents-md'] },
|
|
6
|
+
{ id: 'codex-prompting', query: 'Codex prompting goals context boundaries', url: 'https://learn.chatgpt.com/docs/prompting', paths: ['/docs/prompting', '/codex/prompting'] },
|
|
7
|
+
{ id: 'latest-model-guidance', query: 'latest model prompting best practices', url: 'https://developers.openai.com/api/docs/guides/latest-model', paths: ['/api/docs/guides/latest-model', '/docs/guides/latest-model'] }
|
|
8
|
+
];
|
|
9
|
+
const OFFICIAL_HOSTS = new Set(['developers.openai.com', 'learn.chatgpt.com', 'platform.openai.com']);
|
|
10
|
+
const MAX_RESPONSE_BYTES = 1024 * 1024;
|
|
11
|
+
export async function retrieveOfficialGuidance() {
|
|
12
|
+
const client = new Client({ name: 'sneakoscope-official-guidance', version: PACKAGE_VERSION }, {
|
|
13
|
+
versionNegotiation: { mode: 'auto', probe: { timeoutMs: 6000, maxRetries: 0 } },
|
|
14
|
+
inputRequired: { autoFulfill: false }
|
|
15
|
+
});
|
|
16
|
+
try {
|
|
17
|
+
await client.connect(new StreamableHTTPClientTransport(new URL('https://developers.openai.com/mcp')), { timeout: 6000 });
|
|
18
|
+
const selected = await Promise.all(OFFICIAL_GUIDANCE_SOURCES.map(async (source) => {
|
|
19
|
+
const search = await client.callTool({ name: 'search_openai_docs', arguments: { query: source.query, limit: 5 } }, { timeout: 6000 });
|
|
20
|
+
const result = JSON.parse(toolText(search));
|
|
21
|
+
if (!Array.isArray(result.hits))
|
|
22
|
+
throw new Error(`official_guidance_search_invalid:${source.id}`);
|
|
23
|
+
const hit = result.hits.find((row) => sourceUrlAllowed(source.id, row?.url));
|
|
24
|
+
const url = new URL(hit?.url || source.url);
|
|
25
|
+
url.hash = '';
|
|
26
|
+
url.search = '';
|
|
27
|
+
return {
|
|
28
|
+
source, url: url.toString(), discovered_via_search: Boolean(hit),
|
|
29
|
+
search_result_urls: result.hits.slice(0, 5).map((row) => String(row?.url || '').slice(0, 2048))
|
|
30
|
+
};
|
|
31
|
+
}));
|
|
32
|
+
const sources = await Promise.all(selected.map(async ({ source, url, discovered_via_search, search_result_urls }) => {
|
|
33
|
+
const fetched = await client.callTool({ name: 'fetch_openai_doc', arguments: { url } }, { timeout: 6000 });
|
|
34
|
+
const text = toolText(fetched);
|
|
35
|
+
if (text.length < 100 || Buffer.byteLength(text) > 256 * 1024)
|
|
36
|
+
throw new Error(`official_guidance_document_invalid:${source.id}`);
|
|
37
|
+
const title = (text.match(/^#\s+(.+)$/m)?.[1] || source.id).replace(/[\r\n`]/g, ' ').slice(0, 160);
|
|
38
|
+
return { id: source.id, query: source.query, url, title, discovered_via_search, search_result_urls, text, sha256: digest(text) };
|
|
39
|
+
}));
|
|
40
|
+
return { schema: 'sks.official-guidance.v1', fetched_at: new Date().toISOString(), sources };
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
await client.close();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function validOfficialGuidance(value) {
|
|
47
|
+
const row = value;
|
|
48
|
+
return row?.schema === 'sks.official-guidance.v1'
|
|
49
|
+
&& Number.isFinite(Date.parse(row.fetched_at))
|
|
50
|
+
&& Array.isArray(row.sources) && row.sources.length === OFFICIAL_GUIDANCE_SOURCES.length
|
|
51
|
+
&& OFFICIAL_GUIDANCE_SOURCES.every(expected => row.sources.filter(source => source.id === expected.id).length === 1)
|
|
52
|
+
&& row.sources.every(source => sourceUrlAllowed(source.id, source.url)
|
|
53
|
+
&& typeof source.discovered_via_search === 'boolean'
|
|
54
|
+
&& Array.isArray(source.search_result_urls) && source.search_result_urls.length <= 5
|
|
55
|
+
&& typeof source.text === 'string' && source.text.length >= 100
|
|
56
|
+
&& Buffer.byteLength(source.text) <= 256 * 1024
|
|
57
|
+
&& source.sha256 === digest(source.text));
|
|
58
|
+
}
|
|
59
|
+
function sourceUrlAllowed(id, value) {
|
|
60
|
+
if (typeof value !== 'string')
|
|
61
|
+
return false;
|
|
62
|
+
try {
|
|
63
|
+
const url = new URL(value);
|
|
64
|
+
const source = OFFICIAL_GUIDANCE_SOURCES.find(row => row.id === id);
|
|
65
|
+
const pathname = url.pathname.replace(/\/$/, '');
|
|
66
|
+
return url.protocol === 'https:' && OFFICIAL_HOSTS.has(url.hostname) && !url.port && !url.username && !url.password
|
|
67
|
+
&& Boolean(source?.paths.some(path => pathname === path));
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function toolText(result) {
|
|
74
|
+
const row = result;
|
|
75
|
+
if (row?.isError || !Array.isArray(row?.content))
|
|
76
|
+
throw new Error('official_guidance_tool_failed');
|
|
77
|
+
const text = row.content.filter(item => item.type === 'text' && typeof item.text === 'string').map(item => item.text).join('\n');
|
|
78
|
+
if (!text || Buffer.byteLength(text) > MAX_RESPONSE_BYTES)
|
|
79
|
+
throw new Error('official_guidance_response_invalid');
|
|
80
|
+
return text;
|
|
81
|
+
}
|
|
82
|
+
function digest(text) { return createHash('sha256').update(text).digest('hex'); }
|