sneakoscope 3.1.2 → 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.
Files changed (33) hide show
  1. package/README.md +1 -1
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/crates/sks-core/src/main.rs +1 -1
  5. package/dist/.sks-build-stamp.json +4 -4
  6. package/dist/bin/sks.js +1 -1
  7. package/dist/commands/codex-app.js +45 -1
  8. package/dist/commands/doctor.js +44 -1
  9. package/dist/core/codex-app/codex-agent-role-sync.js +67 -0
  10. package/dist/core/codex-app/codex-app-execution-profile.js +32 -0
  11. package/dist/core/codex-app/codex-app-harness-matrix.js +75 -0
  12. package/dist/core/codex-app/codex-hook-lifecycle.js +40 -0
  13. package/dist/core/codex-app/codex-init-deep.js +87 -0
  14. package/dist/core/codex-app/codex-skill-sync.js +92 -0
  15. package/dist/core/codex-app/lazycodex-analysis.js +51 -0
  16. package/dist/core/codex-app/lazycodex-interop-policy.js +49 -0
  17. package/dist/core/commands/loop-command.js +11 -0
  18. package/dist/core/commands/mad-sks-command.js +77 -16
  19. package/dist/core/commands/naruto-command.js +20 -3
  20. package/dist/core/doctor/doctor-readiness-matrix.js +7 -0
  21. package/dist/core/doctor/doctor-zellij-repair.js +36 -0
  22. package/dist/core/fsx.js +1 -1
  23. package/dist/core/hooks-runtime.js +13 -0
  24. package/dist/core/loops/loop-continuation-enforcer.js +32 -0
  25. package/dist/core/loops/loop-planner.js +9 -0
  26. package/dist/core/loops/loop-worker-runtime.js +5 -1
  27. package/dist/core/version.js +1 -1
  28. package/dist/core/zellij/homebrew-policy.js +45 -0
  29. package/dist/core/zellij/zellij-capability.js +32 -3
  30. package/dist/core/zellij/zellij-self-heal.js +353 -0
  31. package/dist/core/zellij/zellij-update.js +31 -6
  32. package/dist/scripts/sks-3-1-4-directive-check-lib.js +241 -0
  33. 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.2** hardens Loop Mesh for production use: fixture workers/gates/final arbiters are test-only, `gpt:final-arbiter` is explicitly finalizer-owned, integration merge uses a strategy ladder, side-effect reports come from loop diffs and mutation ledgers, loop kill interrupts active worker sessions, and global loop concurrency budgets prevent worker/model-call oversubscription. It remains Codex 0.139-aware while bundling @openai/codex-sdk 0.138.0 at this release boundary; see [docs/codex-0.139-compat.md](docs/codex-0.139-compat.md), [docs/codex-0.139-real-probes.md](docs/codex-0.139-real-probes.md), [docs/loop-fixture-policy.md](docs/loop-fixture-policy.md), and [docs/loop-merge-strategy.md](docs/loop-merge-strategy.md).
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
 
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "3.1.2"
79
+ version = "3.1.4"
80
80
  dependencies = [
81
81
  "serde_json",
82
82
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "3.1.2"
3
+ version = "3.1.4"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -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.2"),
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.2",
5
- "source_digest": "0312e2e27bae702aee9d6c07009b9492e43274c3d26e3b63a5140196997fea39",
6
- "source_file_count": 2448,
7
- "built_at_source_time": 1781367909038
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
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const FAST_PACKAGE_VERSION = '3.1.2';
2
+ const FAST_PACKAGE_VERSION = '3.1.4';
3
3
  const args = process.argv.slice(2);
4
4
  try {
5
5
  if (args[0] === '--agent' && args[1] === 'worker') {
@@ -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
@@ -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