sneakoscope 3.1.8 → 3.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/.sks-build-stamp.json +4 -4
- package/dist/bin/sks.js +1 -1
- package/dist/cli/args.js +17 -0
- package/dist/cli/command-registry.js +16 -13
- package/dist/cli/router.js +8 -5
- package/dist/commands/doctor.js +27 -2
- package/dist/core/commands/basic-cli.js +4 -1
- package/dist/core/commands/mad-sks-command.js +36 -13
- package/dist/core/commands/naruto-command.js +4 -1
- package/dist/core/commands/pipeline-command.js +3 -4
- package/dist/core/commands/qa-loop-command.js +36 -1
- package/dist/core/commands/research-command.js +61 -1
- package/dist/core/commands/team-command.js +63 -3
- package/dist/core/decision-contract.js +28 -4
- package/dist/core/doctor/command-alias-cleanup.js +64 -0
- package/dist/core/feature-fixtures.js +2 -0
- package/dist/core/feature-registry.js +2 -2
- package/dist/core/fsx.js +1 -1
- package/dist/core/naruto/naruto-work-graph.js +4 -1
- package/dist/core/pipeline-internals/runtime-core.js +50 -4
- package/dist/core/pipeline-internals/runtime-gates.js +10 -1
- package/dist/core/proof/route-proof-gate.js +1 -1
- package/dist/core/qa-loop.js +227 -11
- package/dist/core/questions.js +239 -2
- package/dist/core/routes.js +3 -4
- package/dist/core/version.js +1 -1
- package/dist/scripts/agent-native-release-gate.js +13 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
|
|
|
35
35
|
|
|
36
36
|
## 🚀 Current Release
|
|
37
37
|
|
|
38
|
-
SKS **3.1.
|
|
38
|
+
SKS **3.1.9** hardens update/setup/doctor safety around four operator-facing failure modes: immutable core skills, duplicate project skills, real native capability repair status, and Supabase/secret preservation.
|
|
39
39
|
|
|
40
40
|
What changed in 3.1.8:
|
|
41
41
|
|
|
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
|
|
|
4
4
|
fn main() {
|
|
5
5
|
let mut args = std::env::args().skip(1);
|
|
6
6
|
match args.next().as_deref() {
|
|
7
|
-
Some("--version") => println!("sks-rs 3.1.
|
|
7
|
+
Some("--version") => println!("sks-rs 3.1.9"),
|
|
8
8
|
Some("compact-info") => {
|
|
9
9
|
let mut input = String::new();
|
|
10
10
|
let _ = io::stdin().read_to_string(&mut input);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "sks.dist-build-stamp.v1",
|
|
3
3
|
"package_name": "sneakoscope",
|
|
4
|
-
"package_version": "3.1.
|
|
5
|
-
"source_digest": "
|
|
6
|
-
"source_file_count":
|
|
7
|
-
"built_at_source_time":
|
|
4
|
+
"package_version": "3.1.9",
|
|
5
|
+
"source_digest": "dbfd5ddb700abfc4a008256b36e1743363164fd504bba959542ce79c25916dad",
|
|
6
|
+
"source_file_count": 2605,
|
|
7
|
+
"built_at_source_time": 1781537952236
|
|
8
8
|
}
|
package/dist/bin/sks.js
CHANGED
package/dist/cli/args.js
CHANGED
|
@@ -28,6 +28,23 @@ export function positionalArgs(args = []) {
|
|
|
28
28
|
'--command',
|
|
29
29
|
'--project-ref',
|
|
30
30
|
'--agent',
|
|
31
|
+
'--agents',
|
|
32
|
+
'--target-active-slots',
|
|
33
|
+
'--work-items',
|
|
34
|
+
'--minimum-work-items',
|
|
35
|
+
'--max-queue-expansion',
|
|
36
|
+
'--concurrency',
|
|
37
|
+
'--backend',
|
|
38
|
+
'--route',
|
|
39
|
+
'--mission',
|
|
40
|
+
'--mission-id',
|
|
41
|
+
'--profile',
|
|
42
|
+
'--write-mode',
|
|
43
|
+
'--max-write-agents',
|
|
44
|
+
'--service-tier',
|
|
45
|
+
'--zellij-session-name',
|
|
46
|
+
'--worker-placement',
|
|
47
|
+
'--zellij-visible-pane-cap',
|
|
31
48
|
'--phase',
|
|
32
49
|
'--message',
|
|
33
50
|
'--role',
|
|
@@ -99,21 +99,16 @@ export const COMMANDS = {
|
|
|
99
99
|
'codex-app': entry('beta', 'Check Codex App readiness', 'dist/commands/codex-app.js', directCommand(() => import('../commands/codex-app.js'), 'dist/commands/codex-app.js')),
|
|
100
100
|
'codex-native': entry('beta', 'Inspect Codex Native broker and routing readiness', 'dist/commands/codex-native.js', directCommand(() => import('../commands/codex-native.js'), 'dist/commands/codex-native.js')),
|
|
101
101
|
'codex-lb': entry('beta', 'Inspect codex-lb status and circuit health', 'dist/commands/codex-lb.js', directCommand(() => import('../commands/codex-lb.js'), 'dist/commands/codex-lb.js')),
|
|
102
|
-
auth: entry('beta', 'Alias for codex-lb auth commands', 'dist/commands/codex-lb.js', directCommand(() => import('../commands/codex-lb.js'), 'dist/commands/codex-lb.js')),
|
|
103
102
|
hooks: entry('beta', 'Explain and inspect Codex hooks', 'dist/commands/hooks.js', directCommand(() => import('../commands/hooks.js'), 'dist/commands/hooks.js')),
|
|
104
103
|
tmux: entry('beta', 'Show removed-runtime migration notice', 'dist/commands/tmux.js', directCommand(() => import('../commands/tmux.js'), 'dist/commands/tmux.js')),
|
|
105
104
|
'zellij-lane': entry('beta', 'Render a Zellij lane frame for SKS sessions', 'dist/commands/zellij-lane.js', directCommand(() => import('../commands/zellij-lane.js'), 'dist/commands/zellij-lane.js')),
|
|
106
105
|
'zellij-slot-pane': entry('beta', 'Render a compact Zellij worker slot pane', 'dist/commands/zellij-slot-pane.js', directCommand(() => import('../commands/zellij-slot-pane.js'), 'dist/commands/zellij-slot-pane.js')),
|
|
107
106
|
'zellij-slot-column-anchor': entry('beta', 'Render the compact SLOTS anchor pane for first-slot-down Zellij stacks', 'dist/commands/zellij-slot-column-anchor.js', directCommand(() => import('../commands/zellij-slot-column-anchor.js'), 'dist/commands/zellij-slot-column-anchor.js')),
|
|
108
107
|
zellij: entry('beta', 'Inspect Zellij runtime status and explain repair (no auto-install)', 'dist/commands/zellij.js', directCommand(() => import('../commands/zellij.js'), 'dist/commands/zellij.js')),
|
|
109
|
-
mad: entry('beta', 'MAD-SKS Zellij permission launcher', 'dist/commands/mad-sks.js', directCommand(() => import('../commands/mad-sks.js'), 'dist/commands/mad-sks.js')),
|
|
110
108
|
'mad-sks': entry('beta', 'MAD-SKS scoped permission modifier', 'dist/commands/mad-sks.js', directCommand(() => import('../commands/mad-sks.js'), 'dist/commands/mad-sks.js')),
|
|
111
109
|
'mad-db': entry('beta', 'Create or inspect one-cycle Mad-DB break-glass capability tokens', 'dist/commands/mad-db.js', directCommand(() => import('../commands/mad-db.js'), 'dist/commands/mad-db.js')),
|
|
112
110
|
'auto-review': entry('beta', 'Manage auto-review profile', 'dist/commands/auto-review.js', directCommand(() => import('../commands/auto-review.js'), 'dist/commands/auto-review.js')),
|
|
113
|
-
autoreview: entry('beta', 'Alias for auto-review', 'dist/commands/auto-review.js', directCommand(() => import('../commands/auto-review.js'), 'dist/commands/auto-review.js')),
|
|
114
111
|
'dollar-commands': entry('stable', 'List Codex App dollar commands', 'dist/core/commands/basic-cli.js', basicArgs('dollarCommandsCommand')),
|
|
115
|
-
dollars: entry('stable', 'Alias for dollar-commands', 'dist/core/commands/basic-cli.js', basicArgs('dollarCommandsCommand')),
|
|
116
|
-
'$': entry('stable', 'Alias for dollar-commands', 'dist/core/commands/basic-cli.js', basicArgs('dollarCommandsCommand')),
|
|
117
112
|
'fast-mode': entry('stable', 'Toggle SKS Fast mode default for dollar-command routes', 'dist/core/commands/fast-mode-command.js', argsCommand(() => import('../core/commands/fast-mode-command.js'), 'fastModeCommand', 'dist/core/commands/fast-mode-command.js')),
|
|
118
113
|
commit: entry('stable', 'Create a simple git commit', 'dist/commands/commit.js', directCommand(() => import('../commands/commit.js'), 'dist/commands/commit.js')),
|
|
119
114
|
'commit-and-push': entry('stable', 'Create a simple git commit and push', 'dist/commands/commit-and-push.js', directCommand(() => import('../commands/commit-and-push.js'), 'dist/commands/commit-and-push.js')),
|
|
@@ -128,14 +123,9 @@ export const COMMANDS = {
|
|
|
128
123
|
autoresearch: entry('labs', 'Alias for research/autoresearch route', 'dist/core/commands/autoresearch-command.js', subcommand(() => import('../core/commands/autoresearch-command.js'), 'autoresearchCommand', 'dist/core/commands/autoresearch-command.js', 'status')),
|
|
129
124
|
ppt: entry('labs', 'Inspect/build PPT artifacts', 'dist/core/commands/ppt-command.js', commandArgsCommand(() => import('../core/commands/ppt-command.js'), 'pptCommand', 'dist/core/commands/ppt-command.js')),
|
|
130
125
|
'image-ux-review': entry('labs', 'Inspect image UX artifacts', 'dist/core/commands/image-ux-review-command.js', commandArgsCommand(() => import('../core/commands/image-ux-review-command.js'), 'imageUxReviewCommand', 'dist/core/commands/image-ux-review-command.js')),
|
|
131
|
-
'ux-review': entry('labs', 'Alias for image UX review', 'dist/core/commands/image-ux-review-command.js', commandArgsCommand(() => import('../core/commands/image-ux-review-command.js'), 'imageUxReviewCommand', 'dist/core/commands/image-ux-review-command.js')),
|
|
132
|
-
'visual-review': entry('labs', 'Alias for image UX review', 'dist/core/commands/image-ux-review-command.js', commandArgsCommand(() => import('../core/commands/image-ux-review-command.js'), 'imageUxReviewCommand', 'dist/core/commands/image-ux-review-command.js')),
|
|
133
|
-
'ui-ux-review': entry('labs', 'Alias for image UX review', 'dist/core/commands/image-ux-review-command.js', commandArgsCommand(() => import('../core/commands/image-ux-review-command.js'), 'imageUxReviewCommand', 'dist/core/commands/image-ux-review-command.js')),
|
|
134
126
|
'computer-use': entry('beta', 'Record native Mac/non-web Computer Use visual evidence', 'dist/core/commands/computer-use-command.js', commandArgsCommand(() => import('../core/commands/computer-use-command.js'), 'computerUseCommand', 'dist/core/commands/computer-use-command.js')),
|
|
135
|
-
cu: entry('beta', 'Alias for native Computer Use', 'dist/core/commands/computer-use-command.js', commandArgsCommand(() => import('../core/commands/computer-use-command.js'), 'computerUseCommand', 'dist/core/commands/computer-use-command.js')),
|
|
136
127
|
context7: entry('beta', 'Context7 checks and docs', 'dist/cli/context7-command.js', subcommand(() => import('./context7-command.js'), 'context7Command', 'dist/cli/context7-command.js', 'check')),
|
|
137
128
|
xai: entry('beta', 'Set up and check xAI/Grok search MCP integration', 'dist/cli/xai-command.js', subcommand(() => import('./xai-command.js'), 'xaiCommand', 'dist/cli/xai-command.js', 'check')),
|
|
138
|
-
grok: entry('beta', 'Alias for xAI/Grok search setup', 'dist/cli/xai-command.js', subcommand(() => import('./xai-command.js'), 'xaiCommand', 'dist/cli/xai-command.js', 'check')),
|
|
139
129
|
recallpulse: entry('labs', 'RecallPulse evidence route', 'dist/commands/recallpulse.js', directCommand(() => import('../commands/recallpulse.js'), 'dist/commands/recallpulse.js')),
|
|
140
130
|
pipeline: entry('beta', 'Inspect pipeline missions', 'dist/commands/pipeline.js', directCommand(() => import('../commands/pipeline.js'), 'dist/commands/pipeline.js')),
|
|
141
131
|
guard: entry('beta', 'Check harness guard', 'dist/commands/guard.js', directCommand(() => import('../commands/guard.js'), 'dist/commands/guard.js')),
|
|
@@ -156,7 +146,6 @@ export const COMMANDS = {
|
|
|
156
146
|
'skill-dream': entry('labs', 'Track skill dream counters', 'dist/core/commands/skill-dream-command.js', subcommand(() => import('../core/commands/skill-dream-command.js'), 'skillDreamCommand', 'dist/core/commands/skill-dream-command.js', 'status')),
|
|
157
147
|
'code-structure': entry('labs', 'Scan source structure', 'dist/core/commands/code-structure-command.js', subcommand(() => import('../core/commands/code-structure-command.js'), 'codeStructureCommand', 'dist/core/commands/code-structure-command.js', 'scan')),
|
|
158
148
|
rust: entry('beta', 'Inspect optional Rust accelerator status and smoke parity', 'dist/commands/rust.js', directCommand(() => import('../commands/rust.js'), 'dist/commands/rust.js')),
|
|
159
|
-
memory: entry('labs', 'Run retention checks', 'dist/core/commands/gc-command.js', subcommand(() => import('../core/commands/gc-command.js'), 'memoryCommand', 'dist/core/commands/gc-command.js')),
|
|
160
149
|
gx: entry('labs', 'Render/validate GX cartridges', 'dist/core/commands/gx-command.js', subcommand(() => import('../core/commands/gx-command.js'), 'gxCommand', 'dist/core/commands/gx-command.js', 'validate')),
|
|
161
150
|
db: entry('beta', 'Inspect DB safety policy', 'dist/core/commands/db-command.js', subcommand(() => import('../core/commands/db-command.js'), 'dbCommand', 'dist/core/commands/db-command.js', 'policy')),
|
|
162
151
|
eval: entry('labs', 'Run eval reports', 'dist/core/commands/eval-command.js', subcommand(() => import('../core/commands/eval-command.js'), 'evalCommand', 'dist/core/commands/eval-command.js', 'run')),
|
|
@@ -170,13 +159,27 @@ export const COMMANDS = {
|
|
|
170
159
|
bench: entry('beta', 'Run core trust-kernel benchmark budgets', 'dist/core/commands/bench-command.js', argsCommand(() => import('../core/commands/bench-command.js'), 'benchCommand', 'dist/core/commands/bench-command.js'))
|
|
171
160
|
};
|
|
172
161
|
export const TYPED_COMMANDS = COMMANDS;
|
|
162
|
+
export const LEGACY_COMMAND_ALIASES = {
|
|
163
|
+
auth: 'codex-lb',
|
|
164
|
+
mad: 'mad-sks',
|
|
165
|
+
autoreview: 'auto-review',
|
|
166
|
+
dollars: 'dollar-commands',
|
|
167
|
+
'$': 'dollar-commands',
|
|
168
|
+
'ux-review': 'image-ux-review',
|
|
169
|
+
'visual-review': 'image-ux-review',
|
|
170
|
+
'ui-ux-review': 'image-ux-review',
|
|
171
|
+
cu: 'computer-use',
|
|
172
|
+
grok: 'xai',
|
|
173
|
+
memory: 'gc'
|
|
174
|
+
};
|
|
173
175
|
export const COMMAND_ALIASES = {
|
|
176
|
+
...LEGACY_COMMAND_ALIASES,
|
|
174
177
|
'--help': 'help',
|
|
175
178
|
'-h': 'help',
|
|
176
179
|
'--version': 'version',
|
|
177
180
|
'-v': 'version',
|
|
178
|
-
'--mad': 'mad',
|
|
179
|
-
'--MAD': 'mad',
|
|
181
|
+
'--mad': 'mad-sks',
|
|
182
|
+
'--MAD': 'mad-sks',
|
|
180
183
|
'--mad-sks': 'mad-sks',
|
|
181
184
|
'--agent': 'agent',
|
|
182
185
|
'--naruto': 'naruto'
|
package/dist/cli/router.js
CHANGED
|
@@ -5,17 +5,20 @@ export function isCommandName(value) {
|
|
|
5
5
|
export function normalizeCommand(args = []) {
|
|
6
6
|
const cmd = args[0];
|
|
7
7
|
if (!cmd)
|
|
8
|
-
return { command: null, args: [...args] };
|
|
9
|
-
|
|
8
|
+
return { command: null, rawCommand: null, aliasTarget: null, args: [...args] };
|
|
9
|
+
const mapped = cmd in COMMAND_ALIASES ? COMMAND_ALIASES[cmd] : cmd;
|
|
10
10
|
const rest = args.slice(1);
|
|
11
|
+
const command = isCommandName(mapped) ? mapped : null;
|
|
11
12
|
return {
|
|
12
|
-
command
|
|
13
|
+
command,
|
|
14
|
+
rawCommand: cmd,
|
|
15
|
+
aliasTarget: command && mapped !== cmd ? command : null,
|
|
13
16
|
args: rest,
|
|
14
17
|
};
|
|
15
18
|
}
|
|
16
19
|
export async function dispatch(args) {
|
|
17
20
|
const argv = args ?? process.argv.slice(2);
|
|
18
|
-
const { command, args: rest } = normalizeCommand(argv);
|
|
21
|
+
const { command, rawCommand, args: rest } = normalizeCommand(argv);
|
|
19
22
|
if (!command) {
|
|
20
23
|
if (!argv.length) {
|
|
21
24
|
const mod = await import('../commands/doctor.js');
|
|
@@ -36,6 +39,6 @@ export async function dispatch(args) {
|
|
|
36
39
|
const mod = await entry.lazy();
|
|
37
40
|
if (typeof mod.run !== 'function')
|
|
38
41
|
throw new Error(`Command ${command} must export run(command, args)`);
|
|
39
|
-
return mod.run(command, rest);
|
|
42
|
+
return mod.run(rawCommand || command, rest);
|
|
40
43
|
}
|
|
41
44
|
//# sourceMappingURL=router.js.map
|
package/dist/commands/doctor.js
CHANGED
|
@@ -28,6 +28,7 @@ import { buildCodexAppHarnessMatrix } from '../core/codex-app/codex-app-harness-
|
|
|
28
28
|
import { buildCodexNativeFeatureMatrix } from '../core/codex-native/codex-native-feature-broker.js';
|
|
29
29
|
import { repairCodexNativeManagedAssets } from '../core/codex-native/codex-native-repair-transaction.js';
|
|
30
30
|
import { runDoctorNativeCapabilityRepair } from '../core/doctor/doctor-native-capability-repair.js';
|
|
31
|
+
import { runDoctorCommandAliasCleanup } from '../core/doctor/command-alias-cleanup.js';
|
|
31
32
|
export async function run(_command, args = []) {
|
|
32
33
|
const doctorFix = flag(args, '--fix');
|
|
33
34
|
let setupRepair = null;
|
|
@@ -70,6 +71,23 @@ export async function run(_command, args = []) {
|
|
|
70
71
|
};
|
|
71
72
|
}
|
|
72
73
|
const root = await projectRoot();
|
|
74
|
+
const commandAliasCleanup = await runDoctorCommandAliasCleanup({
|
|
75
|
+
root,
|
|
76
|
+
fix: doctorFix
|
|
77
|
+
}).catch((err) => ({
|
|
78
|
+
schema: 'sks.command-alias-cleanup.v1',
|
|
79
|
+
ok: false,
|
|
80
|
+
status: 'blocked',
|
|
81
|
+
root,
|
|
82
|
+
fix: doctorFix,
|
|
83
|
+
report_path: `${root}/.sneakoscope/reports/command-alias-cleanup.json`,
|
|
84
|
+
canonical_command_count: 0,
|
|
85
|
+
legacy_alias_count: 0,
|
|
86
|
+
aliases: [],
|
|
87
|
+
detected: { registered_alias_commands: [], catalog_alias_rows: [], missing_canonical_targets: [] },
|
|
88
|
+
actions: [],
|
|
89
|
+
blockers: [err?.message || String(err)]
|
|
90
|
+
}));
|
|
73
91
|
const doctorNativeCapabilityRepair = await runDoctorNativeCapabilityRepair({
|
|
74
92
|
root,
|
|
75
93
|
fix: doctorFix || flag(args, '--repair-native-capabilities'),
|
|
@@ -287,7 +305,7 @@ export async function run(_command, args = []) {
|
|
|
287
305
|
const runtimeReadiness = buildRuntimeReadiness(zellijReadiness, codexNativeFeatureMatrix);
|
|
288
306
|
const result = {
|
|
289
307
|
schema: 'sks.doctor-status.v1',
|
|
290
|
-
ok: ready.ready && (!sksUpdate || sksUpdate.ok !== false),
|
|
308
|
+
ok: ready.ready && (!sksUpdate || sksUpdate.ok !== false) && commandAliasCleanup.ok !== false,
|
|
291
309
|
root,
|
|
292
310
|
node: { ok: Number(process.versions.node.split('.')[0]) >= 20, version: process.version },
|
|
293
311
|
codex,
|
|
@@ -305,6 +323,7 @@ export async function run(_command, args = []) {
|
|
|
305
323
|
agent_role_config: agentRoleConfigRepair,
|
|
306
324
|
zellij_readiness: zellijReadiness,
|
|
307
325
|
codex_permission_profiles: permissionProfiles,
|
|
326
|
+
command_aliases: commandAliasCleanup,
|
|
308
327
|
imagegen: {
|
|
309
328
|
ok: imagegen.auth_readiness?.available_paths?.length > 0,
|
|
310
329
|
auth_readiness: imagegen.auth_readiness || null,
|
|
@@ -323,7 +342,7 @@ export async function run(_command, args = []) {
|
|
|
323
342
|
ready,
|
|
324
343
|
sneakoscope: { ok: await exists(`${root}/.sneakoscope`) },
|
|
325
344
|
package: { bytes: pkgBytes, human: formatBytes(pkgBytes) },
|
|
326
|
-
repair: { sks_update: sksUpdate, setup: setupRepair, codex_config: configRepair, migration_journal: migrationJournal, global_sks_installs: globalSksInstallCleanup, agent_role_config: agentRoleConfigRepair, zellij: zellijRepair, codex_native: codexNativeRepair, doctor_native_capability: doctorNativeCapabilityRepair }
|
|
345
|
+
repair: { sks_update: sksUpdate, setup: setupRepair, codex_config: configRepair, migration_journal: migrationJournal, global_sks_installs: globalSksInstallCleanup, agent_role_config: agentRoleConfigRepair, zellij: zellijRepair, codex_native: codexNativeRepair, doctor_native_capability: doctorNativeCapabilityRepair, command_aliases: commandAliasCleanup }
|
|
327
346
|
};
|
|
328
347
|
if (flag(args, '--json')) {
|
|
329
348
|
printJson(result);
|
|
@@ -381,6 +400,12 @@ export async function run(_command, args = []) {
|
|
|
381
400
|
console.log('SKS Skills:');
|
|
382
401
|
console.log(` core skills: ${doctorSkillStatus(doctorNativeCapabilityRepair?.core_skills)}`);
|
|
383
402
|
console.log(` duplicate project skills: ${doctorDedupeStatus(doctorNativeCapabilityRepair?.skill_dedupe)}`);
|
|
403
|
+
console.log('SKS Command Aliases:');
|
|
404
|
+
console.log(` status: ${commandAliasCleanup.status || (commandAliasCleanup.ok ? 'clean' : 'blocked')}`);
|
|
405
|
+
console.log(` canonical commands: ${commandAliasCleanup.canonical_command_count ?? 0}`);
|
|
406
|
+
console.log(` compatibility aliases: ${commandAliasCleanup.legacy_alias_count ?? 0}`);
|
|
407
|
+
if (commandAliasCleanup.report_path)
|
|
408
|
+
console.log(` report: ${commandAliasCleanup.report_path}`);
|
|
384
409
|
console.log('Secret preservation:');
|
|
385
410
|
console.log(` Supabase keys: ${doctorNativeCapabilityRepair?.ok === false && String((doctorNativeCapabilityRepair?.blockers || []).join(' ')).includes('secret_preservation_failed') ? 'blocked' : 'preserved'}`);
|
|
386
411
|
console.log(' secret values: redacted');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { spawnSync } from 'node:child_process';
|
|
3
|
-
import { COMMANDS } from '../../cli/command-registry.js';
|
|
3
|
+
import { COMMANDS, LEGACY_COMMAND_ALIASES } from '../../cli/command-registry.js';
|
|
4
4
|
import { flag } from '../../cli/args.js';
|
|
5
5
|
import { printJson, sksTextLogo } from '../../cli/output.js';
|
|
6
6
|
import { PACKAGE_VERSION, ensureDir, exists, nowIso, projectRoot, readJson, sksRoot, tmpdir, writeJsonAtomic } from '../fsx.js';
|
|
@@ -55,6 +55,9 @@ export function dollarCommandsCommand(args = []) {
|
|
|
55
55
|
export function aliasesCommand() {
|
|
56
56
|
console.log('Aliases');
|
|
57
57
|
console.log('- sks, sneakoscope');
|
|
58
|
+
console.log('- CLI compatibility aliases:');
|
|
59
|
+
for (const [alias, canonical] of Object.entries(LEGACY_COMMAND_ALIASES))
|
|
60
|
+
console.log(` sks ${alias} -> sks ${canonical}`);
|
|
58
61
|
console.log('- $ aliases:');
|
|
59
62
|
for (const entry of DOLLAR_COMMAND_ALIASES)
|
|
60
63
|
console.log(` ${entry.app_skill} -> ${entry.canonical}`);
|
|
@@ -30,6 +30,7 @@ export async function madHighCommand(args = [], deps = {}) {
|
|
|
30
30
|
return madSksSubcommand(subcommand, args.filter((arg) => String(arg) !== subcommand));
|
|
31
31
|
const cleanArgs = stripMadLaunchOnlyArgs(args);
|
|
32
32
|
const rawArgs = (args || []).map((arg) => String(arg));
|
|
33
|
+
const madDbGrant = resolveMadLaunchMadDbGrant(rawArgs);
|
|
33
34
|
const dryRun = rawArgs.includes('--dry-run');
|
|
34
35
|
if (args.includes('--json') && !dryRun) {
|
|
35
36
|
const profile = buildMadHighLaunchProfileNoWrite();
|
|
@@ -133,13 +134,6 @@ export async function madHighCommand(args = [], deps = {}) {
|
|
|
133
134
|
// later when the Zellij session opens. All filesystem/permission/EPERM/symlink/ACL
|
|
134
135
|
// readability + repair checks still run. SKS_LAUNCH_FULL_CODEX_PROBE=1 restores the
|
|
135
136
|
// old behavior.
|
|
136
|
-
const madDbRequested = rawArgs.includes('--mad-db');
|
|
137
|
-
const madDbAck = readOption(rawArgs, '--ack', '');
|
|
138
|
-
if (madDbRequested && madDbAck !== MAD_DB_ACK) {
|
|
139
|
-
console.error(`SKS MAD-DB launch blocked. Required --ack ${JSON.stringify(MAD_DB_ACK)}`);
|
|
140
|
-
process.exitCode = 2;
|
|
141
|
-
return { ok: false, status: 'blocked', reason: 'mad_db_ack_phrase_required', required_ack: MAD_DB_ACK };
|
|
142
|
-
}
|
|
143
137
|
const allowMadRepair = rawArgs.includes('--repair-config') || rawArgs.includes('--fix') || rawArgs.includes('--yes-repair');
|
|
144
138
|
const launchPreflight = await runCodexLaunchPreflight(launchRoot, { fix: allowMadRepair, launchFast: process.env.SKS_LAUNCH_FULL_CODEX_PROBE !== '1', profile: profile.profile_name, sandbox: 'danger-full-access', serviceTier: 'fast' });
|
|
145
139
|
const afterPreflightUi = beforeUi ? await writeCodexAppUiSnapshot(launchRoot, `mad-after-preflight-${uiSnapshotId}`).catch(() => null) : null;
|
|
@@ -160,18 +154,38 @@ export async function madHighCommand(args = [], deps = {}) {
|
|
|
160
154
|
return launchPreflight;
|
|
161
155
|
}
|
|
162
156
|
const madLaunch = await activateMadZellijPermissionState(process.cwd(), args);
|
|
163
|
-
const madDbCapability =
|
|
164
|
-
? await createMadDbCapability(madLaunch.root, { missionId: madLaunch.mission_id, ack:
|
|
157
|
+
const madDbCapability = madDbGrant.enabled
|
|
158
|
+
? await createMadDbCapability(madLaunch.root, { missionId: madLaunch.mission_id, ack: madDbGrant.ack, cwd: process.cwd() })
|
|
165
159
|
: null;
|
|
166
160
|
if (madDbCapability) {
|
|
161
|
+
const grantReport = {
|
|
162
|
+
schema: 'sks.mad-sks-launch-grants.v1',
|
|
163
|
+
generated_at: nowIso(),
|
|
164
|
+
mission_id: madLaunch.mission_id,
|
|
165
|
+
mad_sks_active: true,
|
|
166
|
+
mad_db_active: true,
|
|
167
|
+
mad_db_default_grant: madDbGrant.source === 'sks_mad_default',
|
|
168
|
+
mad_db_grant_source: madDbGrant.source,
|
|
169
|
+
mad_db_one_cycle_only: true,
|
|
170
|
+
mad_db_capability_file: 'mad-db-capability.json',
|
|
171
|
+
mad_db_cycle_id: madDbCapability.cycle_id,
|
|
172
|
+
mad_db_expires_at: madDbCapability.expires_at,
|
|
173
|
+
standalone_mad_db_enable_still_requires_ack: true
|
|
174
|
+
};
|
|
175
|
+
await writeJsonAtomic(path.join(madLaunch.dir, 'mad-sks-launch-grants.json'), grantReport);
|
|
167
176
|
await setCurrent(madLaunch.root, {
|
|
168
177
|
mission_id: madLaunch.mission_id,
|
|
169
178
|
mad_db_active: true,
|
|
170
179
|
mad_db_cycle_id: madDbCapability.cycle_id,
|
|
171
180
|
mad_db_capability_file: 'mad-db-capability.json',
|
|
172
|
-
mad_db_break_glass: true
|
|
181
|
+
mad_db_break_glass: true,
|
|
182
|
+
mad_db_default_grant: madDbGrant.source === 'sks_mad_default',
|
|
183
|
+
mad_db_grant_source: madDbGrant.source,
|
|
184
|
+
mad_db_one_cycle_only: true,
|
|
185
|
+
mad_db_priority_override_active: true,
|
|
186
|
+
mad_sks_launch_grants_file: 'mad-sks-launch-grants.json'
|
|
173
187
|
});
|
|
174
|
-
await appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_db.capability_created', cycle_id: madDbCapability.cycle_id, expires_at: madDbCapability.expires_at });
|
|
188
|
+
await appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_db.capability_created', grant_source: madDbGrant.source, cycle_id: madDbCapability.cycle_id, expires_at: madDbCapability.expires_at });
|
|
175
189
|
}
|
|
176
190
|
const updateNotice = await checkSksUpdateNotice({
|
|
177
191
|
packageName: deps.packageName || 'sneakoscope',
|
|
@@ -192,10 +206,10 @@ export async function madHighCommand(args = [], deps = {}) {
|
|
|
192
206
|
await appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_sks.update_notice_checked', non_blocking: true, update_available: updateNotice.update_available === true, source: updateNotice.source });
|
|
193
207
|
console.log(`SKS MAD ready: ${madHighProfileName()} | gate ${madLaunch.mission_id}`);
|
|
194
208
|
if (madDbCapability)
|
|
195
|
-
console.log(`MAD-DB one-cycle capability active; expires ${madDbCapability.expires_at}.`);
|
|
209
|
+
console.log(`MAD-DB one-cycle capability active (${madDbGrant.source}); expires ${madDbCapability.expires_at}.`);
|
|
196
210
|
if (updateNotice.update_available === true)
|
|
197
211
|
console.log(`SKS update notice: ${updateNotice.latest_version} available (non-blocking).`);
|
|
198
|
-
console.log('Scoped high-power maintenance authority active; add explicit --allow-* flags for packages, services, network, browser/Computer Use, generated assets, file permissions,
|
|
212
|
+
console.log('Scoped high-power maintenance authority active; add explicit --allow-* flags for packages, services, network, browser/Computer Use, generated assets, file permissions, or system/admin scopes. MAD-DB one-cycle DB break-glass is already active for this launch; protected-core, audit, and one-cycle bounds remain.');
|
|
199
213
|
const launchLb = lb.status === 'present' ? { ...lb, status: 'configured' } : lb;
|
|
200
214
|
const madSksEnv = {
|
|
201
215
|
SKS_PROTECTED_CORE_POLICY: madLaunch.gate.protected_core_policy,
|
|
@@ -260,6 +274,15 @@ export async function madHighCommand(args = [], deps = {}) {
|
|
|
260
274
|
console.log('MAD launch running headless: live_panes=false.');
|
|
261
275
|
return launch;
|
|
262
276
|
}
|
|
277
|
+
export function resolveMadLaunchMadDbGrant(args = []) {
|
|
278
|
+
const list = (args || []).map((arg) => String(arg));
|
|
279
|
+
return {
|
|
280
|
+
enabled: true,
|
|
281
|
+
source: list.includes('--mad-db') ? 'sks_mad_explicit_redundant_flag' : 'sks_mad_default',
|
|
282
|
+
ack: MAD_DB_ACK,
|
|
283
|
+
one_cycle_only: true
|
|
284
|
+
};
|
|
285
|
+
}
|
|
263
286
|
export async function startMadNativeSwarm(root, madLaunch, args = [], profile = {}, opts = {}) {
|
|
264
287
|
const swarm = resolveMadNativeSwarmOptions(args, profile, opts);
|
|
265
288
|
const dir = madLaunch.dir || missionDirLike(root, madLaunch.mission_id);
|
|
@@ -114,6 +114,7 @@ async function narutoRun(parsed) {
|
|
|
114
114
|
prompt: parsed.prompt,
|
|
115
115
|
requestedClones: roster.agent_count,
|
|
116
116
|
totalWorkItems: parsed.workItems,
|
|
117
|
+
honorExplicitTotalWorkItems: parsed.workItemsExplicit,
|
|
117
118
|
readonly: parsed.readonly,
|
|
118
119
|
writeCapable,
|
|
119
120
|
leaseBasePath: patchEnvelopeBasePath,
|
|
@@ -127,6 +128,7 @@ async function narutoRun(parsed) {
|
|
|
127
128
|
prompt: parsed.prompt,
|
|
128
129
|
requestedClones: roster.agent_count,
|
|
129
130
|
totalWorkItems: parsed.workItems,
|
|
131
|
+
honorExplicitTotalWorkItems: parsed.workItemsExplicit,
|
|
130
132
|
readonly: parsed.readonly,
|
|
131
133
|
writeCapable,
|
|
132
134
|
leaseBasePath: patchEnvelopeBasePath,
|
|
@@ -791,6 +793,7 @@ function parseNarutoArgs(args = []) {
|
|
|
791
793
|
const json = hasFlag(args, '--json');
|
|
792
794
|
const requestedClones = Number(readOption(args, '--clones', readOption(args, '--agents', DEFAULT_NARUTO_CLONES)));
|
|
793
795
|
const clones = clampClones(requestedClones);
|
|
796
|
+
const workItemsExplicit = hasOption(args, '--work-items');
|
|
794
797
|
const workItems = clampWorkItems(Number(readOption(args, '--work-items', clones * 2)), clones);
|
|
795
798
|
const concurrency = normalizeConcurrency(readOption(args, '--concurrency', readOption(args, '--target-active-slots', null)), clones);
|
|
796
799
|
const useOllama = hasFlag(args, '--ollama') || hasFlag(args, '--local-model');
|
|
@@ -831,7 +834,7 @@ function parseNarutoArgs(args = []) {
|
|
|
831
834
|
const messages = normalizeMessages(readOption(args, '--messages', '8'));
|
|
832
835
|
const valueFlags = new Set(['--clones', '--agents', '--work-items', '--concurrency', '--target-active-slots', '--backend', '--write-mode', '--max-write-agents', '--service-tier', '--mission', '--mission-id', '--ollama-model', '--local-model-model', '--ollama-base-url', '--local-model-base-url', '--parallelism', '--messages']);
|
|
833
836
|
const prompt = positionalArgs(rest, valueFlags).join(' ').trim() || 'Naruto shadow clone swarm run';
|
|
834
|
-
return { action, prompt, clones, workItems, concurrency, backend, backendExplicit, mock, real, readonly, ollamaEnabled: useOllama && !noOllama, noOllama, ollamaModel, ollamaBaseUrl, writeMode, applyPatches, dryRunPatches, maxWriteAgents, fastMode, serviceTier, noFast, json, missionId, noOpenZellij, attach, smoke, parallelism, messages };
|
|
837
|
+
return { action, prompt, clones, workItems, workItemsExplicit, concurrency, backend, backendExplicit, mock, real, readonly, ollamaEnabled: useOllama && !noOllama, noOllama, ollamaModel, ollamaBaseUrl, writeMode, applyPatches, dryRunPatches, maxWriteAgents, fastMode, serviceTier, noFast, json, missionId, noOpenZellij, attach, smoke, parallelism, messages };
|
|
835
838
|
}
|
|
836
839
|
function normalizeParallelism(value) {
|
|
837
840
|
const text = String(value || 'extreme').toLowerCase();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { projectRoot, readJson
|
|
2
|
+
import { projectRoot, readJson } from '../fsx.js';
|
|
3
3
|
import { missionDir, stateFile } from '../mission.js';
|
|
4
|
-
import {
|
|
4
|
+
import { PIPELINE_PLAN_ARTIFACT, projectGateStatus, writePipelinePlan } from '../pipeline.js';
|
|
5
5
|
import { routePrompt } from '../routes.js';
|
|
6
6
|
import { flag, positionalArgs, readFlagValue, resolveMissionId } from './command-utils.js';
|
|
7
7
|
export async function pipelineCommand(args = []) {
|
|
@@ -33,14 +33,13 @@ export async function pipelineCommand(args = []) {
|
|
|
33
33
|
force: flag(args, '--force-agents'),
|
|
34
34
|
noAgents: flag(args, '--no-agents')
|
|
35
35
|
};
|
|
36
|
-
const plan =
|
|
36
|
+
const plan = await writePipelinePlan(dir, {
|
|
37
37
|
missionId: id,
|
|
38
38
|
route,
|
|
39
39
|
task: routeContext.task || mission.prompt || state.prompt || '',
|
|
40
40
|
required: Boolean(routeContext.context7_required || state.context7_required),
|
|
41
41
|
agents
|
|
42
42
|
});
|
|
43
|
-
await writeJsonAtomic(path.join(dir, PIPELINE_PLAN_ARTIFACT), plan);
|
|
44
43
|
if (flag(args, '--json'))
|
|
45
44
|
return console.log(JSON.stringify({ schema: 'sks.pipeline-plan.v1', ok: true, mission_id: id, plan }, null, 2));
|
|
46
45
|
console.log(`Pipeline plan written: .sneakoscope/missions/${id}/${PIPELINE_PLAN_ARTIFACT}`);
|
|
@@ -5,7 +5,7 @@ import { getCodexInfo, runCodexExec } from '../codex-adapter.js';
|
|
|
5
5
|
import { createMission, loadMission, setCurrent, stateFile } from '../mission.js';
|
|
6
6
|
import { writeQuestions } from '../questions.js';
|
|
7
7
|
import { sealContract } from '../decision-contract.js';
|
|
8
|
-
import { buildQaLoopQuestionSchema, buildQaLoopPrompt, evaluateQaGate, qaStatus, qaUiRequired, writeMockQaResult, writeQaLoopArtifacts, writeQaNativeAgentLedger } from '../qa-loop.js';
|
|
8
|
+
import { buildQaLoopQuestionSchema, buildQaLoopPrompt, ensureQaLoopVisualEvidenceContract, evaluateQaGate, qaGptImage2AnnotatedReviewRequired, qaStatus, qaUiRequired, writeMockQaResult, writeQaLoopArtifacts, writeQaNativeAgentLedger } from '../qa-loop.js';
|
|
9
9
|
import { containsUserQuestion, noQuestionContinuationReason } from '../no-question-guard.js';
|
|
10
10
|
import { ROUTES, routePrompt, stripVisibleDecisionAnswerBlocks } from '../routes.js';
|
|
11
11
|
import { codexChromeExtensionStatus } from '../codex-app.js';
|
|
@@ -124,6 +124,8 @@ async function qaLoopRun(args) {
|
|
|
124
124
|
const contract = await readJson(contractPath, {});
|
|
125
125
|
if (!(await exists(path.join(dir, 'qa-ledger.json'))))
|
|
126
126
|
await writeQaLoopArtifacts(dir, mission, contract);
|
|
127
|
+
else
|
|
128
|
+
await ensureQaLoopVisualEvidenceContract(dir, mission, contract);
|
|
127
129
|
const safetyScan = await scanDbSafety(root);
|
|
128
130
|
if (!safetyScan.ok) {
|
|
129
131
|
console.error('QA-LOOP cannot run: SKS safety scan found unsafe project data-tool configuration.');
|
|
@@ -148,6 +150,7 @@ async function qaLoopRun(args) {
|
|
|
148
150
|
const reportFile = qaGate.qa_report_file;
|
|
149
151
|
const executionProfile = await readJson(path.join(dir, 'qa-loop', 'execution-profile.json'), null);
|
|
150
152
|
const uiRequired = qaUiRequired(contract.answers || {});
|
|
153
|
+
const gptImage2ReviewRequired = qaGptImage2AnnotatedReviewRequired(contract, mission.prompt);
|
|
151
154
|
const capabilityArtifact = await writeCodex0138CapabilityArtifacts(root, { missionId: id }).catch((err) => ({ error: err?.message || String(err), report: null }));
|
|
152
155
|
const usageArtifact = await writeCodexAccountUsageArtifacts(root, { missionId: id }).catch((err) => ({ error: err?.message || String(err), snapshot: null }));
|
|
153
156
|
const budgetPolicy = buildQaLoopBudgetPolicy({ usage: usageArtifact?.snapshot || null, provider: 'codex-sdk' });
|
|
@@ -253,6 +256,16 @@ async function qaLoopRun(args) {
|
|
|
253
256
|
ui_chrome_extension_evidence: false,
|
|
254
257
|
ui_computer_use_evidence: false,
|
|
255
258
|
ui_evidence_source: 'blocked_chrome_extension_setup_required',
|
|
259
|
+
ui_chrome_extension_screenshot_required: true,
|
|
260
|
+
ui_chrome_extension_screenshot_captured: false,
|
|
261
|
+
ui_chrome_extension_screenshot_artifact: null,
|
|
262
|
+
ui_chrome_extension_screenshot_sha256: null,
|
|
263
|
+
gpt_image_2_annotated_review_required: gptImage2ReviewRequired,
|
|
264
|
+
gpt_image_2_annotated_review_generated: false,
|
|
265
|
+
gpt_image_2_annotated_review_artifact: null,
|
|
266
|
+
gpt_image_2_annotated_review_sha256: null,
|
|
267
|
+
gpt_image_2_annotated_review_model: gptImage2ReviewRequired ? null : 'not_required',
|
|
268
|
+
gpt_image_2_annotated_review_provider: gptImage2ReviewRequired ? null : 'not_required',
|
|
256
269
|
blocker: 'codex_chrome_extension_setup_required',
|
|
257
270
|
blockers: Array.from(new Set([...(qaGate.blockers || []), 'codex_chrome_extension_setup_required', ...(chrome.blockers || [])])),
|
|
258
271
|
evidence: [...(qaGate.evidence || []), 'Codex Chrome Extension preflight failed before web QA execution.'],
|
|
@@ -277,6 +290,28 @@ async function qaLoopRun(args) {
|
|
|
277
290
|
const nativeAgentRun = await runNativeAgentOrchestrator({ root, missionId: id, route: '$QA-LOOP', prompt: mission.prompt || 'QA-LOOP run', backend: mock ? 'fake' : 'codex-sdk', mock, agents: requestedAgents, targetActiveSlots, desiredWorkItemCount, minimumWorkItems, maxQueueExpansion, concurrency: Math.min(requestedAgents, 5), readonly: !(applyPatches && writeMode !== 'off'), profile, writeMode: writeMode, applyPatches, dryRunPatches, maxWriteAgents, roster: nativeRoster, routeCommand: 'sks qa-loop run', routeBlackboxKind: 'actual_qa_command', env: { SKS_CODEX_APP_EXECUTION_PROFILE: executionProfile?.mode || 'unknown', SKS_CODEX_AGENT_ROLE_STRATEGY: executionProfile?.agent_role_strategy || 'message-role' } });
|
|
278
291
|
await writeJsonAtomic(path.join(dir, 'qa-native-agent-run.json'), nativeAgentRun);
|
|
279
292
|
await appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'qaloop.native_agents.completed', backend: nativeAgentRun.backend, ok: nativeAgentRun.ok, proof: nativeAgentRun.proof?.status });
|
|
293
|
+
if (flag(args, '--native-proof-only')) {
|
|
294
|
+
const proofOnlyGate = {
|
|
295
|
+
schema: 'sks.qa-native-proof-only-gate.v1',
|
|
296
|
+
ok: nativeAgentRun.proof?.ok === true,
|
|
297
|
+
native_agent_proof: nativeAgentRun.proof?.ok === true,
|
|
298
|
+
proof_status: nativeAgentRun.proof?.status || null,
|
|
299
|
+
blockers: nativeAgentRun.proof?.blockers || []
|
|
300
|
+
};
|
|
301
|
+
if (flag(args, '--json'))
|
|
302
|
+
return console.log(JSON.stringify({
|
|
303
|
+
schema: 'sks.qa-loop-run.v1',
|
|
304
|
+
ok: proofOnlyGate.ok,
|
|
305
|
+
status: proofOnlyGate.ok ? 'native_proof_ready' : 'blocked',
|
|
306
|
+
mission_id: id,
|
|
307
|
+
gate: proofOnlyGate,
|
|
308
|
+
proof: nativeAgentRun.proof,
|
|
309
|
+
native_agent_run: nativeAgentRun,
|
|
310
|
+
native_proof_only: true
|
|
311
|
+
}, null, 2));
|
|
312
|
+
console.log(`QA-LOOP native proof ready: ${id}`);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
280
315
|
if (mock) {
|
|
281
316
|
let gate = await writeMockQaResult(dir, mission, contract);
|
|
282
317
|
const needsVisual = uiRequired;
|
|
@@ -40,6 +40,38 @@ export async function researchCommand(sub, args = []) {
|
|
|
40
40
|
export async function autoresearchCommand(sub, args = []) {
|
|
41
41
|
return researchCommand(sub || 'status', args);
|
|
42
42
|
}
|
|
43
|
+
function hasFlagOption(args = [], name) {
|
|
44
|
+
return args.includes(name) || args.some((arg) => String(arg).startsWith(`${name}=`));
|
|
45
|
+
}
|
|
46
|
+
function limitResearchNativeWorkGraph(graph, limit) {
|
|
47
|
+
const count = Math.max(1, Math.min(Number(graph?.work_items?.length || 0) || 1, Math.floor(Number(limit) || 1)));
|
|
48
|
+
const workItems = (graph.work_items || []).slice(0, count).map((item) => {
|
|
49
|
+
const selectedIds = new Set((graph.work_items || []).slice(0, count).map((row) => String(row.id || '')));
|
|
50
|
+
return {
|
|
51
|
+
...item,
|
|
52
|
+
dependencies: (item.dependencies || []).map(String).filter((id) => selectedIds.has(id)),
|
|
53
|
+
can_run_in_parallel_with: (item.can_run_in_parallel_with || []).map(String).filter((id) => selectedIds.has(id))
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
const selectedIds = new Set(workItems.map((item) => String(item.id || '')));
|
|
57
|
+
const activeWaves = (graph.active_waves || [])
|
|
58
|
+
.map((wave) => ({
|
|
59
|
+
...wave,
|
|
60
|
+
work_item_ids: (wave.work_item_ids || []).map(String).filter((id) => selectedIds.has(id)),
|
|
61
|
+
write_paths: (wave.write_paths || []).map(String),
|
|
62
|
+
conflict_count: Number(wave.conflict_count || 0)
|
|
63
|
+
}))
|
|
64
|
+
.filter((wave) => wave.work_item_ids.length > 0);
|
|
65
|
+
return {
|
|
66
|
+
...graph,
|
|
67
|
+
requested_clones: Math.min(Number(graph.requested_clones || count), count),
|
|
68
|
+
total_work_items: workItems.length,
|
|
69
|
+
work_items: workItems,
|
|
70
|
+
active_waves: activeWaves,
|
|
71
|
+
mixed_work_kinds: [...new Set(workItems.map((item) => item.kind))],
|
|
72
|
+
write_allowed_count: workItems.filter((item) => item.write_allowed === true).length
|
|
73
|
+
};
|
|
74
|
+
}
|
|
43
75
|
async function researchPrepare(args) {
|
|
44
76
|
const root = await sksRoot();
|
|
45
77
|
if (!(await exists(path.join(root, '.sneakoscope'))))
|
|
@@ -139,10 +171,16 @@ async function researchRun(args) {
|
|
|
139
171
|
const mock = flag(args, '--mock');
|
|
140
172
|
const researchWorkGraph = await writeResearchWorkGraph(dir, plan);
|
|
141
173
|
const graphWorkItemCount = Math.max(1, Number(researchWorkGraph.total_work_items || researchWorkGraph.work_items?.length || 0));
|
|
174
|
+
const explicitWorkItems = hasFlagOption(args, '--work-items');
|
|
175
|
+
const effectiveDesiredWorkItemCount = explicitWorkItems ? desiredWorkItemCount : Math.max(desiredWorkItemCount, graphWorkItemCount);
|
|
176
|
+
const effectiveMinimumWorkItems = Math.min(effectiveDesiredWorkItemCount, explicitWorkItems ? minimumWorkItems : Math.max(minimumWorkItems, Math.min(graphWorkItemCount, targetActiveSlots)));
|
|
177
|
+
const nativeResearchWorkGraph = explicitWorkItems
|
|
178
|
+
? limitResearchNativeWorkGraph(researchWorkGraph, effectiveDesiredWorkItemCount)
|
|
179
|
+
: researchWorkGraph;
|
|
142
180
|
await runResearchCycle(dir, researchWorkGraph, { cycle: 0, status: mock ? 'mock_native_orchestrator_planned' : 'native_orchestrator_planned' });
|
|
143
181
|
await setCurrent(root, { mission_id: id, mode: 'RESEARCH', phase: 'RESEARCH_RUNNING_NO_QUESTIONS', questions_allowed: false, implementation_allowed: false, research_real_run_required: !mock, research_cycle_timeout_minutes: cycleTimeoutMinutes });
|
|
144
182
|
await appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'research.run.started', maxCycles, mock, cycleTimeoutMinutes, real_run_required: !mock });
|
|
145
|
-
const nativeAgentRun = await runNativeAgentOrchestrator({ root, missionId: id, route: flag(args, '--autoresearch') ? '$AutoResearch' : '$Research', prompt: mission.prompt || plan.prompt || 'Research run', backend: mock ? 'fake' : 'codex-sdk', mock, agents: requestedAgents, targetActiveSlots, desiredWorkItemCount:
|
|
183
|
+
const nativeAgentRun = await runNativeAgentOrchestrator({ root, missionId: id, route: flag(args, '--autoresearch') ? '$AutoResearch' : '$Research', prompt: mission.prompt || plan.prompt || 'Research run', backend: mock ? 'fake' : 'codex-sdk', mock, agents: requestedAgents, targetActiveSlots, desiredWorkItemCount: effectiveDesiredWorkItemCount, minimumWorkItems: effectiveMinimumWorkItems, maxQueueExpansion, concurrency: Math.min(requestedAgents, 5), readonly: true, profile, writeMode: writeMode, applyPatches: false, dryRunPatches, maxWriteAgents, roster: plan.native_agent_plan, routeCommand: 'sks research run', routeBlackboxKind: 'actual_research_command', narutoWorkGraph: nativeResearchWorkGraph });
|
|
146
184
|
await writeJsonAtomic(path.join(dir, 'research-native-agent-run.json'), nativeAgentRun);
|
|
147
185
|
await appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'research.native_agents.completed', backend: nativeAgentRun.backend, ok: nativeAgentRun.ok, proof: nativeAgentRun.proof?.status });
|
|
148
186
|
if (!nativeAgentRun.ok) {
|
|
@@ -151,6 +189,28 @@ async function researchRun(args) {
|
|
|
151
189
|
process.exitCode = 2;
|
|
152
190
|
return;
|
|
153
191
|
}
|
|
192
|
+
if (flag(args, '--native-proof-only')) {
|
|
193
|
+
const proofOnlyGate = {
|
|
194
|
+
schema: 'sks.research-native-proof-only-gate.v1',
|
|
195
|
+
ok: nativeAgentRun.proof?.ok === true,
|
|
196
|
+
native_agent_proof: nativeAgentRun.proof?.ok === true,
|
|
197
|
+
proof_status: nativeAgentRun.proof?.status || null,
|
|
198
|
+
blockers: nativeAgentRun.proof?.blockers || []
|
|
199
|
+
};
|
|
200
|
+
if (flag(args, '--json'))
|
|
201
|
+
return console.log(JSON.stringify({
|
|
202
|
+
schema: flag(args, '--autoresearch') ? 'sks.autoresearch-run.v1' : 'sks.research-run.v1',
|
|
203
|
+
ok: proofOnlyGate.ok,
|
|
204
|
+
mission_id: id,
|
|
205
|
+
gate: proofOnlyGate,
|
|
206
|
+
proof: nativeAgentRun.proof,
|
|
207
|
+
native_agent_run: nativeAgentRun,
|
|
208
|
+
research_work_graph: nativeResearchWorkGraph,
|
|
209
|
+
native_proof_only: true
|
|
210
|
+
}, null, 2));
|
|
211
|
+
console.log(`Research native proof ready: ${id}`);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
154
214
|
const legacyResearchCycle = flag(args, '--legacy-research-cycle') || process.env.SKS_RESEARCH_LEGACY_CYCLE === '1';
|
|
155
215
|
const sourceMutationBaseline = await researchCodeMutationSnapshot(root, id);
|
|
156
216
|
if (!legacyResearchCycle) {
|