sneakoscope 4.6.5 → 4.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +18 -4
  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/bin/sks.js +1 -1
  6. package/dist/cli/install-helpers.js +80 -15
  7. package/dist/commands/codex-app.js +34 -3
  8. package/dist/commands/doctor.js +1 -1
  9. package/dist/core/agents/agent-effort-policy.js +110 -5
  10. package/dist/core/agents/agent-orchestrator.js +27 -3
  11. package/dist/core/agents/agent-plan.js +2 -2
  12. package/dist/core/agents/agent-roster.js +8 -0
  13. package/dist/core/agents/agent-worker-slot.js +4 -0
  14. package/dist/core/codex/agent-config-file-repair.js +4 -4
  15. package/dist/core/codex-app/codex-app-fast-ui-repair.js +4 -2
  16. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +14 -3
  17. package/dist/core/codex-app/glm-model-profile.js +1 -1
  18. package/dist/core/codex-app/glm-profile-installer.js +111 -7
  19. package/dist/core/codex-app/glm-profile-schema.js +21 -2
  20. package/dist/core/codex-app.js +2 -0
  21. package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
  22. package/dist/core/codex-model-guard.js +3 -1
  23. package/dist/core/commands/fast-mode-command.js +5 -2
  24. package/dist/core/commands/glm-command.js +2 -1
  25. package/dist/core/commands/mad-sks-command.js +24 -0
  26. package/dist/core/doctor/doctor-codex-startup-repair.js +111 -9
  27. package/dist/core/feature-registry.js +3 -3
  28. package/dist/core/fsx.js +1 -1
  29. package/dist/core/harness-guard.js +89 -3
  30. package/dist/core/init.js +13 -16
  31. package/dist/core/managed-assets/managed-assets-manifest.js +9 -8
  32. package/dist/core/pipeline-internals/runtime-core.js +3 -3
  33. package/dist/core/providers/glm/glm-52-profile.js +46 -0
  34. package/dist/core/providers/glm/glm-52-request.js +11 -2
  35. package/dist/core/providers/glm/glm-direct-run.js +1 -0
  36. package/dist/core/providers/glm/glm-mad-launch.js +3 -2
  37. package/dist/core/providers/glm/glm-profile-resolver.js +69 -4
  38. package/dist/core/providers/glm/naruto/glm-naruto-command.js +2 -1
  39. package/dist/core/team-live.js +2 -2
  40. package/dist/core/version.js +1 -1
  41. package/dist/scripts/agent-role-config-repair-check.js +5 -3
  42. package/dist/scripts/codex-native-reference-cache-check.js +8 -1
  43. package/dist/scripts/doctor-codex-startup-repair-check.js +21 -0
  44. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +6 -2
  45. package/dist/scripts/naruto-shadow-clone-swarm-check.js +11 -3
  46. package/dist/scripts/release-readiness-report.js +1 -1
  47. package/dist/scripts/sks-3-1-6-directive-check-lib.js +11 -0
  48. package/package.json +1 -1
@@ -154,7 +154,7 @@ export function buildAllFeaturesSelftest(registry, opts = {}) {
154
154
  checkRow('native_agent_intake_contract_present', registry.features.some((feature) => feature.id === 'route-native-agent-intake'), ['route-native-agent-intake']),
155
155
  checkRow('cli_agent_fixture_pass', registry.features.some((feature) => feature.id === 'cli-agent' && feature.fixture?.status === 'pass' && feature.fixture.expected_artifacts?.some((artifact) => expectedArtifactPath(artifact).includes('agent-proof-evidence'))), ['cli-agent']),
156
156
  checkRow('agent_proof_evidence_contract_present', registry.features.some((feature) => feature.id === 'proof-agent-evidence'), ['proof-agent-evidence']),
157
- checkRow('agent_lease_policy_present', registry.features.some((feature) => feature.id === 'route-native-agent-intake' && /read-only/i.test(JSON.stringify(feature.contract || {})) && /lease/i.test(JSON.stringify(feature.contract || {}))), ['route-native-agent-intake']),
157
+ checkRow('agent_lease_policy_present', registry.features.some((feature) => feature.id === 'route-native-agent-intake' && /bounded workspace-write/i.test(JSON.stringify(feature.contract || {})) && /lease/i.test(JSON.stringify(feature.contract || {}))), ['route-native-agent-intake']),
158
158
  checkRow('fixture_pass_threshold', (fixturesSummary.counts.pass || 0) >= 90, [`pass=${fixturesSummary.counts.pass || 0}`]),
159
159
  checkRow('fixture_not_required_ceiling', (fixturesSummary.counts.not_required || 0) <= 16, [`not_required=${fixturesSummary.counts.not_required || 0}`]),
160
160
  checkRow('fixture_mock_blocked_zero', (fixturesSummary.counts.blocked || 0) === 0, [`blocked=${fixturesSummary.counts.blocked || 0}`]),
@@ -628,7 +628,7 @@ function nativeAgentIntakeFeature() {
628
628
  aliases: ['sks team "task" [executor:5 reviewer:6 user:1]'],
629
629
  category: 'proof-route',
630
630
  maturity: 'stable',
631
- intent: 'Default read-only native multi-session agent intake before serious route implementation.',
631
+ intent: 'Default bounded workspace-write native multi-session agent intake before serious route implementation.',
632
632
  voxel_triwiki_integration: 'native agent findings are TriWiki-ready and can require image voxel evidence for visual routes',
633
633
  completion_proof_integration: 'Completion Proof evidence.agents records agent_count, route, leases, no-overlap proof, cleanup, proof graph, and dynamic effort policy',
634
634
  known_gaps: ['real speedup claims require runtime timing/eval evidence; mock/static timing is not enough'],
@@ -636,7 +636,7 @@ function nativeAgentIntakeFeature() {
636
636
  input: 'serious route mission, route collaboration fixture, or explicit sks agent run',
637
637
  output: 'agents/agent-central-ledger.json, agents/agent-task-board.json, agents/agent-leases.json, agents/agent-no-overlap-proof.json, agents/agent-session-cleanup.json, agents/agent-proof-evidence.json, agents/agent-effort-policy.json',
638
638
  state: 'mission-local native agent artifacts',
639
- safety: 'read-only analysis agents; central leases prevent overlapping write scopes; parent owns integration',
639
+ safety: 'bounded workspace-write analysis agents; central leases prevent overlapping write scopes; parent owns integration',
640
640
  proof: 'evidence.agents required for serious native route proof',
641
641
  voxel: 'visual agent records image voxel requirements without satisfying visual evidence by itself',
642
642
  tests: 'unit, integration, e2e route fixtures, native release gate scripts',
package/dist/core/fsx.js CHANGED
@@ -5,7 +5,7 @@ import os from 'node:os';
5
5
  import crypto from 'node:crypto';
6
6
  import { spawn } from 'node:child_process';
7
7
  import { fileURLToPath } from 'node:url';
8
- export const PACKAGE_VERSION = '4.6.5';
8
+ export const PACKAGE_VERSION = '4.7.0';
9
9
  export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
10
10
  export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
11
11
  export function nowIso() {
@@ -125,8 +125,9 @@ export function classifyHarnessPayload(root, payload = {}, policy = {}) {
125
125
  const command = extractCommand(payload);
126
126
  const writeIntent = hasWriteIntent(toolName, command, hay);
127
127
  const maintenance = classifyMaintenanceCommand(command || hay);
128
- const protectedMatches = findProtectedMatches(root, strings, policy);
129
- const packageEdit = writeIntent && /\b(package\.json|package-lock\.json|pnpm-lock\.yaml|yarn\.lock)\b/i.test(hay) && /\bsneakoscope\b/i.test(hay);
128
+ const writeTargets = extractWriteTargets(root, payload, strings, command);
129
+ const protectedMatches = findProtectedMatches(root, writeTargets.length ? writeTargets : strings, policy);
130
+ const packageEdit = writeIntent && packageManifestEditDetected(writeTargets, hay);
130
131
  const block = maintenance.block || packageEdit || (writeIntent && protectedMatches.length > 0);
131
132
  const reasons = [];
132
133
  if (maintenance.block)
@@ -135,7 +136,7 @@ export function classifyHarnessPayload(root, payload = {}, policy = {}) {
135
136
  reasons.push('package_manifest_sneakoscope_edit_blocked');
136
137
  if (writeIntent && protectedMatches.length)
137
138
  reasons.push('protected_harness_path_write_blocked');
138
- return { block, reasons: [...new Set(reasons)], matches: protectedMatches, writeIntent, toolName, command };
139
+ return { block, reasons: [...new Set(reasons)], matches: protectedMatches, writeIntent, toolName, command, writeTargets };
139
140
  }
140
141
  export async function collectHarnessFingerprints(root) {
141
142
  const out = {};
@@ -196,6 +197,91 @@ function collectPayloadStrings(obj, out = [], depth = 0) {
196
197
  }
197
198
  return out;
198
199
  }
200
+ function extractWriteTargets(root, payload = {}, strings = [], command = '') {
201
+ const targets = new Set();
202
+ for (const value of collectPathFieldStrings(payload))
203
+ addWriteTarget(root, targets, value);
204
+ for (const text of [command, ...strings]) {
205
+ const s = String(text || '');
206
+ for (const match of s.matchAll(/^\*\*\*\s+(?:Update|Add|Delete)\s+File:\s+(.+)$/gmi))
207
+ addWriteTarget(root, targets, match[1]);
208
+ for (const match of s.matchAll(/^\*\*\*\s+Move to:\s+(.+)$/gmi))
209
+ addWriteTarget(root, targets, match[1]);
210
+ for (const match of s.matchAll(/>{1,2}\s*(['"]?)([^\s;&|'"`]+)\1/g))
211
+ addWriteTarget(root, targets, match[2]);
212
+ collectShellCommandTargets(root, targets, s);
213
+ }
214
+ return [...targets].sort();
215
+ }
216
+ function collectPathFieldStrings(obj, out = [], depth = 0) {
217
+ if (depth > 8 || obj == null)
218
+ return out;
219
+ if (Array.isArray(obj)) {
220
+ for (const value of obj)
221
+ collectPathFieldStrings(value, out, depth + 1);
222
+ return out;
223
+ }
224
+ if (typeof obj !== 'object')
225
+ return out;
226
+ for (const [key, value] of Object.entries(obj)) {
227
+ const normalized = String(key || '').toLowerCase();
228
+ if (typeof value === 'string' && /^(?:path|file|filename|target|destination|dest|to|from|cwd|workdir|file_path|target_path|output_path|artifact_path)$/.test(normalized))
229
+ out.push(value);
230
+ collectPathFieldStrings(value, out, depth + 1);
231
+ }
232
+ return out;
233
+ }
234
+ function collectShellCommandTargets(root, targets, text) {
235
+ const words = shellWords(text);
236
+ for (let i = 0; i < words.length; i += 1) {
237
+ const word = words[i] || '';
238
+ if (!/^(?:rm|rmdir|mv|cp|touch|mkdir|chmod|chown)$/.test(word))
239
+ continue;
240
+ for (let j = i + 1; j < words.length; j += 1) {
241
+ const candidate = words[j] || '';
242
+ if (!candidate || candidate.startsWith('-'))
243
+ continue;
244
+ if (/^(?:&&|\|\||;|\|)$/.test(candidate))
245
+ break;
246
+ if (/^(?:rm|rmdir|mv|cp|touch|mkdir|chmod|chown|git|npm|node|python\d?)$/.test(candidate) && j > i + 1)
247
+ break;
248
+ addWriteTarget(root, targets, candidate);
249
+ }
250
+ }
251
+ }
252
+ function shellWords(text) {
253
+ return [...String(text || '').matchAll(/"([^"]*)"|'([^']*)'|([^\s]+)/g)].map((match) => match[1] || match[2] || match[3]).filter(Boolean);
254
+ }
255
+ function addWriteTarget(root, targets, value) {
256
+ const normalized = normalizeTargetPath(root, value);
257
+ if (normalized)
258
+ targets.add(normalized);
259
+ }
260
+ function normalizeTargetPath(root, value) {
261
+ let s = String(value || '').trim();
262
+ if (!s)
263
+ return '';
264
+ s = s.replace(/^['"`<]+|['"`>,]+$/g, '');
265
+ if (!s || /^\$[\w{]/.test(s) || /^[A-Z_][A-Z0-9_]*=/.test(s))
266
+ return '';
267
+ if (/^(?:--?|&&|\|\||;|\|)$/.test(s))
268
+ return '';
269
+ s = s.replace(/\\/g, '/');
270
+ if (s.startsWith('a/') || s.startsWith('b/'))
271
+ s = s.slice(2);
272
+ if (s.startsWith('./'))
273
+ s = s.slice(2);
274
+ const rootNorm = String(root || '').replace(/\\/g, '/').replace(/\/$/, '');
275
+ if (rootNorm && s.startsWith(`${rootNorm}/`))
276
+ s = s.slice(rootNorm.length + 1);
277
+ return s.replace(/\/$/, '');
278
+ }
279
+ function packageManifestEditDetected(writeTargets, hay) {
280
+ const hasPackageTarget = writeTargets.length > 0
281
+ ? writeTargets.some((target) => /(^|\/)(?:package\.json|package-lock\.json|pnpm-lock\.yaml|yarn\.lock)$/.test(target))
282
+ : /\b(package\.json|package-lock\.json|pnpm-lock\.yaml|yarn\.lock)\b/i.test(hay);
283
+ return hasPackageTarget && /\bsneakoscope\b/i.test(hay);
284
+ }
199
285
  function hasWriteIntent(toolName, command, hay) {
200
286
  if (/\b(apply_patch|edit|write|create|delete|remove|rename|str_replace|file_write|fs_write)\b/i.test(toolName))
201
287
  return true;
package/dist/core/init.js CHANGED
@@ -69,8 +69,7 @@ export function hasTopLevelCodexModeLock(text = '') {
69
69
  const lines = String(text || '').split('\n');
70
70
  const firstTable = lines.findIndex((x) => /^\s*\[.+\]\s*$/.test(x));
71
71
  const top = (firstTable === -1 ? lines : lines.slice(0, firstTable)).join('\n');
72
- const model = top.match(/^model\s*=\s*"([^"]+)"/m)?.[1];
73
- return (Boolean(model) && model !== 'gpt-5.5') || /^model_reasoning_effort\s*=/m.test(top);
72
+ return /^model\s*=/.test(top) || /^model_reasoning_effort\s*=/m.test(top);
74
73
  }
75
74
  export function hasDeprecatedCodexHooksFeatureFlag(text = '') {
76
75
  const lines = String(text || '').split('\n');
@@ -590,10 +589,8 @@ export async function initProject(root, opts = {}) {
590
589
  let next = removeLegacyTopLevelCodexModeLocks(String(existingContent || '').trimEnd());
591
590
  next = removeTomlTableKey(next, 'notice', 'fast_default_opt_out');
592
591
  next = removeTomlTableKey(next, 'features', 'codex_hooks');
593
- // User-overridable top-level keys: seed defaults only when ABSENT so an
594
- // upgrade never clobbers a user's chosen model/service_tier. model_reasoning_effort
595
- // is intentionally left untouched at the top level.
596
- next = upsertTopLevelTomlStringIfAbsent(next, 'model', 'gpt-5.5');
592
+ // Model/reasoning defaults live in profiles. Leaving them out of top-level config
593
+ // keeps Codex Desktop's native model and speed selectors available.
597
594
  next = upsertTopLevelTomlBooleanIfAbsent(next, 'suppress_unstable_features_warning', true);
598
595
  // Codex App feature flags: SET-IF-ABSENT only (see note above).
599
596
  for (const flag of MANAGED_CODEX_FEATURE_FLAGS) {
@@ -704,7 +701,7 @@ export async function initProject(root, opts = {}) {
704
701
  return lines.filter((line, index) => {
705
702
  if (index >= end)
706
703
  return true;
707
- return !/^\s*model_reasoning_effort\s*=/.test(line);
704
+ return !/^\s*(?:model|model_reasoning_effort)\s*=/.test(line);
708
705
  }).join('\n').replace(/^\n+/, '').replace(/\n{3,}/g, '\n\n');
709
706
  }
710
707
  function removeTopLevelTomlKeyIfValue(text = '', key = '', value = '') {
@@ -814,11 +811,11 @@ export async function initProject(root, opts = {}) {
814
811
  // with `url is not supported for stdio`. Remote is also the transport the doctor
815
812
  // migrates everyone to (local stdio can block interactive Codex launch).
816
813
  { table: 'mcp_servers.context7', text: context7ConfigToml('remote').trim(), preserveExisting: true },
817
- { table: 'agents.native_agent', text: agentConfigBlock('native_agent', 'Read-only SKS analysis agent.', './agents/native-agent-intake.toml', ['Analysis', 'Mapper']) },
818
- { table: 'agents.team_consensus', text: agentConfigBlock('team_consensus', 'SKS planning/debate agent.', './agents/team-consensus.toml', ['Consensus', 'Atlas']) },
814
+ { table: 'agents.native_agent', text: agentConfigBlock('native_agent', 'SKS native agent with bounded write capability.', './agents/native-agent-intake.toml', ['Analysis', 'Mapper']) },
815
+ { table: 'agents.team_consensus', text: agentConfigBlock('team_consensus', 'SKS planning/debate agent with bounded write capability.', './agents/team-consensus.toml', ['Consensus', 'Atlas']) },
819
816
  { table: 'agents.implementation_worker', text: agentConfigBlock('implementation_worker', 'SKS bounded implementation worker.', './agents/implementation-worker.toml', ['Builder', 'Mason']) },
820
- { table: 'agents.db_safety_reviewer', text: agentConfigBlock('db_safety_reviewer', 'Read-only DB safety reviewer.', './agents/db-safety-reviewer.toml', ['Sentinel', 'Ledger']) },
821
- { table: 'agents.qa_reviewer', text: agentConfigBlock('qa_reviewer', 'Read-only QA reviewer.', './agents/qa-reviewer.toml', ['Verifier', 'Reviewer']) },
817
+ { table: 'agents.db_safety_reviewer', text: agentConfigBlock('db_safety_reviewer', 'DB safety reviewer with bounded write capability.', './agents/db-safety-reviewer.toml', ['Sentinel', 'Ledger']) },
818
+ { table: 'agents.qa_reviewer', text: agentConfigBlock('qa_reviewer', 'QA reviewer with bounded write capability.', './agents/qa-reviewer.toml', ['Verifier', 'Reviewer']) },
822
819
  // NOTE: SKS config profiles are NO LONGER emitted as `[profiles.sks-*]` tables.
823
820
  // Codex 0.134+ deprecated config-profile tables / the `profile=` selector (warns at
824
821
  // startup) in favor of per-file `$CODEX_HOME/<name>.config.toml` overlays loaded by
@@ -1304,12 +1301,12 @@ async function removeDirIfEmpty(dir) {
1304
1301
  }
1305
1302
  async function installCodexAgents(root) {
1306
1303
  const agents = {
1307
- 'analysis-scout.toml': `name = "analysis_scout"\ndescription = "Read-only SKS analysis scout retained for stale Codex agent-role config repair."\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "medium"\nsandbox_mode = "read-only"\ndeveloper_instructions = """\nYou are an SKS read-only analysis scout.\nDo not edit files.\nInspect only the assigned source paths and return concise source-backed findings.\n"""\n`,
1308
- 'native-agent-intake.toml': `name = "native_agent"\ndescription = "Read-only Team native agent. Maps one independent repo/docs/tests/API/risk/user-friction slice and returns TriWiki-ready source-backed findings before debate starts."\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "medium"\nsandbox_mode = "read-only"\ndeveloper_instructions = """\nYou are an SKS Team native agent.\nDo not edit files.\nOwn exactly one investigation slice assigned by the parent orchestrator.\nUse the mission roster or worker inbox reasoning_effort when the host exposes it; simple bounded work can use low, tool-heavy runtime work medium, and knowledge/research/safety/release work high or xhigh. Default to medium only when no assignment is visible.\nMap relevant source files, docs, tests, APIs, DB or safety risks, UX friction, and likely implementation boundaries.\nReturn concise source-backed claims suitable for team-analysis.md and TriWiki ingestion: claim, source path, evidence hash or quoted anchor, risk, confidence, and recommended implementation slice.\nDo not debate the final plan and do not implement code.\nAlso return a concise LIVE_EVENT line that the parent can record with sks team event.\n"""\n`,
1309
- 'team-consensus.toml': `name = "team_consensus"\ndescription = "Planning and debate specialist for SKS Team mode. Maps options, constraints, role-persona risks, and proposes the agreed objective before implementation starts."\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "high"\nsandbox_mode = "read-only"\ndeveloper_instructions = """\nYou are the SKS Team consensus specialist.\nDo not edit files.\nUse the mission roster reasoning_effort when the host exposes it; planning has a medium minimum, with high or xhigh for knowledge, safety, release, research, or recovery work.\nMap the affected code paths, viable approaches, constraints, risks, and acceptance criteria.\nRun the debate as role-persona synthesis: final users are low-context, self-interested, stubborn, and inconvenience-averse; executors are capable developers; reviewers are strict.\nArgue for the smallest coherent objective that can be handed to a fresh executor_N development team.\nPlan for at least ${MIN_TEAM_REVIEWER_LANES} independent reviewer/QA validation lanes before integration or final.\nReturn: recommended objective, rejected alternatives, implementation slices, required reviewers, user-friction risks, and unresolved risks.\nAlso return a concise LIVE_EVENT line that the parent can record with sks team event.\n"""\n`,
1304
+ 'analysis-scout.toml': `name = "analysis_scout"\ndescription = "SKS analysis scout with bounded write capability retained for stale Codex agent-role config repair."\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "low"\nsandbox_mode = "workspace-write"\ndeveloper_instructions = """\nYou are an SKS analysis scout.\nOnly edit bounded files assigned by the parent orchestrator; otherwise inspect only and return concise source-backed findings.\n"""\n`,
1305
+ 'native-agent-intake.toml': `name = "native_agent"\ndescription = "Team native agent with bounded write capability. Maps one independent repo/docs/tests/API/risk/user-friction slice and can produce patch-envelope work when assigned."\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "low"\nsandbox_mode = "workspace-write"\ndeveloper_instructions = """\nYou are an SKS Team native agent.\nOnly edit bounded files assigned by the parent orchestrator.\nOwn exactly one investigation or implementation slice assigned by the parent orchestrator.\nUse the mission roster or worker inbox model and model_reasoning_effort when the host exposes it: simple bounded work may use gpt-5.4-mini, ordinary tool work uses gpt-5.5 low, and knowledge/research/safety/release work uses gpt-5.5 high.\nMap relevant source files, docs, tests, APIs, DB or safety risks, UX friction, and likely implementation boundaries.\nReturn concise source-backed claims suitable for team-analysis.md and TriWiki ingestion: claim, source path, evidence hash or quoted anchor, risk, confidence, and recommended implementation slice.\nDo not debate the final plan. Implement only when the assigned slice includes write paths.\nAlso return a concise LIVE_EVENT line that the parent can record with sks team event.\n"""\n`,
1306
+ 'team-consensus.toml': `name = "team_consensus"\ndescription = "Planning and debate specialist for SKS Team mode with bounded write capability. Maps options, constraints, role-persona risks, and proposes the agreed objective before implementation starts."\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "high"\nsandbox_mode = "workspace-write"\ndeveloper_instructions = """\nYou are the SKS Team consensus specialist.\nOnly edit bounded files assigned by the parent orchestrator.\nUse the mission roster model and model_reasoning_effort when the host exposes them; planning normally uses gpt-5.5 low or high depending on risk.\nMap the affected code paths, viable approaches, constraints, risks, and acceptance criteria.\nRun the debate as role-persona synthesis: final users are low-context, self-interested, stubborn, and inconvenience-averse; executors are capable developers; reviewers are strict.\nArgue for the smallest coherent objective that can be handed to a fresh executor_N development team.\nPlan for at least ${MIN_TEAM_REVIEWER_LANES} independent reviewer/QA validation lanes before integration or final.\nReturn: recommended objective, rejected alternatives, implementation slices, required reviewers, user-friction risks, and unresolved risks.\nAlso return a concise LIVE_EVENT line that the parent can record with sks team event.\n"""\n`,
1310
1307
  'implementation-worker.toml': `name = "implementation_worker"\ndescription = "Implementation specialist for SKS Team mode. Owns one bounded write set and coordinates with other executor_N workers."\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "medium"\nsandbox_mode = "workspace-write"\ndeveloper_instructions = """\nYou are an SKS Team executor/developer in the fresh development bundle.\nYou are not alone in the codebase. Other executor_N workers may be editing disjoint files.\nUse the mission roster or worker inbox reasoning_effort when the host exposes it; simple bounded changes can use low, tool-heavy implementation medium, and safety/release/DB work high.\nOnly edit the files or module slice assigned to you.\nDo not revert or overwrite edits made by others.\nRead local patterns first, make the smallest correct change, avoid adding user friction, run focused verification for your slice, and report changed paths plus evidence.\nDo not create fallback implementation code, substitute behavior, mock behavior, or compatibility shims unless the user or sealed decision contract explicitly requested them.\nRespect all SKS hooks, DB safety rules, no-question run rules, and H-Proof completion gates.\nAlso return concise LIVE_EVENT lines for started, blocked, changed files, verification, and final result so the parent can record them.\n"""\n`,
1311
- 'db-safety-reviewer.toml': `name = "db_safety_reviewer"\ndescription = "Read-only database safety reviewer for SQL, migrations, Supabase, RLS, destructive-operation risk, and rollback safety."\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "high"\nsandbox_mode = "read-only"\ndeveloper_instructions = """\nYou are a database safety reviewer.\nNever modify files or execute destructive commands.\nReview migrations, SQL, Supabase RLS, transaction boundaries, rollback safety, and MCP database tool usage.\nBlock DROP, TRUNCATE, mass DELETE/UPDATE, db reset, db push, project deletion, branch reset/merge/delete, RLS disabling, and live execute_sql writes.\nReturn concrete risks, exact file references, and required fixes.\nAlso return a concise LIVE_EVENT line that the parent can record with sks team event.\n"""\n`,
1312
- 'qa-reviewer.toml': `name = "qa_reviewer"\ndescription = "Strict read-only verification reviewer for correctness, regressions, missing tests, user friction, and final evidence."\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "high"\nsandbox_mode = "read-only"\ndeveloper_instructions = """\nYou are an SKS Team strict reviewer.\nDo not edit files.\nReview correctness, edge cases, regression risk, missing tests, unsupported claims, and whether the final evidence proves the claimed outcome.\nTeam review must cover at least ${MIN_TEAM_REVIEWER_LANES} independent reviewer/QA validation lanes before integration or final; flag missing review lane evidence.\nAlso evaluate practical friction from the viewpoint of a stubborn, low-context final user who dislikes inconvenience.\nPrioritize concrete findings with file references and focused verification suggestions.\nFlag any unrequested fallback implementation code, substitute behavior, mock behavior, or compatibility shim as a blocking finding unless the user or sealed decision contract explicitly requested it.\nReturn no findings if the implementation is sound, and clearly list residual test gaps.\nAlso return a concise LIVE_EVENT line that the parent can record with sks team event.\n"""\n`
1308
+ 'db-safety-reviewer.toml': `name = "db_safety_reviewer"\ndescription = "Database safety reviewer with bounded write capability for SQL, migrations, Supabase, RLS, destructive-operation risk, and rollback safety."\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "high"\nsandbox_mode = "workspace-write"\ndeveloper_instructions = """\nYou are a database safety reviewer.\nOnly edit bounded files assigned by the parent orchestrator. Never execute destructive commands.\nReview migrations, SQL, Supabase RLS, transaction boundaries, rollback safety, and MCP database tool usage.\nBlock DROP, TRUNCATE, mass DELETE/UPDATE, db reset, db push, project deletion, branch reset/merge/delete, RLS disabling, and live execute_sql writes.\nReturn concrete risks, exact file references, and required fixes.\nAlso return a concise LIVE_EVENT line that the parent can record with sks team event.\n"""\n`,
1309
+ 'qa-reviewer.toml': `name = "qa_reviewer"\ndescription = "Strict verification reviewer with bounded write capability for correctness, regressions, missing tests, user friction, and final evidence."\nmodel = "gpt-5.5"\nmodel_reasoning_effort = "high"\nsandbox_mode = "workspace-write"\ndeveloper_instructions = """\nYou are an SKS Team strict reviewer.\nOnly edit bounded files assigned by the parent orchestrator.\nReview correctness, edge cases, regression risk, missing tests, unsupported claims, and whether the final evidence proves the claimed outcome.\nTeam review must cover at least ${MIN_TEAM_REVIEWER_LANES} independent reviewer/QA validation lanes before integration or final; flag missing review lane evidence.\nAlso evaluate practical friction from the viewpoint of a stubborn, low-context final user who dislikes inconvenience.\nPrioritize concrete findings with file references and focused verification suggestions.\nFlag any unrequested fallback implementation code, substitute behavior, mock behavior, or compatibility shim as a blocking finding unless the user or sealed decision contract explicitly requested it.\nReturn no findings if the implementation is sound, and clearly list residual test gaps.\nAlso return a concise LIVE_EVENT line that the parent can record with sks team event.\n"""\n`
1313
1310
  };
1314
1311
  const dir = path.join(root, '.codex', 'agents');
1315
1312
  await ensureDir(dir);
@@ -1,16 +1,17 @@
1
1
  import { REQUIRED_CODEX_MODEL } from '../codex-model-guard.js';
2
2
  export const MANAGED_ASSET_SCHEMA_VERSION = 1;
3
- export const MANAGED_ASSET_VERSION = '4.2.0';
3
+ export const MANAGED_ASSET_VERSION = '4.7.0';
4
4
  export const MANAGED_ASSET_MARKER = 'SKS-MANAGED-ASSET';
5
5
  export const MANAGED_AGENT_ROLES = Object.freeze([
6
- role('sks-explorer', 'analysis-scout.toml', 'analysis_scout', 'Read-only SKS analysis scout retained for stale Codex agent-role config repair.', 'read-only', ['analysis-scout', 'analysis_scout', 'native_agent']),
7
- role('sks-planner', 'team-consensus.toml', 'team_consensus', 'Planning and debate specialist for SKS Team mode.', 'read-only', ['team-consensus', 'team_consensus']),
6
+ role('sks-explorer', 'analysis-scout.toml', 'analysis_scout', 'SKS analysis scout for bounded read/write slices retained for stale Codex agent-role config repair.', 'workspace-write', ['analysis-scout', 'analysis_scout']),
7
+ role('sks-native-agent', 'native-agent-intake.toml', 'native_agent', 'SKS native agent for bounded read/write intake slices.', 'workspace-write', ['native-agent-intake', 'native_agent']),
8
+ role('sks-planner', 'team-consensus.toml', 'team_consensus', 'Planning and debate specialist for bounded SKS Team mode write sets.', 'workspace-write', ['team-consensus', 'team_consensus']),
8
9
  role('sks-implementer', 'implementation-worker.toml', 'implementation_worker', 'Implementation specialist for bounded SKS Team write sets.', 'workspace-write', ['implementation-worker', 'implementation_worker']),
9
- role('sks-checker', 'qa-reviewer.toml', 'qa_reviewer', 'Strict read-only verification reviewer for correctness, regressions, and final evidence.', 'read-only', ['qa-reviewer', 'qa_reviewer']),
10
- role('sks-release-verifier', 'sks-release-verifier.toml', 'sks_release_verifier', 'Read-only release verifier for repository, docs, tests, API, and risk slices.', 'read-only', ['native-agent-intake', 'native_agent', 'release-verifier']),
11
- role('sks-zellij-ui-verifier', 'sks-zellij-ui-verifier.toml', 'sks_zellij_ui_verifier', 'Read-only Zellij UI verifier for session, pane, layout, and terminal evidence.', 'read-only', ['native-agent-intake', 'native_agent', 'zellij-ui-verifier']),
12
- role('sks-codex-probe-verifier', 'sks-codex-probe-verifier.toml', 'sks_codex_probe_verifier', 'Read-only Codex probe verifier for CLI, App, SDK, MCP, and native capability evidence.', 'read-only', ['native-agent-intake', 'native_agent', 'codex-probe-verifier']),
13
- role('db-safety-reviewer', 'db-safety-reviewer.toml', 'db_safety_reviewer', 'Read-only database safety reviewer for SQL, migrations, Supabase, and rollback safety.', 'read-only', ['db-safety-reviewer', 'db_safety_reviewer'])
10
+ role('sks-checker', 'qa-reviewer.toml', 'qa_reviewer', 'Strict verification reviewer for correctness, regressions, and final evidence with bounded write capability.', 'workspace-write', ['qa-reviewer', 'qa_reviewer']),
11
+ role('sks-release-verifier', 'sks-release-verifier.toml', 'sks_release_verifier', 'Release verifier for repository, docs, tests, API, and risk slices with bounded write capability.', 'workspace-write', ['release-verifier']),
12
+ role('sks-zellij-ui-verifier', 'sks-zellij-ui-verifier.toml', 'sks_zellij_ui_verifier', 'Zellij UI verifier for session, pane, layout, and terminal evidence with bounded write capability.', 'workspace-write', ['zellij-ui-verifier']),
13
+ role('sks-codex-probe-verifier', 'sks-codex-probe-verifier.toml', 'sks_codex_probe_verifier', 'Codex probe verifier for CLI, App, SDK, MCP, and native capability evidence with bounded write capability.', 'workspace-write', ['codex-probe-verifier']),
14
+ role('db-safety-reviewer', 'db-safety-reviewer.toml', 'db_safety_reviewer', 'Database safety reviewer for SQL, migrations, Supabase, and rollback safety with bounded write capability.', 'workspace-write', ['db-safety-reviewer', 'db_safety_reviewer'])
14
15
  ]);
15
16
  export const MANAGED_SKILLS = Object.freeze([
16
17
  'loop',
@@ -213,7 +213,7 @@ export function validatePipelinePlan(plan = {}) {
213
213
  issues.push('ssot_guard_stage');
214
214
  if (!plan.next_actions?.length)
215
215
  issues.push('next_actions');
216
- if (plan.agent_intake?.required && !plan.stages?.some((stage) => stage.id === AGENT_INTAKE_STAGE_ID && stage.agent_count === AGENT_COUNT && stage.read_only === true))
216
+ if (plan.agent_intake?.required && !plan.stages?.some((stage) => stage.id === AGENT_INTAKE_STAGE_ID && stage.agent_count === AGENT_COUNT && stage.read_only === false && /bounded workspace-write/i.test(String(stage.write_policy || '')) && /lease/i.test(String(stage.write_policy || ''))))
217
217
  issues.push('agent_intake_stage');
218
218
  return { ok: issues.length === 0, issues };
219
219
  }
@@ -970,7 +970,7 @@ async function materializeAutoSealedTeam(root, id, dir, route, task, contractHas
970
970
  team_runtime: teamRuntimePlanMetadata(),
971
971
  phases: [
972
972
  { id: 'team_roster_confirmation', goal: `Materialize the Team roster from default SKS counts or explicit user counts, write team-roster.json, and surface role counts ${formatRoleCounts(roleCounts)}.`, agents: ['parent_orchestrator'], output: 'team-roster.json' },
973
- { id: 'native_agent_intake', goal: `Read TriWiki context, then run exactly ${roster.bundle_size} read-only native_agent_N sessions in parallel. ${fromChatImgRequired ? `From-Chat-IMG active: ${CODEX_COMPUTER_USE_ONLY_POLICY}` : 'From-Chat-IMG inactive: do not assume ordinary images are chat captures.'}`, agents: roster.analysis_team.map((agent) => agent.id), max_parallel_native_sessions: agentSessions, write_policy: 'read-only' },
973
+ { id: 'native_agent_intake', goal: `Read TriWiki context, then run exactly ${roster.bundle_size} bounded workspace-write native_agent_N sessions in parallel. ${fromChatImgRequired ? `From-Chat-IMG active: ${CODEX_COMPUTER_USE_ONLY_POLICY}` : 'From-Chat-IMG inactive: do not assume ordinary images are chat captures.'} Native agents may edit only parent-assigned lease paths and parent integration owns final changes.`, agents: roster.analysis_team.map((agent) => agent.id), max_parallel_native_sessions: agentSessions, write_policy: 'bounded workspace-write leases; parent-owned integration' },
974
974
  { id: 'triwiki_refresh', goal: `Refresh or pack TriWiki and run ${triwikiContextTracking().validate_command}.`, agents: ['parent_orchestrator'], output: '.sneakoscope/wiki/context-pack.json' },
975
975
  { id: 'ssot_guard', goal: ssotGuardPolicyText(), agents: ['parent_orchestrator'], output: SSOT_GUARD_ARTIFACT },
976
976
  { id: 'planning_debate', goal: 'Run read-only planning debate, map constraints and implementation slices, then seal one objective.', agents: roster.debate_team.map((agent) => agent.id) },
@@ -1063,7 +1063,7 @@ async function prepareTeam(root, route, task, required, opts = {}) {
1063
1063
  team_runtime: teamRuntimePlanMetadata(),
1064
1064
  phases: [
1065
1065
  { id: 'team_roster_confirmation', goal: `Before any implementation, materialize the Team roster from default SKS counts or explicit user counts, write team-roster.json, and surface role counts ${formatRoleCounts(roleCounts)}. Implementation cannot be considered complete unless team-gate.json has team_roster_confirmed=true.`, agents: ['parent_orchestrator'], output: 'team-roster.json' },
1066
- { id: 'native_agent_intake', goal: `Before native agent intake, read TriWiki context. ${fromChatImgRequired ? `From-Chat-IMG active: for web/browser/webapp targets require Codex Chrome Extension readiness first; for native Mac/non-web surfaces use Codex Computer Use visual inspection when available. List every visible customer request, match every screenshot image region to attachments, write ${FROM_CHAT_IMG_COVERAGE_ARTIFACT}, ${FROM_CHAT_IMG_CHECKLIST_ARTIFACT}, and ${FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT}, then require scoped QA-LOOP evidence in ${FROM_CHAT_IMG_QA_LOOP_ARTIFACT} after the customer-request work is done. ${CODEX_WEB_VERIFICATION_POLICY} ${CODEX_COMPUTER_USE_ONLY_POLICY}` : `From-Chat-IMG inactive: do not assume ordinary images are chat captures. ${CODEX_WEB_VERIFICATION_POLICY} ${CODEX_COMPUTER_USE_ONLY_POLICY}`} Run exactly ${roster.bundle_size} read-only native_agent_N sessions in parallel, using the full available session budget without exceeding ${agentSessions}. Split repo/docs/tests/API/user-flow/risk investigation into independent slices, hydrate relevant low-trust claims from source, and record source-backed findings.`, agents: roster.analysis_team.map((agent) => agent.id), max_parallel_native_sessions: agentSessions, write_policy: 'read-only' },
1066
+ { id: 'native_agent_intake', goal: `Before native agent intake, read TriWiki context. ${fromChatImgRequired ? `From-Chat-IMG active: for web/browser/webapp targets require Codex Chrome Extension readiness first; for native Mac/non-web surfaces use Codex Computer Use visual inspection when available. List every visible customer request, match every screenshot image region to attachments, write ${FROM_CHAT_IMG_COVERAGE_ARTIFACT}, ${FROM_CHAT_IMG_CHECKLIST_ARTIFACT}, and ${FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT}, then require scoped QA-LOOP evidence in ${FROM_CHAT_IMG_QA_LOOP_ARTIFACT} after the customer-request work is done. ${CODEX_WEB_VERIFICATION_POLICY} ${CODEX_COMPUTER_USE_ONLY_POLICY}` : `From-Chat-IMG inactive: do not assume ordinary images are chat captures. ${CODEX_WEB_VERIFICATION_POLICY} ${CODEX_COMPUTER_USE_ONLY_POLICY}`} Run exactly ${roster.bundle_size} bounded workspace-write native_agent_N sessions in parallel, using the full available session budget without exceeding ${agentSessions}. Split repo/docs/tests/API/user-flow/risk investigation into independent slices, hydrate relevant low-trust claims from source, record source-backed findings, and edit only parent-assigned lease paths.`, agents: roster.analysis_team.map((agent) => agent.id), max_parallel_native_sessions: agentSessions, write_policy: 'bounded workspace-write leases; parent-owned integration' },
1067
1067
  { id: 'triwiki_refresh', goal: `Parent orchestrator updates Team analysis artifacts, then runs ${triwikiContextTracking().refresh_command} or ${triwikiContextTracking().pack_command}, prunes with ${triwikiContextTracking().prune_command} when stale/oversized wiki state would pollute handoffs, and runs ${triwikiContextTracking().validate_command} so the next stage uses current TriWiki context.`, agents: ['parent_orchestrator'], output: '.sneakoscope/wiki/context-pack.json' },
1068
1068
  { id: 'ssot_guard', goal: ssotGuardPolicyText(), agents: ['parent_orchestrator'], output: SSOT_GUARD_ARTIFACT },
1069
1069
  { id: 'planning_debate', goal: `Before debate, read the refreshed TriWiki pack. Debate team of exactly ${roster.bundle_size} participants maps user inconvenience, options, constraints, affected files, DB/test risk, and tradeoffs while applying compact Hyperplan-derived lenses: challenge framing, subtract surface, demand evidence, test integration risk, and consider one simpler alternative. Hydrate low-trust claims from source.`, agents: roster.debate_team.map((agent) => agent.id) },
@@ -2,6 +2,48 @@ import { GLM_52_OPENROUTER_MODEL, GLM_MAD_MODE } from './glm-52-settings.js';
2
2
  import { profileFromConst } from './glm-profile-resolver.js';
3
3
  export const GLM_CODEX_APP_PROFILE_ID = 'sks/glm-5.2-mad';
4
4
  export const GLM_CODEX_APP_PROFILE_LABEL = 'GLM 5.2 (MAD Speed / OpenRouter)';
5
+ export const GLM_CODEX_CONFIG_PROVIDER_ID = 'openrouter';
6
+ export const GLM_CODEX_CONFIG_PROFILE_ID = 'sks-glm-52-mad';
7
+ export const GLM_CODEX_SELECTABLE_REASONING_EFFORTS = [
8
+ 'none',
9
+ 'minimal',
10
+ 'low',
11
+ 'medium',
12
+ 'high',
13
+ 'xhigh',
14
+ ];
15
+ export const GLM_CODEX_CONFIG_REASONING_PROFILES = [
16
+ {
17
+ id: GLM_CODEX_CONFIG_PROFILE_ID,
18
+ label: 'GLM 5.2 MAD Speed',
19
+ reasoning_effort: 'none',
20
+ },
21
+ {
22
+ id: 'sks-glm-52-minimal',
23
+ label: 'GLM 5.2 Minimal',
24
+ reasoning_effort: 'minimal',
25
+ },
26
+ {
27
+ id: 'sks-glm-52-low',
28
+ label: 'GLM 5.2 Low',
29
+ reasoning_effort: 'low',
30
+ },
31
+ {
32
+ id: 'sks-glm-52-medium',
33
+ label: 'GLM 5.2 Medium',
34
+ reasoning_effort: 'medium',
35
+ },
36
+ {
37
+ id: 'sks-glm-52-high',
38
+ label: 'GLM 5.2 High',
39
+ reasoning_effort: 'high',
40
+ },
41
+ {
42
+ id: 'sks-glm-52-xhigh',
43
+ label: 'GLM 5.2 XHigh',
44
+ reasoning_effort: 'xhigh',
45
+ },
46
+ ];
5
47
  export function buildGlmCodexAppModelProfile() {
6
48
  const speed = profileFromConst('speed');
7
49
  return {
@@ -10,6 +52,10 @@ export function buildGlmCodexAppModelProfile() {
10
52
  label: GLM_CODEX_APP_PROFILE_LABEL,
11
53
  provider: 'openrouter',
12
54
  model: GLM_52_OPENROUTER_MODEL,
55
+ codexConfigProvider: GLM_CODEX_CONFIG_PROVIDER_ID,
56
+ codexConfigProfile: GLM_CODEX_CONFIG_PROFILE_ID,
57
+ supportedReasoningEfforts: GLM_CODEX_SELECTABLE_REASONING_EFFORTS,
58
+ reasoningProfiles: GLM_CODEX_CONFIG_REASONING_PROFILES,
13
59
  mode: GLM_MAD_MODE,
14
60
  strictModelLock: true,
15
61
  gptFallbackAllowed: false,
@@ -1,14 +1,15 @@
1
1
  import { GLM_52_DEFAULT_REQUEST_SETTINGS, GLM_52_OPENROUTER_MODEL, clampGlm52MaxTokens } from './glm-52-settings.js';
2
2
  import { buildDeepReasoningConfig, buildFastReasoningConfig } from './glm-reasoning-policy.js';
3
- import { profileFromConst, resolveGlmProfileFromArgs } from './glm-profile-resolver.js';
3
+ import { profileFromConst, reasoningEffortFromGlmSlashModelArgs, resolveGlmProfileFromArgs } from './glm-profile-resolver.js';
4
4
  export function buildGlm52Request(input) {
5
5
  const profile = resolveInputProfile(input.profile, input.args, input.reasoningEffort);
6
6
  if (profile.blockers.length) {
7
7
  throw new Error(`GLM request profile blocked: ${profile.blockers.join(', ')}`);
8
8
  }
9
9
  const strictOrDeepEffort = profile.reasoning_effort || (input.reasoningEffort === 'high' || input.reasoningEffort === 'xhigh' ? input.reasoningEffort : undefined);
10
+ const selectedReasoningEffort = input.reasoningEffort || (input.args ? reasoningEffortFromGlmSlashModelArgs(input.args) || undefined : undefined);
10
11
  const reasoning = profile.name === 'speed'
11
- ? buildFastReasoningConfig(input.reasoningMeta)
12
+ ? buildSpeedReasoningConfig(selectedReasoningEffort, input.reasoningMeta)
12
13
  : buildDeepReasoningConfig(strictOrDeepEffort || 'high');
13
14
  if (profile.name === 'speed' && (reasoning.effort === 'high' || reasoning.effort === 'xhigh')) {
14
15
  throw new Error(`GLM speed profile invariant violated: forbidden reasoning effort ${reasoning.effort}`);
@@ -62,4 +63,12 @@ function resolveInputProfile(profile, args, reasoningEffort) {
62
63
  return profileFromConst('deep');
63
64
  return profileFromConst(GLM_52_DEFAULT_REQUEST_SETTINGS.mode === 'mad-glm-speed' ? 'speed' : 'speed');
64
65
  }
66
+ function buildSpeedReasoningConfig(reasoningEffort, reasoningMeta) {
67
+ if (reasoningEffort === 'none')
68
+ return { exclude: true };
69
+ if (reasoningEffort === 'minimal' || reasoningEffort === 'low' || reasoningEffort === 'medium') {
70
+ return { effort: reasoningEffort, exclude: true };
71
+ }
72
+ return buildFastReasoningConfig(reasoningMeta);
73
+ }
65
74
  //# sourceMappingURL=glm-52-request.js.map
@@ -39,6 +39,7 @@ export async function runGlmDirectSpeedRun(input) {
39
39
  controller.transition('request');
40
40
  const request = buildGlm52Request({
41
41
  profile: 'speed',
42
+ ...(input.args ? { args: input.args } : {}),
42
43
  messages: [
43
44
  { role: 'system', content: 'Return only <sks_patch>, <sks_need_context>, or <sks_blocked>. Use unified diff for patches.' },
44
45
  { role: 'user', content: JSON.stringify({ task: input.task, context }) }
@@ -45,7 +45,8 @@ export function buildMadGlmLaunchProfileNoWrite(args = []) {
45
45
  model_reasoning_effort: effort,
46
46
  service_tier: 'fast',
47
47
  gpt_fallback_allowed: false,
48
- writes_user_codex_config: false
48
+ writes_user_codex_config: false,
49
+ blockers: profile.blockers
49
50
  };
50
51
  }
51
52
  export async function resolveMadGlmLaunchKey(env = process.env) {
@@ -111,7 +112,7 @@ export function buildMadGlmLaunchArtifact(input) {
111
112
  real_codex_bin: input.wrapper.real_codex_bin,
112
113
  raw_key_written_to_wrapper: false,
113
114
  codex_args: profile.launch_args,
114
- blockers: input.keyResolution.key ? [] : input.keyResolution.blockers,
115
+ blockers: [...profile.blockers, ...(input.keyResolution.key ? [] : input.keyResolution.blockers)],
115
116
  warnings: input.keyResolution.warnings || []
116
117
  };
117
118
  }
@@ -1,16 +1,17 @@
1
1
  import { readOption } from '../../../cli/args.js';
2
- import { GLM_DEEP_MODE, GLM_DEEP_PROFILE, GLM_SPEED_MODE, GLM_SPEED_PROFILE, GLM_STRICT_MODE, GLM_STRICT_PROFILE, GLM_XHIGH_MODE, GLM_XHIGH_PROFILE } from './glm-52-settings.js';
2
+ import { GLM_DEEP_MODE, GLM_DEEP_PROFILE, GLM_52_OPENROUTER_MODEL, GLM_SPEED_MODE, GLM_SPEED_PROFILE, GLM_STRICT_MODE, GLM_STRICT_PROFILE, GLM_XHIGH_MODE, GLM_XHIGH_PROFILE } from './glm-52-settings.js';
3
3
  export function resolveGlmProfileFromArgs(args = []) {
4
4
  const list = args.map(String);
5
5
  const exactProvider = readOption(list, '--exact-provider', null);
6
+ const slashSelection = parseGlmSlashModelSelection(list);
6
7
  const providerBlockers = exactProvider && !isValidOpenRouterProviderSlug(exactProvider)
7
8
  ? [`invalid_openrouter_provider_slug:${exactProvider}`]
8
9
  : [];
9
- const base = list.includes('--xhigh')
10
+ const base = slashSelection.reasoning_effort === 'xhigh' || list.includes('--xhigh')
10
11
  ? profileFromConst('xhigh')
11
12
  : list.includes('--strict')
12
13
  ? profileFromConst('strict')
13
- : list.includes('--deep')
14
+ : slashSelection.reasoning_effort === 'high' || list.includes('--deep')
14
15
  ? profileFromConst('deep')
15
16
  : profileFromConst('speed');
16
17
  const provider = exactProvider && !providerBlockers.length
@@ -29,7 +30,64 @@ export function resolveGlmProfileFromArgs(args = []) {
29
30
  return {
30
31
  ...base,
31
32
  provider,
32
- blockers: providerBlockers
33
+ blockers: [...providerBlockers, ...slashSelection.blockers]
34
+ };
35
+ }
36
+ export function reasoningEffortFromGlmSlashModelArgs(args = []) {
37
+ return parseGlmSlashModelSelection(args).reasoning_effort;
38
+ }
39
+ export function stripGlmSlashModelArgs(args = []) {
40
+ const consumed = new Set(parseGlmSlashModelSelection(args).consumed_indexes);
41
+ return args.map(String).filter((_arg, index) => !consumed.has(index));
42
+ }
43
+ export function parseGlmSlashModelSelection(args = []) {
44
+ const list = args.map(String);
45
+ const consumed = new Set();
46
+ const values = [];
47
+ for (let i = 0; i < list.length; i += 1) {
48
+ const arg = list[i] || '';
49
+ if (arg === '/model') {
50
+ consumed.add(i);
51
+ for (let j = i + 1; j < list.length && values.length < 2; j += 1) {
52
+ const candidate = list[j] || '';
53
+ if (candidate.startsWith('--') || candidate.startsWith('/'))
54
+ break;
55
+ consumed.add(j);
56
+ values.push(candidate);
57
+ if (values.length === 1 && isSelectableGlmReasoningEffort(candidate.trim().toLowerCase()))
58
+ break;
59
+ }
60
+ break;
61
+ }
62
+ const inline = arg.match(/^\/model(?::|=)(.+)$/)?.[1];
63
+ if (inline) {
64
+ consumed.add(i);
65
+ values.push(...inline.split(/[,:]/).map((value) => value.trim()).filter(Boolean).slice(0, 2));
66
+ break;
67
+ }
68
+ }
69
+ let model = null;
70
+ let reasoning = null;
71
+ const blockers = [];
72
+ for (const value of values) {
73
+ const normalized = value.trim().toLowerCase();
74
+ if (isSelectableGlmReasoningEffort(normalized)) {
75
+ reasoning = normalized;
76
+ continue;
77
+ }
78
+ if (!model) {
79
+ model = value;
80
+ if (!isAllowedGlmSlashModel(value))
81
+ blockers.push(`glm_slash_model_mismatch:${value}`);
82
+ continue;
83
+ }
84
+ blockers.push(`glm_slash_model_unrecognized:${value}`);
85
+ }
86
+ return {
87
+ model,
88
+ reasoning_effort: reasoning,
89
+ consumed_indexes: [...consumed].sort((a, b) => a - b),
90
+ blockers
33
91
  };
34
92
  }
35
93
  export function profileFromConst(name) {
@@ -101,4 +159,11 @@ export function profileFromConst(name) {
101
159
  export function isValidOpenRouterProviderSlug(value) {
102
160
  return /^(?!.*(?:^|\/)\.\.?(?:\/|$))[a-z0-9][a-z0-9._-]{0,63}(?:\/[a-z0-9][a-z0-9._-]{0,63}){0,3}$/i.test(value);
103
161
  }
162
+ function isSelectableGlmReasoningEffort(value) {
163
+ return value === 'none' || value === 'minimal' || value === 'low' || value === 'medium' || value === 'high' || value === 'xhigh';
164
+ }
165
+ function isAllowedGlmSlashModel(value) {
166
+ const normalized = value.trim().toLowerCase();
167
+ return normalized === GLM_52_OPENROUTER_MODEL || normalized === 'glm-5.2' || normalized === 'glm5.2';
168
+ }
104
169
  //# sourceMappingURL=glm-profile-resolver.js.map
@@ -2,6 +2,7 @@ import { flag, readOption, positionalArgs } from '../../../../cli/args.js';
2
2
  import { printJson } from '../../../../cli/output.js';
3
3
  import { runGlmNarutoMission } from './glm-naruto-orchestrator.js';
4
4
  import { runGlmNarutoBench } from './glm-naruto-bench.js';
5
+ import { stripGlmSlashModelArgs } from '../glm-profile-resolver.js';
5
6
  export async function glmNarutoCommand(args = []) {
6
7
  if (flag(args, '--bench')) {
7
8
  // --compare is an alias; the benchmark always compares direct vs Naruto.
@@ -24,7 +25,7 @@ export async function glmNarutoCommand(args = []) {
24
25
  }
25
26
  return result;
26
27
  }
27
- const positional = positionalArgs(args).map(String);
28
+ const positional = positionalArgs(stripGlmSlashModelArgs(args)).map(String);
28
29
  const task = positional.join(' ').trim();
29
30
  if (!task && !flag(args, '--repair') && !flag(args, '--status')) {
30
31
  const result = {
@@ -417,14 +417,14 @@ export function buildTeamRoster(roleCounts = DEFAULT_TEAM_ROLE_COUNTS, opts = {}
417
417
  const debateReviewers = numberedAgents('debate_reviewer', counts.reviewer, 'Strict debate reviewer: applies validator/researcher lenses to correctness, safety, DB risk, tests, regressions, and unsupported assumptions.', 'reviewer', { prompt });
418
418
  const debateExecutorPool = numberedAgents('debate_executor', bundleSize, 'Capable developer voice in debate: applies skeptic/architect lenses to implementation shape, ownership boundaries, dependencies, coupling, and risks before coding starts.', 'executor', { prompt });
419
419
  const debateTeam = composeDebateTeam({ users: debateUsers, planners: debatePlanners, reviewers: debateReviewers, executors: debateExecutorPool, bundleSize });
420
- const nativeAgents = numberedAgents('native_agent', bundleSize, 'Read-only native agent: quickly maps one independent slice of repo/docs/tests/API risk, records source paths and evidence, and returns TriWiki-ready findings.', 'analysis', { prompt });
420
+ const nativeAgents = numberedAgents('native_agent', bundleSize, 'Bounded native agent: quickly maps one independent slice of repo/docs/tests/API risk, records source paths and evidence, returns TriWiki-ready findings, and edits only parent-assigned lease paths.', 'analysis', { prompt });
421
421
  const developmentExecutors = numberedAgents('executor', bundleSize, 'Capable developer executor: owns one disjoint implementation slice and coordinates without reverting others.', 'executor', { prompt });
422
422
  const validationReviewers = numberedAgents('reviewer', counts.reviewer, 'Strict reviewer: adversarial about correctness, safety, DB risk, tests, regressions, and unsupported claims.', 'reviewer', { prompt });
423
423
  const validationUsers = numberedAgents('user', counts.user, 'Impatient final user acceptance persona: low-context, self-interested, stubborn, dislikes inconvenience, rejects clever work that feels annoying.', 'user', { prompt });
424
424
  return {
425
425
  role_counts: counts,
426
426
  bundle_size: bundleSize,
427
- analysis_team: nativeAgents.map((agent) => ({ ...agent, write_policy: 'read-only native analysis', output: 'team-analysis.md' })),
427
+ analysis_team: nativeAgents.map((agent) => ({ ...agent, write_policy: 'bounded workspace-write native analysis lease', output: 'team-analysis.md' })),
428
428
  debate_team: debateTeam,
429
429
  development_team: developmentExecutors.map((agent) => ({ ...agent, write_policy: 'workspace-write with explicit ownership' })),
430
430
  validation_team: [
@@ -1,2 +1,2 @@
1
- export const PACKAGE_VERSION = '4.6.5';
1
+ export const PACKAGE_VERSION = '4.7.0';
2
2
  //# sourceMappingURL=version.js.map
@@ -16,18 +16,20 @@ fs.writeFileSync(path.join(staleRoot, '.codex', 'agents', 'analysis-scout.toml')
16
16
  const stalePlan = await mod.repairAgentRoleConfigs({ root: staleRoot, apply: false, codexHome: path.join(staleRoot, 'codex-home') });
17
17
  const staleRepair = await mod.repairAgentRoleConfigs({ root: staleRoot, apply: true, codexHome: path.join(staleRoot, 'codex-home') });
18
18
  const repairedText = fs.readFileSync(path.join(staleRoot, '.codex', 'agents', 'analysis-scout.toml'), 'utf8');
19
+ const createdText = fs.readFileSync(analysisScout, 'utf8');
19
20
  const report = {
20
21
  schema: 'sks.agent-role-config-repair-check.v1',
21
22
  plan_ok: plan.ok === true && plan.missing.includes('analysis-scout.toml'),
22
23
  repair_ok: repair.ok === true,
23
24
  analysis_scout_created: fs.existsSync(analysisScout),
24
- created_matches_model: fs.readFileSync(analysisScout, 'utf8').includes('model = "gpt-5.5"'),
25
+ created_matches_model: createdText.includes('model = "gpt-5.5"'),
26
+ created_write_capable: createdText.includes('sandbox_mode = "workspace-write"') && !createdText.includes('Do not edit files.'),
25
27
  stale_detected: stalePlan.stale.includes('analysis-scout.toml'),
26
- stale_repaired: staleRepair.repaired.includes('.codex/agents/analysis-scout.toml') && repairedText.includes('name = "analysis_scout"') && repairedText.includes('model = "gpt-5.5"'),
28
+ stale_repaired: staleRepair.repaired.includes('.codex/agents/analysis-scout.toml') && repairedText.includes('name = "analysis_scout"') && repairedText.includes('model = "gpt-5.5"') && repairedText.includes('sandbox_mode = "workspace-write"'),
27
29
  warnings_suppressed: repair.warnings_suppressed === true,
28
30
  artifact_written: fs.existsSync(path.join(root, '.sneakoscope', 'reports', 'agent-role-config-repair.json'))
29
31
  };
30
- const ok = report.plan_ok && report.repair_ok && report.analysis_scout_created && report.created_matches_model && report.stale_detected && report.stale_repaired && report.warnings_suppressed && report.artifact_written;
32
+ const ok = report.plan_ok && report.repair_ok && report.analysis_scout_created && report.created_matches_model && report.created_write_capable && report.stale_detected && report.stale_repaired && report.warnings_suppressed && report.artifact_written;
31
33
  assertGate(ok, 'doctor --fix must repair missing SKS-owned agent role configs', report);
32
34
  emitGate('agent:role-config-repair', report);
33
35
  //# sourceMappingURL=agent-role-config-repair-check.js.map