sneakoscope 3.1.3 → 3.1.4
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 +1 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/.sks-build-stamp.json +4 -4
- package/dist/bin/sks.js +1 -1
- package/dist/commands/codex-app.js +45 -1
- package/dist/commands/doctor.js +44 -1
- package/dist/core/codex-app/codex-agent-role-sync.js +67 -0
- package/dist/core/codex-app/codex-app-execution-profile.js +32 -0
- package/dist/core/codex-app/codex-app-harness-matrix.js +75 -0
- package/dist/core/codex-app/codex-hook-lifecycle.js +40 -0
- package/dist/core/codex-app/codex-init-deep.js +87 -0
- package/dist/core/codex-app/codex-skill-sync.js +92 -0
- package/dist/core/codex-app/lazycodex-analysis.js +51 -0
- package/dist/core/codex-app/lazycodex-interop-policy.js +49 -0
- package/dist/core/commands/loop-command.js +11 -0
- package/dist/core/commands/mad-sks-command.js +77 -16
- package/dist/core/doctor/doctor-readiness-matrix.js +7 -0
- package/dist/core/doctor/doctor-zellij-repair.js +36 -0
- package/dist/core/fsx.js +1 -1
- package/dist/core/hooks-runtime.js +13 -0
- package/dist/core/loops/loop-continuation-enforcer.js +32 -0
- package/dist/core/loops/loop-planner.js +9 -0
- package/dist/core/loops/loop-worker-runtime.js +5 -1
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/homebrew-policy.js +45 -0
- package/dist/core/zellij/zellij-capability.js +32 -3
- package/dist/core/zellij/zellij-self-heal.js +353 -0
- package/dist/core/zellij/zellij-update.js +31 -6
- package/dist/scripts/sks-3-1-4-directive-check-lib.js +241 -0
- package/package.json +28 -2
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
|
|
|
35
35
|
|
|
36
36
|
## 🚀 Current Release
|
|
37
37
|
|
|
38
|
-
SKS **3.1.
|
|
38
|
+
SKS **3.1.4** makes `doctor --fix` a real Zellij dependency self-healer, lets `sks --mad` repair or explicitly run headless without contradictory optional/blocking messages, and adds Codex App Harness Matrix reporting for plugins, hooks, skills, agent roles, init-deep memory, and execution profile decisions.
|
|
39
39
|
|
|
40
40
|
SKS 3.0.0 was the parallel-runtime stabilization release. The whole live-swarm experience — what you actually *see* while 5, 20, or 100 workers run — was rebuilt and proven end-to-end.
|
|
41
41
|
|
|
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
|
|
|
4
4
|
fn main() {
|
|
5
5
|
let mut args = std::env::args().skip(1);
|
|
6
6
|
match args.next().as_deref() {
|
|
7
|
-
Some("--version") => println!("sks-rs 3.1.
|
|
7
|
+
Some("--version") => println!("sks-rs 3.1.4"),
|
|
8
8
|
Some("compact-info") => {
|
|
9
9
|
let mut input = String::new();
|
|
10
10
|
let _ = io::stdin().read_to_string(&mut input);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "sks.dist-build-stamp.v1",
|
|
3
3
|
"package_name": "sneakoscope",
|
|
4
|
-
"package_version": "3.1.
|
|
5
|
-
"source_digest": "
|
|
6
|
-
"source_file_count":
|
|
7
|
-
"built_at_source_time":
|
|
4
|
+
"package_version": "3.1.4",
|
|
5
|
+
"source_digest": "47f6028f6b91151c205109059bff2ef5c51d2f084ae930063eca118d1888a8fc",
|
|
6
|
+
"source_file_count": 2488,
|
|
7
|
+
"built_at_source_time": 1781425289529
|
|
8
8
|
}
|
package/dist/bin/sks.js
CHANGED
|
@@ -2,10 +2,35 @@ import { flag } from '../cli/args.js';
|
|
|
2
2
|
import { printJson } from '../cli/output.js';
|
|
3
3
|
import { codexAccessTokenStatus, codexAppIntegrationStatus, codexChromeExtensionStatus, codexProductDesignPluginStatus, formatCodexAppStatus, formatCodexProductDesignPluginStatus } from '../core/codex-app.js';
|
|
4
4
|
import { codexAppRemoteControlCommand } from '../cli/codex-app-command.js';
|
|
5
|
+
import { sksRoot } from '../core/fsx.js';
|
|
6
|
+
import { buildCodexAppHarnessMatrix } from '../core/codex-app/codex-app-harness-matrix.js';
|
|
7
|
+
import { syncCodexSksSkills } from '../core/codex-app/codex-skill-sync.js';
|
|
8
|
+
import { syncCodexAgentRoles } from '../core/codex-app/codex-agent-role-sync.js';
|
|
9
|
+
import { runCodexInitDeep } from '../core/codex-app/codex-init-deep.js';
|
|
10
|
+
import { buildCodexHookLifecycle } from '../core/codex-app/codex-hook-lifecycle.js';
|
|
11
|
+
import { resolveCodexAppExecutionProfile } from '../core/codex-app/codex-app-execution-profile.js';
|
|
12
|
+
import { buildLazyCodexInteropPolicy } from '../core/codex-app/lazycodex-interop-policy.js';
|
|
5
13
|
export async function run(_command, args = []) {
|
|
6
14
|
const action = args[0] || 'check';
|
|
7
15
|
if (action === 'remote-control' || action === 'remote')
|
|
8
16
|
return codexAppRemoteControlCommand(args.slice(1));
|
|
17
|
+
if (action === 'harness-matrix')
|
|
18
|
+
return printCodexAppResult(args, await buildCodexAppHarnessMatrix({ root: await sksRoot(), applyRepairs: flag(args, '--fix') || flag(args, '--apply') }));
|
|
19
|
+
if (action === 'skill-sync')
|
|
20
|
+
return printCodexAppResult(args, await syncCodexSksSkills({ root: await sksRoot(), apply: flag(args, '--apply') || flag(args, '--fix') }));
|
|
21
|
+
if (action === 'agent-role-sync')
|
|
22
|
+
return printCodexAppResult(args, await syncCodexAgentRoles({ root: await sksRoot(), apply: flag(args, '--apply') || flag(args, '--fix') }));
|
|
23
|
+
if (action === 'init-deep')
|
|
24
|
+
return printCodexAppResult(args, await runCodexInitDeep({ root: await sksRoot(), apply: !flag(args, '--check-only') && !flag(args, '--dry-run') }));
|
|
25
|
+
if (action === 'hook-lifecycle')
|
|
26
|
+
return printCodexAppResult(args, await buildCodexHookLifecycle({ root: await sksRoot(), apply: flag(args, '--apply') || flag(args, '--fix') }));
|
|
27
|
+
if (action === 'execution-profile')
|
|
28
|
+
return printCodexAppResult(args, await resolveCodexAppExecutionProfile({ root: await sksRoot() }));
|
|
29
|
+
if (action === 'interop' && args[1] === 'lazycodex') {
|
|
30
|
+
const modeArg = readOption(args, '--mode', 'coexist');
|
|
31
|
+
const mode = modeArg === 'sks-primary' || modeArg === 'handoff-to-omo' ? modeArg : 'coexist';
|
|
32
|
+
return printCodexAppResult(args, await buildLazyCodexInteropPolicy({ root: await sksRoot(), mode }));
|
|
33
|
+
}
|
|
9
34
|
if (action === 'product-design' || action === 'design-product' || action === 'ensure-product-design') {
|
|
10
35
|
const checkOnly = flag(args, '--check-only') || flag(args, '--no-install');
|
|
11
36
|
const status = await codexProductDesignPluginStatus({
|
|
@@ -66,7 +91,26 @@ export async function run(_command, args = []) {
|
|
|
66
91
|
process.exitCode = 1;
|
|
67
92
|
return;
|
|
68
93
|
}
|
|
69
|
-
console.error('Usage: sks codex-app check|status|product-design [--check-only]|ensure-product-design|chrome-extension|pat status|remote-control [--json]');
|
|
94
|
+
console.error('Usage: sks codex-app check|status|harness-matrix|skill-sync|agent-role-sync|init-deep|hook-lifecycle|execution-profile|interop lazycodex [--mode coexist]|product-design [--check-only]|ensure-product-design|chrome-extension|pat status|remote-control [--json]');
|
|
70
95
|
process.exitCode = 1;
|
|
71
96
|
}
|
|
97
|
+
function printCodexAppResult(args = [], result) {
|
|
98
|
+
if (flag(args, '--json')) {
|
|
99
|
+
printJson(result);
|
|
100
|
+
if (result?.ok === false)
|
|
101
|
+
process.exitCode = 1;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
console.log(`${result?.schema || 'sks.codex-app-result'}: ${result?.ok === false ? 'blocked' : 'ok'}`);
|
|
105
|
+
for (const blocker of result?.blockers || [])
|
|
106
|
+
console.log(`- blocker: ${blocker}`);
|
|
107
|
+
for (const warning of result?.warnings || [])
|
|
108
|
+
console.log(`- warning: ${warning}`);
|
|
109
|
+
if (result?.ok === false)
|
|
110
|
+
process.exitCode = 1;
|
|
111
|
+
}
|
|
112
|
+
function readOption(args = [], name, fallback) {
|
|
113
|
+
const index = args.indexOf(name);
|
|
114
|
+
return index >= 0 && args[index + 1] ? String(args[index + 1]) : fallback;
|
|
115
|
+
}
|
|
72
116
|
//# sourceMappingURL=codex-app.js.map
|
package/dist/commands/doctor.js
CHANGED
|
@@ -23,6 +23,8 @@ import { writeCodex0138CapabilityArtifacts } from '../core/codex-control/codex-0
|
|
|
23
23
|
import { runCodex0138Doctor } from '../core/doctor/codex-0138-doctor.js';
|
|
24
24
|
import { writeCodexPluginInventoryArtifacts, pluginAppTemplatePolicy } from '../core/codex-plugins/codex-plugin-json.js';
|
|
25
25
|
import { writeMcpPluginInventoryArtifacts } from '../core/mcp/mcp-plugin-inventory.js';
|
|
26
|
+
import { runDoctorZellijRepair, doctorZellijRepairConsoleLine } from '../core/doctor/doctor-zellij-repair.js';
|
|
27
|
+
import { buildCodexAppHarnessMatrix } from '../core/codex-app/codex-app-harness-matrix.js';
|
|
26
28
|
export async function run(_command, args = []) {
|
|
27
29
|
const doctorFix = flag(args, '--fix');
|
|
28
30
|
let setupRepair = null;
|
|
@@ -149,6 +151,23 @@ export async function run(_command, args = []) {
|
|
|
149
151
|
blockers: [err?.message || String(err)]
|
|
150
152
|
}))
|
|
151
153
|
: codexAppUiPlan;
|
|
154
|
+
const zellijRepair = await runDoctorZellijRepair({ root, args, doctorFix }).catch((err) => ({
|
|
155
|
+
schema: 'sks.zellij-self-heal.v1',
|
|
156
|
+
ok: false,
|
|
157
|
+
requested_by: 'doctor --fix',
|
|
158
|
+
fix_requested: doctorFix,
|
|
159
|
+
auto_approved: flag(args, '--yes') || flag(args, '-y'),
|
|
160
|
+
install_homebrew_allowed: false,
|
|
161
|
+
before: { status: 'unknown', version: null, bin: null },
|
|
162
|
+
latest_version: null,
|
|
163
|
+
strategy: 'failed',
|
|
164
|
+
command: 'sks doctor --fix --yes',
|
|
165
|
+
after: { status: 'unknown', version: null, bin: null },
|
|
166
|
+
mutation_guard_artifact: null,
|
|
167
|
+
homebrew: { present: false, bin: null, install_attempted: false, install_allowed: false },
|
|
168
|
+
blockers: [err?.message || String(err)],
|
|
169
|
+
warnings: []
|
|
170
|
+
}));
|
|
152
171
|
const zellij = await checkZellijCapability({ root, require: process.env.SKS_REQUIRE_ZELLIJ === '1' });
|
|
153
172
|
const localModel = await readLocalModelConfig().catch(() => null);
|
|
154
173
|
const permissionProfiles = await inventoryCodexPermissionProfiles(root, { writeReport: true });
|
|
@@ -178,6 +197,15 @@ export async function run(_command, args = []) {
|
|
|
178
197
|
const mcpPluginInventory = pluginInventory?.report
|
|
179
198
|
? await writeMcpPluginInventoryArtifacts(root, { inventory: pluginInventory.report }).catch((err) => ({ error: err?.message || String(err), candidates: null }))
|
|
180
199
|
: null;
|
|
200
|
+
const codexAppHarnessMatrix = await buildCodexAppHarnessMatrix({ root, applyRepairs: doctorFix }).catch((err) => ({
|
|
201
|
+
schema: 'sks.codex-app-harness-matrix.v1',
|
|
202
|
+
ok: false,
|
|
203
|
+
codex_cli: { available: false, version: null },
|
|
204
|
+
app_features: {},
|
|
205
|
+
sks_integrations: {},
|
|
206
|
+
blockers: [err?.message || String(err)],
|
|
207
|
+
warnings: []
|
|
208
|
+
}));
|
|
181
209
|
const pkgBytes = await dirSize(root).catch(() => 0);
|
|
182
210
|
const ready = await writeDoctorReadinessMatrix(root, {
|
|
183
211
|
codex,
|
|
@@ -194,10 +222,12 @@ export async function run(_command, args = []) {
|
|
|
194
222
|
codex_0138_doctor: codex0138Doctor,
|
|
195
223
|
codex_plugin_inventory: pluginInventory?.report || null,
|
|
196
224
|
codex_plugin_app_template_policy: pluginPolicy,
|
|
225
|
+
codex_app_harness_matrix: codexAppHarnessMatrix,
|
|
197
226
|
require_codex_cli_config_load: flag(args, '--fix') || flag(args, '--require-actual-codex'),
|
|
198
227
|
operator_actions: [
|
|
199
228
|
...(codexConfig.operator_actions || []),
|
|
200
229
|
...(configRepair?.operator_actions || []),
|
|
230
|
+
...(zellijRepair && !zellijRepair.ok && zellijRepair.command ? [`Run: ${zellijRepair.command}`] : []),
|
|
201
231
|
...(pluginPolicy?.doctor_warnings || [])
|
|
202
232
|
]
|
|
203
233
|
});
|
|
@@ -217,6 +247,7 @@ export async function run(_command, args = []) {
|
|
|
217
247
|
codex_doctor: codexDoctor,
|
|
218
248
|
codex_doctor_diff: codexDoctorDiff,
|
|
219
249
|
zellij,
|
|
250
|
+
zellij_repair: zellijRepair,
|
|
220
251
|
local_model: localModel,
|
|
221
252
|
agent_role_config: agentRoleConfigRepair,
|
|
222
253
|
zellij_readiness: zellijReadiness,
|
|
@@ -233,10 +264,11 @@ export async function run(_command, args = []) {
|
|
|
233
264
|
plugin_app_template_policy: pluginPolicy,
|
|
234
265
|
mcp_plugin_inventory: mcpPluginInventory?.candidates || null
|
|
235
266
|
},
|
|
267
|
+
codex_app_harness_matrix: codexAppHarnessMatrix,
|
|
236
268
|
ready,
|
|
237
269
|
sneakoscope: { ok: await exists(`${root}/.sneakoscope`) },
|
|
238
270
|
package: { bytes: pkgBytes, human: formatBytes(pkgBytes) },
|
|
239
|
-
repair: { sks_update: sksUpdate, setup: setupRepair, codex_config: configRepair, migration_journal: migrationJournal, global_sks_installs: globalSksInstallCleanup, agent_role_config: agentRoleConfigRepair }
|
|
271
|
+
repair: { sks_update: sksUpdate, setup: setupRepair, codex_config: configRepair, migration_journal: migrationJournal, global_sks_installs: globalSksInstallCleanup, agent_role_config: agentRoleConfigRepair, zellij: zellijRepair }
|
|
240
272
|
};
|
|
241
273
|
if (flag(args, '--json')) {
|
|
242
274
|
printJson(result);
|
|
@@ -260,9 +292,20 @@ export async function run(_command, args = []) {
|
|
|
260
292
|
console.log(` pane proof: ${zellijReadiness.pane_proof}`);
|
|
261
293
|
console.log(` screen proof:${zellijReadiness.screen_proof}`);
|
|
262
294
|
console.log(` tmux: ${zellijReadiness.tmux_removed_runtime ? 'removed_runtime' : 'present'}`);
|
|
295
|
+
const zellijRepairLine = doctorZellijRepairConsoleLine(zellijRepair);
|
|
296
|
+
if (zellijRepairLine)
|
|
297
|
+
console.log(zellijRepairLine);
|
|
263
298
|
console.log(` codex doctor: ${codexDoctor.available ? (codexDoctor.exit_code === 0 ? 'ok' : 'warning') : 'unavailable'}`);
|
|
264
299
|
console.log(`Rust acc.: ${rust.mode || (rust.available ? 'rust_accelerated' : 'js_fallback')} ${rust.version || rust.status || ''}`);
|
|
265
300
|
console.log(`Codex App: ${ready.codex_app_ready ? 'ok' : 'optional_missing'}`);
|
|
301
|
+
console.log('Codex App Harness:');
|
|
302
|
+
console.log(` plugins: ${codexAppHarnessMatrix.app_features?.plugin_json ? 'ok' : 'degraded'}`);
|
|
303
|
+
console.log(` hook approval: ${codexAppHarnessMatrix.app_features?.hook_approval_state_detectable ? 'ok' : 'unknown'}`);
|
|
304
|
+
console.log(` skills: ${codexAppHarnessMatrix.sks_integrations?.dollar_skills_synced ? 'ok' : 'degraded'}`);
|
|
305
|
+
console.log(` agent roles: ${codexAppHarnessMatrix.sks_integrations?.agent_roles_synced ? 'ok' : 'degraded'}`);
|
|
306
|
+
console.log(` native agent_type: ${codexAppHarnessMatrix.app_features?.agent_type_supported ? 'ok' : 'fallback message-role'}`);
|
|
307
|
+
console.log(` init-deep memory: ${codexAppHarnessMatrix.sks_integrations?.init_deep_available ? 'available' : 'missing'}`);
|
|
308
|
+
console.log(` loop mesh app profile: ${codexAppHarnessMatrix.sks_integrations?.loop_mesh_app_profile_available ? 'available' : 'missing'}`);
|
|
266
309
|
console.log('Codex App UI:');
|
|
267
310
|
console.log(` fast selector: ${codexAppUi.fast_selector || 'unknown'}`);
|
|
268
311
|
console.log(` provider selector: ${codexAppUi.provider_selector || 'unknown'}`);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import { nowIso, writeJsonAtomic, writeTextAtomic, ensureDir } from '../fsx.js';
|
|
6
|
+
import { repairAgentRoleConfigs } from '../agents/agent-role-config.js';
|
|
7
|
+
const DIRECTIVE_ROLES = [
|
|
8
|
+
'sks-explorer',
|
|
9
|
+
'sks-planner',
|
|
10
|
+
'sks-implementer',
|
|
11
|
+
'sks-checker',
|
|
12
|
+
'sks-release-verifier',
|
|
13
|
+
'sks-zellij-ui-verifier',
|
|
14
|
+
'sks-codex-probe-verifier'
|
|
15
|
+
];
|
|
16
|
+
export async function syncCodexAgentRoles(input) {
|
|
17
|
+
const root = path.resolve(input.root);
|
|
18
|
+
const codexHome = input.codexHome || process.env.CODEX_HOME || path.join(os.homedir(), '.codex');
|
|
19
|
+
const targetDir = path.join(codexHome, 'agents');
|
|
20
|
+
const baseRepair = await repairAgentRoleConfigs({
|
|
21
|
+
root,
|
|
22
|
+
apply: input.apply === true,
|
|
23
|
+
codexHome,
|
|
24
|
+
reportPath: path.join(root, '.sneakoscope', 'reports', 'agent-role-config-repair.json')
|
|
25
|
+
}).catch((err) => ({ ok: false, blockers: [err?.message || String(err)] }));
|
|
26
|
+
const created = [];
|
|
27
|
+
if (input.apply === true) {
|
|
28
|
+
await ensureDir(targetDir);
|
|
29
|
+
for (const role of DIRECTIVE_ROLES) {
|
|
30
|
+
const file = path.join(targetDir, `${role}.toml`);
|
|
31
|
+
const current = await fs.readFile(file, 'utf8').catch(() => '');
|
|
32
|
+
if (current && !current.includes('SKS managed 3.1.4 directive role'))
|
|
33
|
+
continue;
|
|
34
|
+
await writeTextAtomic(file, roleToml(role));
|
|
35
|
+
created.push(file);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const report = {
|
|
39
|
+
schema: 'sks.codex-agent-role-sync.v1',
|
|
40
|
+
generated_at: nowIso(),
|
|
41
|
+
ok: baseRepair.ok !== false,
|
|
42
|
+
apply: input.apply === true,
|
|
43
|
+
agent_type_supported: input.agentTypeSupported === true || process.env.SKS_CODEX_AGENT_TYPE_SUPPORTED === '1',
|
|
44
|
+
fallback: (input.agentTypeSupported === true || process.env.SKS_CODEX_AGENT_TYPE_SUPPORTED === '1') ? 'agent_type' : 'message-role',
|
|
45
|
+
codex_home: codexHome,
|
|
46
|
+
directive_roles: DIRECTIVE_ROLES,
|
|
47
|
+
created,
|
|
48
|
+
base_repair: baseRepair,
|
|
49
|
+
blockers: baseRepair.blockers || []
|
|
50
|
+
};
|
|
51
|
+
await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'codex-agent-role-sync.json'), report).catch(() => undefined);
|
|
52
|
+
return report;
|
|
53
|
+
}
|
|
54
|
+
function roleToml(role) {
|
|
55
|
+
return [
|
|
56
|
+
`name = "${role}"`,
|
|
57
|
+
`description = "SKS managed 3.1.4 directive role: ${role}"`,
|
|
58
|
+
'model_reasoning_effort = "medium"',
|
|
59
|
+
role.includes('implementer') ? 'sandbox_mode = "workspace-write"' : 'sandbox_mode = "read-only"',
|
|
60
|
+
'approval_policy = "never"',
|
|
61
|
+
'developer_instructions = """',
|
|
62
|
+
`You are ${role}. SKS managed 3.1.4 directive role. Respect bounded ownership and never clobber user files.`,
|
|
63
|
+
'"""',
|
|
64
|
+
''
|
|
65
|
+
].join('\n');
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=codex-agent-role-sync.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { nowIso, writeJsonAtomic } from '../fsx.js';
|
|
4
|
+
import { buildCodexAppHarnessMatrix } from './codex-app-harness-matrix.js';
|
|
5
|
+
export async function resolveCodexAppExecutionProfile(input = { root: process.cwd() }) {
|
|
6
|
+
const root = path.resolve(input.root || process.cwd());
|
|
7
|
+
const matrix = input.matrix || await buildCodexAppHarnessMatrix({ root }).catch(() => null);
|
|
8
|
+
const mode = !matrix?.codex_cli?.available
|
|
9
|
+
? 'degraded-no-app'
|
|
10
|
+
: matrix.app_features?.app_handoff_ready && matrix.app_features?.agent_type_supported
|
|
11
|
+
? 'codex-app-native'
|
|
12
|
+
: matrix.codex_cli.available
|
|
13
|
+
? 'codex-cli-headless'
|
|
14
|
+
: 'sks-loop-headless';
|
|
15
|
+
const profile = {
|
|
16
|
+
schema: 'sks.codex-app-execution-profile.v1',
|
|
17
|
+
generated_at: nowIso(),
|
|
18
|
+
ok: mode !== 'degraded-no-app',
|
|
19
|
+
mode,
|
|
20
|
+
agent_role_strategy: matrix?.app_features?.agent_type_supported ? 'agent_type' : 'message-role',
|
|
21
|
+
hooks_assumed_running: false,
|
|
22
|
+
hooks_approval_required: matrix?.app_features?.hook_approval_state_detectable !== true,
|
|
23
|
+
app_handoff_ready: matrix?.app_features?.app_handoff_ready === true,
|
|
24
|
+
image_path_exposure_ready: matrix?.app_features?.image_path_exposure_ready === true,
|
|
25
|
+
loop_mesh_app_profile_available: true,
|
|
26
|
+
blockers: mode === 'degraded-no-app' ? ['codex_cli_missing'] : [],
|
|
27
|
+
warnings: matrix?.warnings || []
|
|
28
|
+
};
|
|
29
|
+
await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'codex-app-execution-profile.json'), profile).catch(() => undefined);
|
|
30
|
+
return profile;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=codex-app-execution-profile.js.map
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { findCodexBinary } from '../codex-adapter.js';
|
|
4
|
+
import { codexAppIntegrationStatus } from '../codex-app.js';
|
|
5
|
+
import { detectCodex0138Capability } from '../codex-control/codex-0138-capability.js';
|
|
6
|
+
import { detectCodex0139Capability } from '../codex-control/codex-0139-capability.js';
|
|
7
|
+
import { buildCodexPluginInventory } from '../codex-plugins/codex-plugin-json.js';
|
|
8
|
+
import { readCodexHookActualState } from '../codex-hooks/codex-hook-actual-discovery.js';
|
|
9
|
+
import { nowIso, runProcess, writeJsonAtomic } from '../fsx.js';
|
|
10
|
+
import { repairAgentRoleConfigs } from '../agents/agent-role-config.js';
|
|
11
|
+
import { buildLazyCodexInteropPolicy } from './lazycodex-interop-policy.js';
|
|
12
|
+
export async function buildCodexAppHarnessMatrix(input = { root: process.cwd() }) {
|
|
13
|
+
const root = path.resolve(input.root || process.cwd());
|
|
14
|
+
const codexBin = await findCodexBinary().catch(() => null);
|
|
15
|
+
const version = codexBin ? await codexVersion(codexBin) : null;
|
|
16
|
+
const cap0138 = await detectCodex0138Capability({ codexBin }).catch((err) => ({ blockers: [err?.message || String(err)] }));
|
|
17
|
+
const cap0139 = await detectCodex0139Capability({ codexBin }).catch((err) => ({ blockers: [err?.message || String(err)] }));
|
|
18
|
+
const app = await codexAppIntegrationStatus({ codex: { bin: codexBin, version, available: Boolean(codexBin) } }).catch((err) => ({ ok: false, blockers: [err?.message || String(err)] }));
|
|
19
|
+
const plugins = await buildCodexPluginInventory().catch((err) => ({ plugins: [], marketplace_available: false, blockers: [err?.message || String(err)] }));
|
|
20
|
+
const hooks = await readCodexHookActualState(root).catch((err) => ({ ok: false, entries: [], blockers: [err?.message || String(err)] }));
|
|
21
|
+
const agents = await repairAgentRoleConfigs({ root, apply: input.applyRepairs === true, reportPath: path.join(root, '.sneakoscope', 'reports', 'codex-agent-role-sync.json') }).catch((err) => ({ ok: false, blockers: [err?.message || String(err)] }));
|
|
22
|
+
const interop = await buildLazyCodexInteropPolicy({ root, inventory: plugins }).catch(() => null);
|
|
23
|
+
const hasSkills = app?.required_skills?.ok === true || app?.skills?.ok === true || app?.skill_shadows?.ok !== false;
|
|
24
|
+
const hookApprovalKnown = false;
|
|
25
|
+
const matrix = {
|
|
26
|
+
schema: 'sks.codex-app-harness-matrix.v1',
|
|
27
|
+
generated_at: nowIso(),
|
|
28
|
+
ok: Boolean(codexBin) && cap0138.supports_plugin_json !== false && agents.ok !== false,
|
|
29
|
+
codex_cli: { available: Boolean(codexBin), version },
|
|
30
|
+
app_features: {
|
|
31
|
+
plugin_json: cap0138.supports_plugin_json === true,
|
|
32
|
+
marketplace_add: cap0139.supports_marketplace_source_field === true || plugins.marketplace_available === true,
|
|
33
|
+
marketplace_upgrade: cap0139.supports_marketplace_source_field === true,
|
|
34
|
+
startup_review_detectable: hookApprovalKnown,
|
|
35
|
+
hook_approval_state_detectable: hookApprovalKnown,
|
|
36
|
+
skill_picker_ready: Boolean(hasSkills),
|
|
37
|
+
agent_type_supported: process.env.SKS_CODEX_AGENT_TYPE_SUPPORTED === '1',
|
|
38
|
+
mcp_inventory_ready: Array.isArray(plugins.plugins),
|
|
39
|
+
app_handoff_ready: cap0138.supports_app_handoff === true,
|
|
40
|
+
image_path_exposure_ready: cap0138.supports_image_path_exposure === true
|
|
41
|
+
},
|
|
42
|
+
sks_integrations: {
|
|
43
|
+
dollar_skills_synced: Boolean(hasSkills),
|
|
44
|
+
agent_roles_synced: agents.ok !== false,
|
|
45
|
+
hooks_synced: hooks.ok !== false && (hooks.entries || []).length > 0,
|
|
46
|
+
init_deep_available: true,
|
|
47
|
+
loop_mesh_app_profile_available: true
|
|
48
|
+
},
|
|
49
|
+
blockers: [
|
|
50
|
+
...(!codexBin ? ['codex_cli_missing'] : []),
|
|
51
|
+
...(cap0138.blockers || []),
|
|
52
|
+
...(plugins.blockers || []),
|
|
53
|
+
...(agents.blockers || [])
|
|
54
|
+
],
|
|
55
|
+
warnings: [
|
|
56
|
+
...(cap0139.blockers || []).map((b) => `codex_0139:${b}`),
|
|
57
|
+
...(hooks.blockers || []).map((b) => `hooks:${b}`),
|
|
58
|
+
...(!hookApprovalKnown ? ['hook_approval_state_unknown'] : []),
|
|
59
|
+
...(interop?.lazycodex_detected ? ['lazycodex_detected_coexist_mode'] : [])
|
|
60
|
+
]
|
|
61
|
+
};
|
|
62
|
+
matrix.ok = matrix.blockers.length === 0;
|
|
63
|
+
await writeCodexAppHarnessMatrix(root, matrix, input.missionDir);
|
|
64
|
+
return matrix;
|
|
65
|
+
}
|
|
66
|
+
export async function writeCodexAppHarnessMatrix(root, matrix, missionDir) {
|
|
67
|
+
await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'codex-app-harness-matrix.json'), matrix);
|
|
68
|
+
if (missionDir)
|
|
69
|
+
await writeJsonAtomic(path.join(missionDir, 'codex-app-harness-matrix.json'), matrix).catch(() => undefined);
|
|
70
|
+
}
|
|
71
|
+
async function codexVersion(bin) {
|
|
72
|
+
const run = await runProcess(bin, ['--version'], { timeoutMs: 5000, maxOutputBytes: 16 * 1024 }).catch(() => null);
|
|
73
|
+
return run?.code === 0 ? `${run.stdout || run.stderr || ''}`.trim() || null : null;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=codex-app-harness-matrix.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { nowIso, writeJsonAtomic } from '../fsx.js';
|
|
4
|
+
import { readCodexHookActualState } from '../codex-hooks/codex-hook-actual-discovery.js';
|
|
5
|
+
import { installManagedCodexHooks } from '../codex-hooks/codex-hook-managed-install.js';
|
|
6
|
+
export async function buildCodexHookLifecycle(input = {}) {
|
|
7
|
+
const root = path.resolve(input.root || process.cwd());
|
|
8
|
+
const install = input.apply === true
|
|
9
|
+
? await installManagedCodexHooks(root).catch((err) => ({ ok: false, blockers: [err?.message || String(err)] }))
|
|
10
|
+
: null;
|
|
11
|
+
const actual = await readCodexHookActualState(root).catch((err) => ({ ok: false, entries: [], blockers: [err?.message || String(err)] }));
|
|
12
|
+
const events = {
|
|
13
|
+
UserPromptSubmit: ['route_classifier', 'goal_to_loop_compiler', 'permission_profile_badge'],
|
|
14
|
+
PreToolUse: ['requested_scope_guard', 'mad_db_priority_resolver', 'side_effect_zero_gate'],
|
|
15
|
+
PostToolUse: ['evidence_ledger', 'mutation_ledger', 'side_effect_scanner', 'context7_native_session_updates'],
|
|
16
|
+
Stop: ['continuation_enforcer', 'final_proof_check', 'loop_resume_hint'],
|
|
17
|
+
Notification: ['operator_status', 'zellij_anchor', 'codex_app_status']
|
|
18
|
+
};
|
|
19
|
+
const installedEvents = new Set((actual.entries || []).map((entry) => entry.event));
|
|
20
|
+
const report = {
|
|
21
|
+
schema: 'sks.codex-hook-lifecycle.v1',
|
|
22
|
+
generated_at: nowIso(),
|
|
23
|
+
ok: actual.ok !== false,
|
|
24
|
+
apply: input.apply === true,
|
|
25
|
+
approval_state: 'unknown',
|
|
26
|
+
approval_state_detectable: false,
|
|
27
|
+
lifecycle: Object.fromEntries(Object.entries(events).map(([event, actions]) => [event, {
|
|
28
|
+
actions,
|
|
29
|
+
installed: installedEvents.has(event),
|
|
30
|
+
approval_state: 'unknown'
|
|
31
|
+
}])),
|
|
32
|
+
actual_state: actual,
|
|
33
|
+
install,
|
|
34
|
+
blockers: actual.blockers || [],
|
|
35
|
+
warnings: ['hook_approval_state_unknown']
|
|
36
|
+
};
|
|
37
|
+
await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'codex-hook-lifecycle.json'), report).catch(() => undefined);
|
|
38
|
+
return report;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=codex-hook-lifecycle.js.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { ensureDir, nowIso, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
|
|
5
|
+
export async function runCodexInitDeep(input = {}) {
|
|
6
|
+
const root = path.resolve(input.root || process.cwd());
|
|
7
|
+
const dirs = await scoreDirectories(root);
|
|
8
|
+
const selected = dirs.filter((row) => row.score >= 4).slice(0, 12);
|
|
9
|
+
const contextDir = path.join(root, '.sneakoscope', 'context');
|
|
10
|
+
const generatedPath = path.join(contextDir, 'AGENTS.generated.md');
|
|
11
|
+
const markdown = renderGeneratedAgents(selected);
|
|
12
|
+
if (input.apply === true) {
|
|
13
|
+
await ensureDir(contextDir);
|
|
14
|
+
await writeTextAtomic(generatedPath, markdown);
|
|
15
|
+
}
|
|
16
|
+
const report = {
|
|
17
|
+
schema: 'sks.codex-init-deep.v1',
|
|
18
|
+
generated_at: nowIso(),
|
|
19
|
+
ok: true,
|
|
20
|
+
apply: input.apply === true,
|
|
21
|
+
root,
|
|
22
|
+
generated_path: path.relative(root, generatedPath),
|
|
23
|
+
root_agents_preserved: true,
|
|
24
|
+
directory_guidance: selected,
|
|
25
|
+
blockers: []
|
|
26
|
+
};
|
|
27
|
+
await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'codex-init-deep.json'), report).catch(() => undefined);
|
|
28
|
+
return report;
|
|
29
|
+
}
|
|
30
|
+
export async function readInitDeepMemory(root) {
|
|
31
|
+
const file = path.join(root, '.sneakoscope', 'context', 'AGENTS.generated.md');
|
|
32
|
+
const text = await fs.readFile(file, 'utf8').catch(() => '');
|
|
33
|
+
return text.trim() ? { path: file, text } : null;
|
|
34
|
+
}
|
|
35
|
+
async function scoreDirectories(root) {
|
|
36
|
+
const counts = new Map();
|
|
37
|
+
await walk(path.join(root, 'src'), root, counts);
|
|
38
|
+
await walk(path.join(root, 'docs'), root, counts);
|
|
39
|
+
const highRisk = [/src\/core\/zellij/, /src\/core\/loops/, /src\/core\/codex-app/, /src\/commands/];
|
|
40
|
+
return [...counts.entries()].map(([dir, value]) => {
|
|
41
|
+
const risky = highRisk.some((re) => re.test(dir));
|
|
42
|
+
const score = Math.min(10, Math.ceil(value.file_count / 6) + value.langs.size + (risky ? 3 : 0));
|
|
43
|
+
return {
|
|
44
|
+
dir,
|
|
45
|
+
file_count: value.file_count,
|
|
46
|
+
languages: [...value.langs].sort(),
|
|
47
|
+
score,
|
|
48
|
+
guidance: risky ? 'High-risk SKS runtime area; hydrate TriWiki/current source before edits.' : 'Use local source conventions and keep changes owner-scoped.'
|
|
49
|
+
};
|
|
50
|
+
}).sort((a, b) => b.score - a.score || a.dir.localeCompare(b.dir));
|
|
51
|
+
}
|
|
52
|
+
async function walk(dir, root, counts, depth = 0) {
|
|
53
|
+
if (depth > 3)
|
|
54
|
+
return;
|
|
55
|
+
const rows = await fs.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
56
|
+
for (const row of rows) {
|
|
57
|
+
const full = path.join(dir, row.name);
|
|
58
|
+
if (row.isDirectory()) {
|
|
59
|
+
if (!['node_modules', 'dist', '.git'].includes(row.name))
|
|
60
|
+
await walk(full, root, counts, depth + 1);
|
|
61
|
+
}
|
|
62
|
+
else if (row.isFile()) {
|
|
63
|
+
const relDir = path.relative(root, path.dirname(full)).split(path.sep).join('/');
|
|
64
|
+
const entry = counts.get(relDir) || { file_count: 0, langs: new Set() };
|
|
65
|
+
entry.file_count += 1;
|
|
66
|
+
entry.langs.add(path.extname(row.name).replace(/^\./, '') || 'text');
|
|
67
|
+
counts.set(relDir, entry);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function renderGeneratedAgents(rows) {
|
|
72
|
+
return [
|
|
73
|
+
'# SKS Init-Deep Generated Context',
|
|
74
|
+
'',
|
|
75
|
+
'This file is generated under `.sneakoscope/context` so user-authored `AGENTS.md` files are preserved.',
|
|
76
|
+
'',
|
|
77
|
+
...rows.flatMap((row) => [
|
|
78
|
+
`## ${row.dir}`,
|
|
79
|
+
'',
|
|
80
|
+
`- Files: ${row.file_count}`,
|
|
81
|
+
`- Languages: ${row.languages.join(', ') || 'unknown'}`,
|
|
82
|
+
`- Guidance: ${row.guidance}`,
|
|
83
|
+
''
|
|
84
|
+
])
|
|
85
|
+
].join('\n');
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=codex-init-deep.js.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import crypto from 'node:crypto';
|
|
6
|
+
import { ensureDir, nowIso, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
|
|
7
|
+
const SKS_SKILLS = [
|
|
8
|
+
'$Loop',
|
|
9
|
+
'$Naruto',
|
|
10
|
+
'$QA-LOOP',
|
|
11
|
+
'$Research',
|
|
12
|
+
'$DFix',
|
|
13
|
+
'$Image-UX-Review',
|
|
14
|
+
'$Computer-Use',
|
|
15
|
+
'$Init-Deep'
|
|
16
|
+
];
|
|
17
|
+
const LAZYCODEX_RESERVED = new Set(['ulw-loop', 'ulw-plan', 'start-work']);
|
|
18
|
+
export async function syncCodexSksSkills(input) {
|
|
19
|
+
const root = path.resolve(input.root);
|
|
20
|
+
const skillsRoot = input.skillsRoot || path.join(process.env.CODEX_HOME || path.join(os.homedir(), '.codex'), 'skills');
|
|
21
|
+
const existing = await listSkillNames(skillsRoot);
|
|
22
|
+
const collisions = existing.filter((name) => LAZYCODEX_RESERVED.has(name));
|
|
23
|
+
const desired = SKS_SKILLS.map((skill) => skillName(skill));
|
|
24
|
+
const created = [];
|
|
25
|
+
const skipped = [];
|
|
26
|
+
if (input.apply === true) {
|
|
27
|
+
await ensureDir(skillsRoot);
|
|
28
|
+
for (const name of desired) {
|
|
29
|
+
if (LAZYCODEX_RESERVED.has(name)) {
|
|
30
|
+
skipped.push(name);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const dir = path.join(skillsRoot, name);
|
|
34
|
+
const file = path.join(dir, 'SKILL.md');
|
|
35
|
+
const content = skillContent(name);
|
|
36
|
+
const current = await fs.readFile(file, 'utf8').catch(() => '');
|
|
37
|
+
if (current && !current.includes('BEGIN SKS MANAGED SKILL')) {
|
|
38
|
+
skipped.push(name);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
await ensureDir(dir);
|
|
42
|
+
await writeTextAtomic(file, content);
|
|
43
|
+
created.push(file);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const report = {
|
|
47
|
+
schema: 'sks.codex-skill-sync.v1',
|
|
48
|
+
generated_at: nowIso(),
|
|
49
|
+
ok: true,
|
|
50
|
+
apply: input.apply === true,
|
|
51
|
+
skills_root: skillsRoot,
|
|
52
|
+
desired_skills: desired,
|
|
53
|
+
existing_skills: existing,
|
|
54
|
+
created,
|
|
55
|
+
skipped,
|
|
56
|
+
lazycodex_reserved_present: collisions,
|
|
57
|
+
interop: {
|
|
58
|
+
mode: 'coexist',
|
|
59
|
+
clobbered_lazycodex: false,
|
|
60
|
+
clobbered_user_skills: false
|
|
61
|
+
},
|
|
62
|
+
blockers: []
|
|
63
|
+
};
|
|
64
|
+
await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'codex-skill-sync.json'), report).catch(() => undefined);
|
|
65
|
+
return report;
|
|
66
|
+
}
|
|
67
|
+
async function listSkillNames(root) {
|
|
68
|
+
const rows = await fs.readdir(root, { withFileTypes: true }).catch(() => []);
|
|
69
|
+
return rows.filter((row) => row.isDirectory()).map((row) => row.name).sort();
|
|
70
|
+
}
|
|
71
|
+
function skillName(value) {
|
|
72
|
+
return value.replace(/^\$/, '').toLowerCase();
|
|
73
|
+
}
|
|
74
|
+
function skillContent(name) {
|
|
75
|
+
const body = [
|
|
76
|
+
'---',
|
|
77
|
+
`name: ${name}`,
|
|
78
|
+
`description: SKS managed Codex App route bridge for $${name}.`,
|
|
79
|
+
'---',
|
|
80
|
+
'',
|
|
81
|
+
'<!-- BEGIN SKS MANAGED SKILL -->',
|
|
82
|
+
`Invoke the matching SKS route for $${name}. Do not overwrite user or LazyCodex/OmO skills.`,
|
|
83
|
+
`checksum: ${hash(name)}`,
|
|
84
|
+
'<!-- END SKS MANAGED SKILL -->',
|
|
85
|
+
''
|
|
86
|
+
].join('\n');
|
|
87
|
+
return body;
|
|
88
|
+
}
|
|
89
|
+
function hash(value) {
|
|
90
|
+
return crypto.createHash('sha256').update(`sks-skill:${value}`).digest('hex').slice(0, 12);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=codex-skill-sync.js.map
|