sneakoscope 3.1.4 → 3.1.6
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 +8 -36
- 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/cli/command-registry.js +1 -2
- package/dist/cli/install-helpers.js +56 -4
- package/dist/commands/codex-app.js +1 -11
- package/dist/commands/codex-lb.js +12 -9
- package/dist/commands/codex-native.js +68 -0
- package/dist/commands/doctor.js +64 -0
- package/dist/core/codex-app/codex-agent-role-sync.js +69 -11
- package/dist/core/codex-app/codex-agent-type-probe.js +202 -0
- package/dist/core/codex-app/codex-app-execution-profile.js +43 -14
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +7 -4
- package/dist/core/codex-app/codex-app-harness-matrix.js +4 -65
- package/dist/core/codex-app/codex-app-types.js +21 -0
- package/dist/core/codex-app/codex-hook-approval-probe.js +188 -0
- package/dist/core/codex-app/codex-hook-lifecycle.js +34 -10
- package/dist/core/codex-app/codex-init-deep.js +154 -3
- package/dist/core/codex-app/codex-skill-sync.js +84 -9
- package/dist/core/codex-native/codex-native-capability-cache.js +21 -0
- package/dist/core/codex-native/codex-native-feature-broker.js +182 -0
- package/dist/core/codex-native/codex-native-feature-matrix.js +31 -0
- package/dist/core/codex-native/codex-native-harness-compat.js +54 -0
- package/dist/core/codex-native/codex-native-interop-policy.js +58 -0
- package/dist/core/codex-native/codex-native-invocation-router.js +112 -0
- package/dist/core/codex-native/codex-native-pattern-analysis.js +56 -0
- package/dist/core/codex-native/codex-native-reference-evidence.js +2 -0
- package/dist/core/codex-native/codex-native-reference-source.js +110 -0
- package/dist/core/codex-native/codex-native-rename-map.js +25 -0
- package/dist/core/commands/mad-sks-command.js +37 -2
- package/dist/core/commands/qa-loop-command.js +3 -2
- package/dist/core/commands/research-command.js +2 -2
- package/dist/core/doctor/doctor-zellij-repair.js +5 -1
- package/dist/core/feature-fixtures.js +3 -4
- package/dist/core/feature-registry.js +5 -2
- package/dist/core/fsx.js +1 -1
- package/dist/core/image/image-artifact-path-contract.js +18 -1
- package/dist/core/init.js +4 -1
- package/dist/core/loops/loop-continuation-enforcer.js +11 -3
- package/dist/core/loops/loop-owner-inference.js +3 -0
- package/dist/core/loops/loop-planner.js +28 -5
- package/dist/core/loops/loop-worker-runtime.js +52 -8
- package/dist/core/naruto/naruto-loop-worker-router.js +11 -2
- package/dist/core/qa-loop.js +62 -4
- package/dist/core/research/research-cycle-runner.js +1 -0
- package/dist/core/research/research-stage-runner.js +9 -2
- package/dist/core/research.js +68 -1
- package/dist/core/routes.js +2 -3
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/homebrew-policy.js +0 -1
- package/dist/core/zellij/zellij-self-heal-types.js +45 -0
- package/dist/core/zellij/zellij-self-heal.js +69 -8
- package/dist/core/zellij/zellij-update.js +9 -1
- package/dist/scripts/sks-3-1-4-directive-check-lib.js +1 -30
- package/dist/scripts/sks-3-1-5-directive-check-lib.js +318 -0
- package/dist/scripts/sks-3-1-6-directive-check-lib.js +522 -0
- package/package.json +53 -9
- package/dist/cli/hermes-command.js +0 -99
- package/dist/cli/openclaw-command.js +0 -83
- package/dist/commands/hermes.js +0 -5
- package/dist/commands/openclaw.js +0 -3
- package/dist/core/codex-app/lazycodex-analysis.js +0 -51
- package/dist/core/codex-app/lazycodex-interop-policy.js +0 -49
- package/dist/core/hermes.js +0 -192
- package/dist/core/openclaw.js +0 -171
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
import fs from 'node:fs/promises';
|
|
3
2
|
import path from 'node:path';
|
|
4
3
|
import os from 'node:os';
|
|
5
4
|
import { nowIso, writeJsonAtomic, writeTextAtomic, ensureDir } from '../fsx.js';
|
|
6
5
|
import { repairAgentRoleConfigs } from '../agents/agent-role-config.js';
|
|
6
|
+
import { agentRolePayloadFor, probeCodexAgentTypeSupport } from './codex-agent-type-probe.js';
|
|
7
7
|
const DIRECTIVE_ROLES = [
|
|
8
8
|
'sks-explorer',
|
|
9
9
|
'sks-planner',
|
|
@@ -15,6 +15,7 @@ const DIRECTIVE_ROLES = [
|
|
|
15
15
|
];
|
|
16
16
|
export async function syncCodexAgentRoles(input) {
|
|
17
17
|
const root = path.resolve(input.root);
|
|
18
|
+
const env = input.env || process.env;
|
|
18
19
|
const codexHome = input.codexHome || process.env.CODEX_HOME || path.join(os.homedir(), '.codex');
|
|
19
20
|
const targetDir = path.join(codexHome, 'agents');
|
|
20
21
|
const baseRepair = await repairAgentRoleConfigs({
|
|
@@ -22,46 +23,103 @@ export async function syncCodexAgentRoles(input) {
|
|
|
22
23
|
apply: input.apply === true,
|
|
23
24
|
codexHome,
|
|
24
25
|
reportPath: path.join(root, '.sneakoscope', 'reports', 'agent-role-config-repair.json')
|
|
25
|
-
}).catch((err) => ({ ok: false, blockers: [
|
|
26
|
+
}).catch((err) => ({ ok: false, blockers: [messageOf(err)] }));
|
|
27
|
+
const agentTypeProbe = input.agentTypeSupported === undefined
|
|
28
|
+
? await probeCodexAgentTypeSupport(root, { env }).catch((err) => ({
|
|
29
|
+
schema: 'sks.codex-agent-type-probe.v1',
|
|
30
|
+
generated_at: nowIso(),
|
|
31
|
+
ok: false,
|
|
32
|
+
supported: false,
|
|
33
|
+
source: 'unknown',
|
|
34
|
+
spawn_tool_name: 'unknown',
|
|
35
|
+
schema_path: null,
|
|
36
|
+
evidence: [],
|
|
37
|
+
blockers: [messageOf(err)],
|
|
38
|
+
warnings: ['agent_type_probe_failed_message_role_fallback']
|
|
39
|
+
}))
|
|
40
|
+
: {
|
|
41
|
+
schema: 'sks.codex-agent-type-probe.v1',
|
|
42
|
+
generated_at: nowIso(),
|
|
43
|
+
ok: true,
|
|
44
|
+
supported: input.agentTypeSupported,
|
|
45
|
+
source: 'fixture',
|
|
46
|
+
spawn_tool_name: input.agentTypeSupported ? 'spawn_agent' : 'unknown',
|
|
47
|
+
schema_path: input.agentTypeSupported ? 'input.agentTypeSupported' : null,
|
|
48
|
+
evidence: [`input.agentTypeSupported=${input.agentTypeSupported}`],
|
|
49
|
+
blockers: [],
|
|
50
|
+
warnings: []
|
|
51
|
+
};
|
|
52
|
+
const rolePayloads = Object.fromEntries(DIRECTIVE_ROLES.map((role) => [role, agentRolePayloadFor(role, agentTypeProbe)]));
|
|
26
53
|
const created = [];
|
|
27
54
|
if (input.apply === true) {
|
|
28
55
|
await ensureDir(targetDir);
|
|
29
56
|
for (const role of DIRECTIVE_ROLES) {
|
|
30
57
|
const file = path.join(targetDir, `${role}.toml`);
|
|
31
58
|
const current = await fs.readFile(file, 'utf8').catch(() => '');
|
|
32
|
-
if (current && !current.includes('SKS managed 3.1.4 directive role'))
|
|
59
|
+
if (current && !current.includes('SKS managed 3.1.4 directive role') && !current.includes('SKS managed 3.1.5 directive role') && !current.includes('SKS managed 3.1.6 directive role') && !current.includes('SKS managed 3.1.6 bounded role'))
|
|
33
60
|
continue;
|
|
34
|
-
await writeTextAtomic(file, roleToml(role));
|
|
61
|
+
await writeTextAtomic(file, roleToml(role, rolePayloads[role]));
|
|
35
62
|
created.push(file);
|
|
36
63
|
}
|
|
37
64
|
}
|
|
38
65
|
const report = {
|
|
39
66
|
schema: 'sks.codex-agent-role-sync.v1',
|
|
40
67
|
generated_at: nowIso(),
|
|
41
|
-
ok: baseRepair.ok !== false,
|
|
68
|
+
ok: recordOk(baseRepair) !== false && agentTypeProbe.ok !== false,
|
|
42
69
|
apply: input.apply === true,
|
|
43
|
-
agent_type_supported:
|
|
44
|
-
fallback:
|
|
70
|
+
agent_type_supported: agentTypeProbe.supported,
|
|
71
|
+
fallback: agentTypeProbe.supported ? 'agent_type' : 'message-role',
|
|
45
72
|
codex_home: codexHome,
|
|
46
73
|
directive_roles: DIRECTIVE_ROLES,
|
|
74
|
+
role_payloads: rolePayloads,
|
|
75
|
+
agent_type_probe: agentTypeProbe,
|
|
47
76
|
created,
|
|
48
77
|
base_repair: baseRepair,
|
|
49
|
-
blockers: baseRepair
|
|
78
|
+
blockers: blockersOf(baseRepair)
|
|
50
79
|
};
|
|
51
80
|
await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'codex-agent-role-sync.json'), report).catch(() => undefined);
|
|
52
81
|
return report;
|
|
53
82
|
}
|
|
54
|
-
function roleToml(role) {
|
|
83
|
+
function roleToml(role, payload) {
|
|
84
|
+
const strategyLine = payload?.strategy === 'agent_type'
|
|
85
|
+
? `agent_type = "${payload.agent_type || role}"`
|
|
86
|
+
: `message_role_prefix = "${escapeToml(payload?.message_role_prefix || `Role: ${role}.`)}"`;
|
|
55
87
|
return [
|
|
56
88
|
`name = "${role}"`,
|
|
57
|
-
`description = "SKS managed 3.1.
|
|
89
|
+
`description = "SKS managed 3.1.6 directive role: ${role}"`,
|
|
90
|
+
strategyLine,
|
|
58
91
|
'model_reasoning_effort = "medium"',
|
|
59
92
|
role.includes('implementer') ? 'sandbox_mode = "workspace-write"' : 'sandbox_mode = "read-only"',
|
|
60
93
|
'approval_policy = "never"',
|
|
61
94
|
'developer_instructions = """',
|
|
62
|
-
`You are ${role}. SKS managed 3.1.
|
|
95
|
+
`You are ${role}. SKS managed 3.1.6 directive role with bounded ownership.`,
|
|
96
|
+
'Bounded ownership: use only the assigned owner files/directories and treat memory as guidance, not permission.',
|
|
97
|
+
role.includes('implementer') ? 'Maker/checker separation: implementer may patch only owner scope and cannot self-approve.' : 'Maker/checker separation: checker is read-only and must reject missing gates or missing proof artifacts.',
|
|
98
|
+
role.includes('release') ? 'Release verifier: verify version truth, release DAG coverage, package scripts, packlist, and changelog evidence.' : '',
|
|
99
|
+
role.includes('zellij') ? 'UI/Zellij verifier: inspect readiness status, headless fallback, repair_required, pane proof, and slot telemetry without mutating unrelated UI state.' : '',
|
|
100
|
+
role.includes('codex') ? 'Codex native verifier: inspect hook approval, agent_type, skill sync, plugin inventory, MCP candidates, and invocation plan artifacts.' : '',
|
|
101
|
+
'Side effects: no destructive shell, package publish, global config mutation, database mutation, or external service write unless the sealed route contract explicitly allows it.',
|
|
102
|
+
'Required proof artifacts: cite concrete repo paths, command outputs, and route-local JSON proof before claiming completion.',
|
|
103
|
+
'Final arbiter: parent integration owns final acceptance; this role supplies evidence and cannot override missing gates.',
|
|
104
|
+
`Execution role strategy: ${payload?.strategy || 'message-role'}. Probe: ${payload?.probe_artifact_path || '.sneakoscope/reports/codex-agent-type-probe.json'}.`,
|
|
63
105
|
'"""',
|
|
64
106
|
''
|
|
65
107
|
].join('\n');
|
|
66
108
|
}
|
|
109
|
+
function blockersOf(value) {
|
|
110
|
+
return Boolean(value) && typeof value === 'object' && Array.isArray(value.blockers)
|
|
111
|
+
? (value.blockers).map((item) => String(item)).filter(Boolean)
|
|
112
|
+
: [];
|
|
113
|
+
}
|
|
114
|
+
function recordOk(value) {
|
|
115
|
+
return Boolean(value) && typeof value === 'object' && typeof value.ok === 'boolean'
|
|
116
|
+
? value.ok
|
|
117
|
+
: undefined;
|
|
118
|
+
}
|
|
119
|
+
function escapeToml(value) {
|
|
120
|
+
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
121
|
+
}
|
|
122
|
+
function messageOf(err) {
|
|
123
|
+
return err instanceof Error ? err.message : String(err);
|
|
124
|
+
}
|
|
67
125
|
//# sourceMappingURL=codex-agent-role-sync.js.map
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { findCodexBinary } from '../codex-adapter.js';
|
|
4
|
+
import { nowIso, runProcess, writeJsonAtomic } from '../fsx.js';
|
|
5
|
+
import { isRecord } from './codex-app-types.js';
|
|
6
|
+
export async function probeCodexAgentTypeSupport(root, input = {}) {
|
|
7
|
+
const env = input.env || process.env;
|
|
8
|
+
const fixture = await fixtureSchemaProbe(env);
|
|
9
|
+
if (fixture)
|
|
10
|
+
return persist(root, fixture, input.writeReport !== false);
|
|
11
|
+
const schema = await readSchemaFromEnv(env);
|
|
12
|
+
if (schema)
|
|
13
|
+
return persist(root, probeSchema(schema.value, schema.source, schema.schemaPath), input.writeReport !== false);
|
|
14
|
+
const doctor = await probeDoctorJson(input.codexBin, env);
|
|
15
|
+
if (doctor.source !== 'unknown')
|
|
16
|
+
return persist(root, doctor, input.writeReport !== false);
|
|
17
|
+
const help = await probeHelp(input.codexBin, env);
|
|
18
|
+
if (help.source !== 'unknown')
|
|
19
|
+
return persist(root, help, input.writeReport !== false);
|
|
20
|
+
const envProbe = envFallbackProbe(env);
|
|
21
|
+
if (envProbe)
|
|
22
|
+
return persist(root, envProbe, input.writeReport !== false);
|
|
23
|
+
return persist(root, {
|
|
24
|
+
schema: 'sks.codex-agent-type-probe.v1',
|
|
25
|
+
generated_at: nowIso(),
|
|
26
|
+
ok: true,
|
|
27
|
+
supported: false,
|
|
28
|
+
source: 'unknown',
|
|
29
|
+
spawn_tool_name: 'unknown',
|
|
30
|
+
schema_path: null,
|
|
31
|
+
evidence: [],
|
|
32
|
+
blockers: [],
|
|
33
|
+
warnings: ['agent_type_support_unknown_message_role_fallback']
|
|
34
|
+
}, input.writeReport !== false);
|
|
35
|
+
}
|
|
36
|
+
export function agentRolePayloadFor(role, probe) {
|
|
37
|
+
if (probe.supported)
|
|
38
|
+
return { strategy: 'agent_type', agent_type: role, probe_artifact_path: '.sneakoscope/reports/codex-agent-type-probe.json' };
|
|
39
|
+
return {
|
|
40
|
+
strategy: 'message-role',
|
|
41
|
+
message_role_prefix: `Role: ${role}. Use this as a message-level role because native agent_type is unavailable or unverified.`,
|
|
42
|
+
probe_artifact_path: '.sneakoscope/reports/codex-agent-type-probe.json'
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function fixtureSchemaProbe(env) {
|
|
46
|
+
const raw = env.SKS_CODEX_AGENT_TYPE_FIXTURE;
|
|
47
|
+
if (!raw)
|
|
48
|
+
return null;
|
|
49
|
+
const supported = raw === '1' || raw === 'supported' || raw === 'true';
|
|
50
|
+
return {
|
|
51
|
+
schema: 'sks.codex-agent-type-probe.v1',
|
|
52
|
+
generated_at: nowIso(),
|
|
53
|
+
ok: true,
|
|
54
|
+
supported,
|
|
55
|
+
source: 'fixture',
|
|
56
|
+
spawn_tool_name: supported ? 'spawn_agent' : 'unknown',
|
|
57
|
+
schema_path: supported ? 'fixture.spawn_agent.parameters.agent_type' : null,
|
|
58
|
+
evidence: [`fixture:${raw}`],
|
|
59
|
+
blockers: [],
|
|
60
|
+
warnings: []
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async function readSchemaFromEnv(env) {
|
|
64
|
+
if (env.SKS_CODEX_TOOL_SCHEMA_FILE) {
|
|
65
|
+
const file = path.resolve(env.SKS_CODEX_TOOL_SCHEMA_FILE);
|
|
66
|
+
const text = await fs.readFile(file, 'utf8').catch(() => '');
|
|
67
|
+
if (text)
|
|
68
|
+
return { value: JSON.parse(text), source: 'codex-tool-schema', schemaPath: file };
|
|
69
|
+
}
|
|
70
|
+
if (env.SKS_CODEX_TOOL_SCHEMA_JSON) {
|
|
71
|
+
return { value: JSON.parse(env.SKS_CODEX_TOOL_SCHEMA_JSON), source: 'codex-tool-schema', schemaPath: 'env:SKS_CODEX_TOOL_SCHEMA_JSON' };
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
async function probeDoctorJson(codexBin, env) {
|
|
76
|
+
const bin = codexBin || env.CODEX_BIN || await findCodexBinary().catch(() => null);
|
|
77
|
+
if (!bin)
|
|
78
|
+
return unknownProbe(['codex_cli_missing']);
|
|
79
|
+
const run = await runProcess(bin, ['doctor', '--json'], { env, timeoutMs: 8000, maxOutputBytes: 256 * 1024 }).catch(() => null);
|
|
80
|
+
const text = `${run?.stdout || ''}${run?.stderr || ''}`.trim();
|
|
81
|
+
if (!run || run.code !== 0 || !text)
|
|
82
|
+
return unknownProbe(['codex_doctor_json_unavailable']);
|
|
83
|
+
try {
|
|
84
|
+
const parsed = JSON.parse(text);
|
|
85
|
+
const probed = probeSchema(parsed, 'codex-doctor-json', 'doctor-json');
|
|
86
|
+
return { ...probed, source: probed.supported ? 'codex-doctor-json' : 'unknown' };
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return unknownProbe(['codex_doctor_json_parse_failed']);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function probeHelp(codexBin, env) {
|
|
93
|
+
const bin = codexBin || env.CODEX_BIN || await findCodexBinary().catch(() => null);
|
|
94
|
+
if (!bin)
|
|
95
|
+
return unknownProbe(['codex_cli_missing']);
|
|
96
|
+
const run = await runProcess(bin, ['--help'], { env, timeoutMs: 5000, maxOutputBytes: 128 * 1024 }).catch(() => null);
|
|
97
|
+
const text = `${run?.stdout || ''}${run?.stderr || ''}`;
|
|
98
|
+
if (!run || run.code !== 0 || !text)
|
|
99
|
+
return unknownProbe(['codex_help_unavailable']);
|
|
100
|
+
const supported = /\bagent_type\b/.test(text) && /\bspawn_agent\b|\bmulti_agent_v2\b/.test(text);
|
|
101
|
+
return {
|
|
102
|
+
schema: 'sks.codex-agent-type-probe.v1',
|
|
103
|
+
generated_at: nowIso(),
|
|
104
|
+
ok: true,
|
|
105
|
+
supported,
|
|
106
|
+
source: supported ? 'codex-help' : 'unknown',
|
|
107
|
+
spawn_tool_name: text.includes('multi_agent_v2') ? 'multi_agent_v2' : supported ? 'spawn_agent' : 'unknown',
|
|
108
|
+
schema_path: supported ? 'codex --help' : null,
|
|
109
|
+
evidence: supported ? ['help_mentions_agent_type'] : [],
|
|
110
|
+
blockers: [],
|
|
111
|
+
warnings: supported ? [] : ['agent_type_not_found_in_help']
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function envFallbackProbe(env) {
|
|
115
|
+
if (env.SKS_CODEX_AGENT_TYPE_SUPPORTED === undefined)
|
|
116
|
+
return null;
|
|
117
|
+
if (env.SKS_CODEX_AGENT_TYPE_ALLOW_ENV_FALLBACK !== '1' && env.NODE_ENV !== 'test') {
|
|
118
|
+
return {
|
|
119
|
+
schema: 'sks.codex-agent-type-probe.v1',
|
|
120
|
+
generated_at: nowIso(),
|
|
121
|
+
ok: true,
|
|
122
|
+
supported: false,
|
|
123
|
+
source: 'env',
|
|
124
|
+
spawn_tool_name: 'unknown',
|
|
125
|
+
schema_path: null,
|
|
126
|
+
evidence: [],
|
|
127
|
+
blockers: [],
|
|
128
|
+
warnings: ['env_agent_type_fallback_ignored_outside_test_mode']
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const supported = env.SKS_CODEX_AGENT_TYPE_SUPPORTED === '1';
|
|
132
|
+
return {
|
|
133
|
+
schema: 'sks.codex-agent-type-probe.v1',
|
|
134
|
+
generated_at: nowIso(),
|
|
135
|
+
ok: true,
|
|
136
|
+
supported,
|
|
137
|
+
source: 'env',
|
|
138
|
+
spawn_tool_name: supported ? 'spawn_agent' : 'unknown',
|
|
139
|
+
schema_path: supported ? 'env:SKS_CODEX_AGENT_TYPE_SUPPORTED' : null,
|
|
140
|
+
evidence: [`env:SKS_CODEX_AGENT_TYPE_SUPPORTED=${env.SKS_CODEX_AGENT_TYPE_SUPPORTED}`],
|
|
141
|
+
blockers: [],
|
|
142
|
+
warnings: ['env_agent_type_fallback_test_only']
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function probeSchema(value, source, schemaPath) {
|
|
146
|
+
const found = findAgentType(value);
|
|
147
|
+
return {
|
|
148
|
+
schema: 'sks.codex-agent-type-probe.v1',
|
|
149
|
+
generated_at: nowIso(),
|
|
150
|
+
ok: true,
|
|
151
|
+
supported: found.supported,
|
|
152
|
+
source,
|
|
153
|
+
spawn_tool_name: found.tool,
|
|
154
|
+
schema_path: found.path || schemaPath,
|
|
155
|
+
evidence: found.supported ? [`agent_type:${found.path || 'found'}`] : ['agent_type_absent'],
|
|
156
|
+
blockers: [],
|
|
157
|
+
warnings: found.supported ? [] : ['agent_type_not_supported_message_role_fallback']
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function findAgentType(value, trail = []) {
|
|
161
|
+
if (Array.isArray(value)) {
|
|
162
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
163
|
+
const found = findAgentType(value[index], [...trail, String(index)]);
|
|
164
|
+
if (found.supported)
|
|
165
|
+
return found;
|
|
166
|
+
}
|
|
167
|
+
return { supported: false, tool: 'unknown', path: null };
|
|
168
|
+
}
|
|
169
|
+
if (!isRecord(value))
|
|
170
|
+
return { supported: false, tool: 'unknown', path: null };
|
|
171
|
+
const name = String(value.name || value.tool || value.id || '');
|
|
172
|
+
const tool = name.includes('multi_agent_v2') ? 'multi_agent_v2' : name.includes('spawn_agent') ? 'spawn_agent' : 'unknown';
|
|
173
|
+
if ('agent_type' in value || isRecord(value.properties) && 'agent_type' in value.properties) {
|
|
174
|
+
return { supported: true, tool: tool === 'unknown' ? 'spawn_agent' : tool, path: [...trail, 'agent_type'].join('.') };
|
|
175
|
+
}
|
|
176
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
177
|
+
const found = findAgentType(entry, [...trail, key]);
|
|
178
|
+
if (found.supported)
|
|
179
|
+
return { ...found, tool: found.tool === 'unknown' && tool !== 'unknown' ? tool : found.tool };
|
|
180
|
+
}
|
|
181
|
+
return { supported: false, tool, path: null };
|
|
182
|
+
}
|
|
183
|
+
function unknownProbe(blockers) {
|
|
184
|
+
return {
|
|
185
|
+
schema: 'sks.codex-agent-type-probe.v1',
|
|
186
|
+
generated_at: nowIso(),
|
|
187
|
+
ok: blockers.length === 0,
|
|
188
|
+
supported: false,
|
|
189
|
+
source: 'unknown',
|
|
190
|
+
spawn_tool_name: 'unknown',
|
|
191
|
+
schema_path: null,
|
|
192
|
+
evidence: [],
|
|
193
|
+
blockers,
|
|
194
|
+
warnings: ['agent_type_support_unknown_message_role_fallback']
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
async function persist(root, report, writeReport) {
|
|
198
|
+
if (writeReport)
|
|
199
|
+
await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'codex-agent-type-probe.json'), report).catch(() => undefined);
|
|
200
|
+
return report;
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=codex-agent-type-probe.js.map
|
|
@@ -1,32 +1,61 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
import path from 'node:path';
|
|
3
2
|
import { nowIso, writeJsonAtomic } from '../fsx.js';
|
|
4
3
|
import { buildCodexAppHarnessMatrix } from './codex-app-harness-matrix.js';
|
|
4
|
+
import { isCodexAppHarnessMatrix } from './codex-app-types.js';
|
|
5
|
+
import { buildCodexNativeFeatureMatrix } from '../codex-native/codex-native-feature-broker.js';
|
|
5
6
|
export async function resolveCodexAppExecutionProfile(input = { root: process.cwd() }) {
|
|
6
7
|
const root = path.resolve(input.root || process.cwd());
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
const nativeMatrix = await buildCodexNativeFeatureMatrix({ root }).catch(() => null);
|
|
9
|
+
const maybeMatrix = input.matrix || (nativeMatrix ? null : await buildCodexAppHarnessMatrix({ root }).catch(() => null));
|
|
10
|
+
const matrix = isCodexAppHarnessMatrix(maybeMatrix) ? maybeMatrix : null;
|
|
11
|
+
const mode = nativeMatrix
|
|
12
|
+
? modeFromNative(nativeMatrix)
|
|
13
|
+
: !matrix?.codex_cli.available
|
|
14
|
+
? 'degraded-no-app'
|
|
15
|
+
: matrix.app_features.app_handoff_ready && matrix.app_features.agent_type_supported
|
|
16
|
+
? 'codex-app-native'
|
|
17
|
+
: matrix.codex_cli.available
|
|
18
|
+
? 'codex-cli-headless'
|
|
19
|
+
: 'sks-loop-headless';
|
|
20
|
+
const agentRoleStrategy = nativeMatrix?.invocation_defaults.loop_worker_role_strategy || (matrix?.app_features.agent_type_supported ? 'agent_type' : 'message-role');
|
|
21
|
+
const hookApprovalState = hookApprovalStateFrom(nativeMatrix) || matrix?.app_features.hook_approval_state || 'unknown';
|
|
15
22
|
const profile = {
|
|
16
23
|
schema: 'sks.codex-app-execution-profile.v1',
|
|
17
24
|
generated_at: nowIso(),
|
|
18
25
|
ok: mode !== 'degraded-no-app',
|
|
19
26
|
mode,
|
|
20
|
-
agent_role_strategy:
|
|
27
|
+
agent_role_strategy: agentRoleStrategy,
|
|
21
28
|
hooks_assumed_running: false,
|
|
22
|
-
hooks_approval_required:
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
hooks_approval_required: hookApprovalState !== 'approved',
|
|
30
|
+
hook_approval_state: hookApprovalState,
|
|
31
|
+
app_handoff_ready: nativeMatrix?.features.app_handoff.ok === true || matrix?.app_features.app_handoff_ready === true,
|
|
32
|
+
image_path_exposure_ready: nativeMatrix?.features.image_path_exposure.ok === true || matrix?.app_features.image_path_exposure_ready === true,
|
|
33
|
+
plugin_mcp_inventory_ready: nativeMatrix?.features.mcp_inventory.ok === true || matrix?.app_features.mcp_inventory_ready === true,
|
|
25
34
|
loop_mesh_app_profile_available: true,
|
|
35
|
+
artifact_path: '.sneakoscope/reports/codex-app-execution-profile.json',
|
|
36
|
+
matrix_artifact_path: nativeMatrix ? '.sneakoscope/reports/codex-native-feature-matrix.json' : '.sneakoscope/reports/codex-app-harness-matrix.json',
|
|
37
|
+
agent_type_probe_artifact_path: '.sneakoscope/reports/codex-agent-type-probe.json',
|
|
38
|
+
hook_approval_probe_artifact_path: '.sneakoscope/reports/codex-hook-approval-probe.json',
|
|
26
39
|
blockers: mode === 'degraded-no-app' ? ['codex_cli_missing'] : [],
|
|
27
|
-
warnings: matrix?.warnings || []
|
|
40
|
+
warnings: nativeMatrix?.warnings || matrix?.warnings || []
|
|
28
41
|
};
|
|
29
42
|
await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'codex-app-execution-profile.json'), profile).catch(() => undefined);
|
|
30
43
|
return profile;
|
|
31
44
|
}
|
|
45
|
+
function modeFromNative(matrix) {
|
|
46
|
+
if (!matrix.codex_cli.available)
|
|
47
|
+
return 'degraded-no-app';
|
|
48
|
+
if (matrix.features.app_handoff.ok && matrix.features.agent_type.ok)
|
|
49
|
+
return 'codex-app-native';
|
|
50
|
+
return 'codex-cli-headless';
|
|
51
|
+
}
|
|
52
|
+
function hookApprovalStateFrom(matrix) {
|
|
53
|
+
const probe = matrix?.probes.hook_approval;
|
|
54
|
+
if (!probe || typeof probe !== 'object' || Array.isArray(probe))
|
|
55
|
+
return null;
|
|
56
|
+
const state = probe.approval_state;
|
|
57
|
+
return state === 'approved' || state === 'pending_review' || state === 'modified_requires_reapproval' || state === 'not_installed' || state === 'unknown'
|
|
58
|
+
? state
|
|
59
|
+
: null;
|
|
60
|
+
}
|
|
32
61
|
//# sourceMappingURL=codex-app-execution-profile.js.map
|
|
@@ -4,8 +4,9 @@ import { ensureDir, nowIso, readText, sha256, writeJsonAtomic, writeTextAtomic }
|
|
|
4
4
|
import { codexHome, scanProjectLocalForbiddenKeys, snapshotCodexAppUiState } from './codex-app-ui-state-snapshot.js';
|
|
5
5
|
import { assertCodexAppUiMutationAllowed } from './codex-app-ui-clobber-guard.js';
|
|
6
6
|
export const CODEX_APP_FAST_UI_REPAIR_SCHEMA = 'sks.codex-app-fast-ui-repair.v1';
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const FAST_UI_TOP_LEVEL_RE = /^\s*service_tier\s*=/;
|
|
8
|
+
const FAST_UI_FEATURE_LINE_RE = /^\s*fast_mode\s*=/;
|
|
9
|
+
const FAST_UI_USER_TABLE_LINE_RE = /^\s*(enabled|visible|locked|hidden|disabled)\s*=/;
|
|
9
10
|
const SKS_CAUSED_RE = /(?:SKS|Sneakoscope|codex-lb|sks-mad|sks fast)/i;
|
|
10
11
|
export async function repairCodexAppFastUi(root = process.cwd(), input = {}) {
|
|
11
12
|
const resolvedRoot = path.resolve(root);
|
|
@@ -124,8 +125,10 @@ function stripProjectLocalForbiddenKeys(text) {
|
|
|
124
125
|
}
|
|
125
126
|
function stripSksCausedHostOwnedLines(text) {
|
|
126
127
|
return stripMatchingLines(text, (line, table, previous, next) => {
|
|
127
|
-
const
|
|
128
|
-
|
|
128
|
+
const isFastUiLine = FAST_UI_TOP_LEVEL_RE.test(line)
|
|
129
|
+
|| (table === 'features' && FAST_UI_FEATURE_LINE_RE.test(line))
|
|
130
|
+
|| (table === 'user.fast_mode' && FAST_UI_USER_TABLE_LINE_RE.test(line));
|
|
131
|
+
return isFastUiLine && (SKS_CAUSED_RE.test(line) || SKS_CAUSED_RE.test(previous) || SKS_CAUSED_RE.test(next));
|
|
129
132
|
});
|
|
130
133
|
}
|
|
131
134
|
function stripMatchingLines(text, shouldRemove) {
|
|
@@ -1,66 +1,9 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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';
|
|
2
|
+
import { writeJsonAtomic } from '../fsx.js';
|
|
3
|
+
import { buildCodexAppHarnessMatrixFromNative } from '../codex-native/codex-native-harness-compat.js';
|
|
12
4
|
export async function buildCodexAppHarnessMatrix(input = { root: process.cwd() }) {
|
|
13
|
-
const
|
|
14
|
-
|
|
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);
|
|
5
|
+
const matrix = await buildCodexAppHarnessMatrixFromNative(input);
|
|
6
|
+
await writeCodexAppHarnessMatrix(path.resolve(input.root || process.cwd()), matrix, input.missionDir);
|
|
64
7
|
return matrix;
|
|
65
8
|
}
|
|
66
9
|
export async function writeCodexAppHarnessMatrix(root, matrix, missionDir) {
|
|
@@ -68,8 +11,4 @@ export async function writeCodexAppHarnessMatrix(root, matrix, missionDir) {
|
|
|
68
11
|
if (missionDir)
|
|
69
12
|
await writeJsonAtomic(path.join(missionDir, 'codex-app-harness-matrix.json'), matrix).catch(() => undefined);
|
|
70
13
|
}
|
|
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
14
|
//# sourceMappingURL=codex-app-harness-matrix.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function isRecord(value) {
|
|
2
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
export function stringList(value) {
|
|
5
|
+
return Array.isArray(value) ? value.map((item) => String(item)).filter(Boolean) : [];
|
|
6
|
+
}
|
|
7
|
+
export function isCodexAppHarnessMatrix(value) {
|
|
8
|
+
if (!isRecord(value))
|
|
9
|
+
return false;
|
|
10
|
+
if (value.schema !== 'sks.codex-app-harness-matrix.v1')
|
|
11
|
+
return false;
|
|
12
|
+
const app = value.app_features;
|
|
13
|
+
const sks = value.sks_integrations;
|
|
14
|
+
return isRecord(app)
|
|
15
|
+
&& isRecord(sks)
|
|
16
|
+
&& typeof value.ok === 'boolean'
|
|
17
|
+
&& isRecord(value.codex_cli)
|
|
18
|
+
&& Array.isArray(value.blockers)
|
|
19
|
+
&& Array.isArray(value.warnings);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=codex-app-types.js.map
|