sneakoscope 2.0.16 → 2.0.18
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 +23 -30
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/.sks-build-stamp.json +4 -4
- package/dist/bin/sks.js +1 -1
- package/dist/cli/command-registry.js +1 -1
- package/dist/commands/doctor.js +39 -1
- package/dist/commands/proof.js +21 -0
- package/dist/commands/zellij-slot-pane.js +7 -1
- package/dist/core/agents/agent-effort-policy.js +7 -1
- package/dist/core/agents/agent-orchestrator.js +3 -1
- package/dist/core/agents/agent-scheduler.js +14 -1
- package/dist/core/agents/native-cli-session-swarm.js +11 -7
- package/dist/core/agents/native-cli-worker.js +56 -7
- package/dist/core/agents/parallel-runtime-proof.js +68 -9
- package/dist/core/agents/runtime-proof-summary.js +75 -0
- package/dist/core/codex-app/codex-app-handoff.js +77 -0
- package/dist/core/codex-control/codex-0138-capability.js +64 -0
- package/dist/core/codex-control/codex-model-capabilities.js +41 -0
- package/dist/core/codex-control/codex-sdk-config-policy.js +1 -1
- package/dist/core/codex-control/codex-task-runner.js +1 -1
- package/dist/core/codex-plugins/codex-plugin-json.js +152 -0
- package/dist/core/commands/mad-sks-command.js +4 -0
- package/dist/core/commands/naruto-command.js +20 -4
- package/dist/core/commands/qa-loop-command.js +111 -4
- package/dist/core/commands/team-command.js +6 -311
- package/dist/core/commands/team-legacy-observe-command.js +182 -0
- package/dist/core/db-safety.js +15 -0
- package/dist/core/doctor/codex-0138-doctor.js +104 -0
- package/dist/core/doctor/doctor-readiness-matrix.js +11 -0
- package/dist/core/effort-orchestrator.js +9 -0
- package/dist/core/feature-registry.js +4 -2
- package/dist/core/fsx.js +1 -1
- package/dist/core/hooks-runtime.js +38 -4
- package/dist/core/image/image-artifact-path-contract.js +99 -0
- package/dist/core/image-ux-review/imagegen-adapter.js +24 -3
- package/dist/core/init.js +1 -0
- package/dist/core/mad-db/mad-db-capability.js +9 -1
- package/dist/core/mad-db/mad-db-result-lifecycle.js +207 -0
- package/dist/core/mcp/mcp-plugin-inventory.js +29 -0
- package/dist/core/mcp/mcp-server-policy.js +24 -0
- package/dist/core/qa-loop/qa-loop-budget-policy.js +37 -0
- package/dist/core/qa-loop.js +28 -2
- package/dist/core/release/release-gate-affected-selector.js +47 -5
- package/dist/core/release/release-gate-dag.js +5 -1
- package/dist/core/release/release-gate-scheduler.js +2 -1
- package/dist/core/routes.js +3 -1
- package/dist/core/usage/codex-account-usage.js +78 -0
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-slot-column-anchor.js +16 -7
- package/dist/core/zellij/zellij-slot-pane-renderer.js +92 -1
- package/dist/core/zellij/zellij-slot-telemetry.js +29 -6
- package/dist/core/zellij/zellij-ui-mode.js +12 -2
- package/dist/scripts/prepublish-release-check-or-fast.js +3 -3
- package/dist/scripts/release-gate-existence-audit.js +5 -1
- package/dist/scripts/release-speed-summary.js +22 -2
- package/package.json +38 -4
- package/schemas/agents/parallel-runtime-proof.schema.json +31 -0
- package/schemas/codex-app/codex-app-handoff.schema.json +20 -0
- package/schemas/codex-plugins/codex-plugin-inventory.schema.json +32 -0
- package/schemas/image/image-artifact-path-contract.schema.json +32 -0
- package/schemas/usage/codex-account-usage.schema.json +27 -0
package/README.md
CHANGED
|
@@ -16,43 +16,34 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
|
|
|
16
16
|
|
|
17
17
|
## Current Release
|
|
18
18
|
|
|
19
|
-
SKS **2.0.
|
|
19
|
+
SKS **2.0.18** is the Codex 0.138 integration release: capability artifacts, Desktop `/app` handoff, plugin JSON inventory, image saved-path contracts, model-advertised effort order, account usage budget policy, and startup doctor checks.
|
|
20
20
|
|
|
21
21
|
What changed:
|
|
22
22
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
- Release audit, dynamic selection, and stamp hashing use `release-gates.v2.json` as the manifest source of truth.
|
|
32
|
-
- Git capability checks detect repo roots, Git dirs, worktree support, and safe cache roots while blocking in-repo worktree roots unless `SKS_ALLOW_IN_REPO_WORKTREES=1` is explicit.
|
|
33
|
-
- Worker worktree allocation creates isolated branches/paths under `$SKS_WORKTREE_ROOT`, `$XDG_CACHE_HOME/sks/worktrees`, or `~/.cache/sks/worktrees`; main checkouts stay untouched until integration.
|
|
34
|
-
- Product Design plugin readiness now checks both local and remote Codex App catalogs, auto-installs the remote plugin when needed, and records the installed/enabled skill surface.
|
|
35
|
-
- UI/design/PPT runtime routes prefer Product Design for research, ideation, audit, design QA, prototype, URL-to-code, image-to-code, share, and user-context steps.
|
|
36
|
-
- Naruto read-only runs force write mode off, propagate no-patch reasons through worker proof, and skip changed-file lease checks when no write-capable patch envelope exists.
|
|
37
|
-
- `codex-sdk` is the default native agent backend for Team, QA, Research, Naruto, MAD-SKS, and direct agent runs, with every runtime task entering through `runCodexTask`.
|
|
38
|
-
- Codex App UI snapshot, preservation, clobber guard, and doctor repair checks protect host-owned Fast UI/profile settings around `sks --mad`.
|
|
39
|
-
- Provider context resolves `openai`, `codex-lb`, and `codex-app` with badge/fallback surfaces while avoiding private Codex App UI mutation.
|
|
40
|
-
- UltraRouter writes `ultra-router-proof.json` decisions with tier, scores, hard filters, cache state, and cheapest-good-enough profile selection.
|
|
41
|
-
- Reliability Shield writes `codex-reliability-shield.json` for empty-result retry, stream-idle blocking, tool-result repair, and no-CoT keepalive heartbeats.
|
|
42
|
-
- Raw `codex exec` execution is removed from runtime fallback paths; explicit legacy requests are blocked with `legacy_codex_exec_runtime_removed`.
|
|
43
|
-
- SDK runs write `codex-control-proof.json`, `codex-thread-registry.json`, `codex-sdk-events.jsonl`, and schema-validated worker results.
|
|
44
|
-
- Zellij proof now links `pane_id`, `slot_id`, `generation_index`, `session_id`, `sdk_thread_id`, provider, and `service_tier`.
|
|
45
|
-
- Production runtime scripts are TypeScript source under `src/scripts` and build to `dist/scripts`; Python remains optional diagnostics under `pytools`.
|
|
46
|
-
- Release gates include `codex-control:*`, `ultra-router:*`, `codex-sdk:*`, Codex App Fast UI preservation, provider badges, Zellij spawn-on-demand, slot/pane binding, release truth, and real smoke checks.
|
|
47
|
-
- Research synthesis is now evidence-bound in non-mock runs; deterministic report generation is mock/fallback only.
|
|
48
|
-
- Research quality checks reject repeated paragraphs, template-like prose, low source density, low claim density, and thin implementation sections.
|
|
49
|
-
- Research handoffs now include context, key claims, evidence summary, blueprint sections, parallel work items, acceptance tests, rollback, and source appendix for `$Team` or `$Naruto`.
|
|
23
|
+
- `sks doctor` now reports Codex 0.138 feature readiness, plugin JSON inventory, candidate-only remote MCP servers, unavailable app templates, and repairable plugin discovery cache state.
|
|
24
|
+
- QA-LOOP can write a Codex Desktop `/app` handoff artifact with `--app-handoff` or require it with `--app-handoff-required`; this never substitutes for Codex Chrome Extension web UI evidence.
|
|
25
|
+
- Zellij slot panes and the right-column anchor surface pending QA `/app` handoffs so desktop review is visible during long native-agent runs.
|
|
26
|
+
- Codex plugin detail JSON is normalized into `.sneakoscope/codex-plugin-inventory.json`, and plugin-provided remote MCP servers remain candidate-only until explicitly enabled under DB/Mad-DB safety policy.
|
|
27
|
+
- Imagegen and QA image flows write `image-artifact-path-contract.json` with exact saved file paths and follow-up edit hints.
|
|
28
|
+
- Effort routing now understands the fallback order `minimal < low < medium < high < xhigh`, records model capability, and escalates QA effort after repeated failures.
|
|
29
|
+
- Codex account token usage can be recorded from an app-server usage endpoint, and QA budget policy reduces remote concurrency near limits while preserving GPT final review.
|
|
30
|
+
- Naruto final pass status now depends on the parallel runtime proof, and Mad-DB post-tool lifecycle recording handles MCP `isError` failures.
|
|
50
31
|
|
|
51
32
|
Quick checks:
|
|
52
33
|
|
|
53
34
|
```bash
|
|
54
35
|
npm run typecheck
|
|
55
36
|
npm run build
|
|
37
|
+
npm run codex:0138-capability
|
|
38
|
+
npm run codex-sdk:version-compat
|
|
39
|
+
npm run codex-app:handoff
|
|
40
|
+
npm run codex-plugin:inventory
|
|
41
|
+
npm run qa-loop:app-handoff
|
|
42
|
+
npm run image:artifact-path-contract
|
|
43
|
+
npm run codex:effort-order
|
|
44
|
+
npm run codex:account-usage
|
|
45
|
+
npm run codex:0138-doctor
|
|
46
|
+
npm run doctor:codex-0138-fix
|
|
56
47
|
npm run codex-control:capability
|
|
57
48
|
npm run codex-control:structured-output
|
|
58
49
|
npm run codex-control:event-stream-ledger
|
|
@@ -613,7 +604,9 @@ SKS_HERMES=1 sks status --json
|
|
|
613
604
|
|
|
614
605
|
Use these inside Codex App or another agent prompt. They are prompt commands, not terminal commands.
|
|
615
606
|
|
|
616
|
-
Common prompts: `$Team`, `$From-Chat-IMG`, `$with-local-llm-on`, `$with-local-llm-off`, `$DFix`, `$Answer`, `$SKS`, `$QA-LOOP`, `$PPT`, `$Computer-Use`/`$CU`, `$Goal`, `$Research`, `$AutoResearch`, `$DB`, `$MAD-SKS`, `$GX`, `$Wiki`, and `$Help`.
|
|
607
|
+
Common prompts: `$Team`, `$From-Chat-IMG`, `$with-local-llm-on`, `$with-local-llm-off`, `$DFix`, `$Answer`, `$SKS`, `$QA-LOOP`, `$PPT`, `$Computer-Use`/`$CU`, `$Goal`, `$Research`, `$AutoResearch`, `$DB`, `$MAD-SKS`, `$MAD-DB`, `$GX`, `$Wiki`, and `$Help`.
|
|
608
|
+
|
|
609
|
+
`$MAD-DB` is the prompt-visible Mad-DB alias for one-cycle DB break-glass work. It maps to the same guarded MAD-SKS permission route, while the terminal lifecycle remains `sks mad-db status|enable|revoke`; it is not a permanent DB unlock and catastrophic DB safeguards remain active.
|
|
617
610
|
|
|
618
611
|
## Common Workflows
|
|
619
612
|
|
|
@@ -759,7 +752,7 @@ npm run release:check
|
|
|
759
752
|
npm run publish:dry
|
|
760
753
|
```
|
|
761
754
|
|
|
762
|
-
`release:check` runs the change-aware affected release gate for ordinary local checks. Publish readiness uses `release:check:full`, which runs the full release DAG and writes a source digest stamp under `.sneakoscope/reports/` so publish commands can verify the same source/dist state. The DAG preserves the 1.18 baseline gates and adds Codex 0.136 compatibility, inherited Codex 0.135/0.134 runner truth, patch swarm runtime truth, transaction journaling, serial conflict rebase, strict strategy-to-patch proof, rollback command proof, Native CLI Session Swarm 5/10/20-process proof, Real Worker Backend Router proof, Codex child overlap proof, model-authored patch-envelope separation, Zellij layout/pane/screen/socket-dir proof, no-subagent-scaling proof, Fast mode default/worker/Codex/MAD propagation proof, Appshots attachment provenance, MCP runtime overlap evidence, task graph expansion, schema-bound follow-up work, actual Agent/Team/Research/QA route blackboxes, scheduler proof hardening, Source Intelligence propagation, Goal mode propagation checks, slot telemetry, update notice, MAD-DB, and Naruto SSOT gates. Broader live gates remain explicit scripts such as `release:real-check`; real Codex patch smoke, real Codex parallel worker proof, and real Zellij proof are optional unless their `SKS_REQUIRE_REAL_*` or `SKS_REQUIRE_ZELLIJ=1` environment variables are set. Generate the human-readable registry with `sks features inventory --write-docs`. Plain `npm publish` uses the `latest` dist-tag.
|
|
755
|
+
`release:check` runs the change-aware affected release gate for ordinary local checks. Publish readiness uses `release:check:full`, which runs the full release DAG and writes a source digest stamp under `.sneakoscope/reports/` so publish commands can verify the same source/dist state. The DAG preserves the 1.18 baseline gates and adds Codex 0.136 compatibility, inherited Codex 0.135/0.134 runner truth, patch swarm runtime truth, transaction journaling, serial conflict rebase, strict strategy-to-patch proof, rollback command proof, Native CLI Session Swarm 5/10/20-process proof, Real Worker Backend Router proof, Codex child overlap proof, model-authored patch-envelope separation, Zellij layout/pane/screen/socket-dir proof, no-subagent-scaling proof, Fast mode default/worker/Codex/MAD propagation proof, Appshots attachment provenance, MCP runtime overlap evidence, task graph expansion, schema-bound follow-up work, actual Agent/Team/Research/QA route blackboxes, scheduler proof hardening, Source Intelligence propagation, Goal mode propagation checks, slot telemetry, update notice, MAD-DB, and Naruto SSOT gates. Broader live gates remain explicit scripts such as `release:real-check`; real Codex patch smoke, real Codex parallel worker proof, and real Zellij proof are optional unless their `SKS_REQUIRE_REAL_*` or `SKS_REQUIRE_ZELLIJ=1` environment variables are set. Generate the human-readable registry with `sks features inventory --write-docs`. Plain `npm publish` uses the `latest` dist-tag. `npm run publish:dry` runs `release:check:full`, verifies the fresh stamp, and then performs provenance/registry and npm dry-run checks. npm's `prepublishOnly` uses `prepublish-release-check-or-fast` to accept that current stamp before the real publish; if the stamp is missing or stale, it runs `release:check:full` once before continuing.
|
|
763
756
|
|
|
764
757
|
Version bumps are manual. Run `sks versioning bump` only when preparing release metadata; SKS will not create `.git/hooks/pre-commit` or auto-bump during ordinary commits.
|
|
765
758
|
|
|
@@ -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 2.0.
|
|
7
|
+
Some("--version") => println!("sks-rs 2.0.18"),
|
|
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": "2.0.
|
|
5
|
-
"source_digest": "
|
|
6
|
-
"source_file_count":
|
|
7
|
-
"built_at_source_time":
|
|
4
|
+
"package_version": "2.0.18",
|
|
5
|
+
"source_digest": "3c246288e22bf5f29b5ba20a2a05b3f15a6afb9e6d680c531f7e78ef996c8c33",
|
|
6
|
+
"source_file_count": 2238,
|
|
7
|
+
"built_at_source_time": 1780992531184
|
|
8
8
|
}
|
package/dist/bin/sks.js
CHANGED
|
@@ -119,7 +119,7 @@ export const COMMANDS = {
|
|
|
119
119
|
commit: entry('stable', 'Create a simple git commit', 'dist/commands/commit.js', directCommand(() => import('../commands/commit.js'), 'dist/commands/commit.js')),
|
|
120
120
|
'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')),
|
|
121
121
|
dfix: entry('stable', 'Run DFix diagnose/plan/patch/verify loop', 'dist/core/commands/dfix-command.js', commandArgsCommand(() => import('../core/commands/dfix-command.js'), 'dfixCommand', 'dist/core/commands/dfix-command.js')),
|
|
122
|
-
team: entry('beta', 'Deprecated
|
|
122
|
+
team: entry('beta', 'Deprecated alias. New execution redirects to Naruto; legacy observe/watch remains.', 'dist/core/commands/team-command.js', argsCommand(() => import('../core/commands/team-command.js'), 'team', 'dist/core/commands/team-command.js')),
|
|
123
123
|
agent: entry('beta', 'Run native multi-session agent missions', 'dist/core/commands/agent-command.js', argsCommand(() => import('../core/commands/agent-command.js'), 'agentCommand', 'dist/core/commands/agent-command.js')),
|
|
124
124
|
'with-local-llm': entry('beta', 'Enable or inspect local Ollama worker backend', 'dist/core/commands/local-model-command.js', argsCommand(() => import('../core/commands/local-model-command.js'), 'localModelCommand', 'dist/core/commands/local-model-command.js')),
|
|
125
125
|
naruto: entry('labs', 'Run $Naruto shadow-clone swarm (up to 100 parallel sessions)', 'dist/core/commands/naruto-command.js', argsCommand(() => import('../core/commands/naruto-command.js'), 'narutoCommand', 'dist/core/commands/naruto-command.js')),
|
package/dist/commands/doctor.js
CHANGED
|
@@ -19,6 +19,10 @@ import { repairCodexAppFastUi } from '../core/codex-app/codex-app-fast-ui-repair
|
|
|
19
19
|
import { resolveProviderContext } from '../core/provider/provider-context.js';
|
|
20
20
|
import { readLocalModelConfig } from '../core/agents/ollama-worker-config.js';
|
|
21
21
|
import { repairAgentRoleConfigs } from '../core/agents/agent-role-config.js';
|
|
22
|
+
import { writeCodex0138CapabilityArtifacts } from '../core/codex-control/codex-0138-capability.js';
|
|
23
|
+
import { runCodex0138Doctor } from '../core/doctor/codex-0138-doctor.js';
|
|
24
|
+
import { writeCodexPluginInventoryArtifacts, pluginAppTemplatePolicy } from '../core/codex-plugins/codex-plugin-json.js';
|
|
25
|
+
import { writeMcpPluginInventoryArtifacts } from '../core/mcp/mcp-plugin-inventory.js';
|
|
22
26
|
export async function run(_command, args = []) {
|
|
23
27
|
const doctorFix = flag(args, '--fix');
|
|
24
28
|
let setupRepair = null;
|
|
@@ -167,6 +171,13 @@ export async function run(_command, args = []) {
|
|
|
167
171
|
: null;
|
|
168
172
|
const { detectImagegenCapability } = await import('../core/imagegen/imagegen-capability.js');
|
|
169
173
|
const imagegen = await detectImagegenCapability({ codexBin: codexBin || undefined }).catch((err) => ({ ok: false, error: err.message, auth_readiness: null }));
|
|
174
|
+
const codex0138Capability = await writeCodex0138CapabilityArtifacts(root, { codexBin: codexBin || null }).catch((err) => ({ error: err?.message || String(err), report: null }));
|
|
175
|
+
const codex0138Doctor = await runCodex0138Doctor(root, { fix: doctorFix }).catch((err) => ({ schema: 'sks.codex-0138-doctor.v1', ok: false, error: err?.message || String(err), blockers: ['codex_0138_doctor_exception'], warnings: [] }));
|
|
176
|
+
const pluginInventory = await writeCodexPluginInventoryArtifacts(root).catch((err) => ({ error: err?.message || String(err), report: null, artifact: null }));
|
|
177
|
+
const pluginPolicy = pluginInventory?.report ? pluginAppTemplatePolicy(pluginInventory.report) : null;
|
|
178
|
+
const mcpPluginInventory = pluginInventory?.report
|
|
179
|
+
? await writeMcpPluginInventoryArtifacts(root, { inventory: pluginInventory.report }).catch((err) => ({ error: err?.message || String(err), candidates: null }))
|
|
180
|
+
: null;
|
|
170
181
|
const pkgBytes = await dirSize(root).catch(() => 0);
|
|
171
182
|
const ready = await writeDoctorReadinessMatrix(root, {
|
|
172
183
|
codex,
|
|
@@ -180,10 +191,14 @@ export async function run(_command, args = []) {
|
|
|
180
191
|
agent_role_config: agentRoleConfigRepair,
|
|
181
192
|
repair: configRepair,
|
|
182
193
|
codex_app_ui: codexAppUi,
|
|
194
|
+
codex_0138_doctor: codex0138Doctor,
|
|
195
|
+
codex_plugin_inventory: pluginInventory?.report || null,
|
|
196
|
+
codex_plugin_app_template_policy: pluginPolicy,
|
|
183
197
|
require_codex_cli_config_load: flag(args, '--fix') || flag(args, '--require-actual-codex'),
|
|
184
198
|
operator_actions: [
|
|
185
199
|
...(codexConfig.operator_actions || []),
|
|
186
|
-
...(configRepair?.operator_actions || [])
|
|
200
|
+
...(configRepair?.operator_actions || []),
|
|
201
|
+
...(pluginPolicy?.doctor_warnings || [])
|
|
187
202
|
]
|
|
188
203
|
});
|
|
189
204
|
const zellijReadiness = buildZellijReadiness(root, zellij, ready);
|
|
@@ -211,6 +226,13 @@ export async function run(_command, args = []) {
|
|
|
211
226
|
auth_readiness: imagegen.auth_readiness || null,
|
|
212
227
|
codex_app_builtin_available: imagegen.codex_app?.available === true
|
|
213
228
|
},
|
|
229
|
+
codex_0138: {
|
|
230
|
+
capability: codex0138Capability.report || null,
|
|
231
|
+
doctor: codex0138Doctor,
|
|
232
|
+
plugins: pluginInventory?.report || null,
|
|
233
|
+
plugin_app_template_policy: pluginPolicy,
|
|
234
|
+
mcp_plugin_inventory: mcpPluginInventory?.candidates || null
|
|
235
|
+
},
|
|
214
236
|
ready,
|
|
215
237
|
sneakoscope: { ok: await exists(`${root}/.sneakoscope`) },
|
|
216
238
|
package: { bytes: pkgBytes, human: formatBytes(pkgBytes) },
|
|
@@ -262,6 +284,22 @@ export async function run(_command, args = []) {
|
|
|
262
284
|
console.log(` - ${action}`);
|
|
263
285
|
}
|
|
264
286
|
}
|
|
287
|
+
const codex0138 = codex0138Capability.report || {};
|
|
288
|
+
console.log('Codex 0.138 features:');
|
|
289
|
+
console.log(` /app handoff: ${codex0138.supports_app_handoff ? 'ok' : 'unavailable'}`);
|
|
290
|
+
console.log(` plugin JSON: ${codex0138.supports_plugin_json ? 'ok' : 'unavailable'}`);
|
|
291
|
+
console.log(` image path exposure: ${codex0138.supports_image_path_exposure ? 'ok' : 'unavailable'}`);
|
|
292
|
+
console.log(` OAuth MCP pre-refresh: ${codex0138.supports_oauth_mcp_prerefresh ? 'ok' : 'unavailable'}`);
|
|
293
|
+
const plugins = pluginInventory?.report?.plugins || [];
|
|
294
|
+
const remoteMcpCount = plugins.flatMap((plugin) => plugin.remote_mcp_servers || []).length;
|
|
295
|
+
const unavailableTemplates = pluginPolicy?.unavailable_app_templates?.length || 0;
|
|
296
|
+
console.log(`Codex plugins: ${pluginInventory?.report ? 'ok' : 'warning'}`);
|
|
297
|
+
console.log(` Remote MCP servers: ${remoteMcpCount} candidates`);
|
|
298
|
+
console.log(` Unavailable app templates: ${unavailableTemplates}`);
|
|
299
|
+
for (const warning of pluginPolicy?.doctor_warnings || [])
|
|
300
|
+
console.log(` warning: ${warning}`);
|
|
301
|
+
if (codex0138Doctor?.fixed?.length)
|
|
302
|
+
console.log(` doctor --fix repaired: ${codex0138Doctor.fixed.join(', ')}`);
|
|
265
303
|
console.log(`codex-lb: ${codexLb.ok ? 'ok' : `warning ${codexLb.circuit?.state || 'unknown'}`}`);
|
|
266
304
|
if (localModel) {
|
|
267
305
|
console.log('Local LLM:');
|
package/dist/commands/proof.js
CHANGED
|
@@ -8,10 +8,20 @@ import { writeRouteCompletionProof } from '../core/proof/route-adapter.js';
|
|
|
8
8
|
import { finalizeRouteWithProof } from '../core/proof/route-finalizer.js';
|
|
9
9
|
import { renderProofMarkdown, writeCompletionProof } from '../core/proof/proof-writer.js';
|
|
10
10
|
import { validateCompletionProof } from '../core/proof/validation.js';
|
|
11
|
+
import { buildRuntimeProofSummary, renderRuntimeProofSummary } from '../core/agents/runtime-proof-summary.js';
|
|
11
12
|
export async function run(_command, args = []) {
|
|
12
13
|
const root = await projectRoot();
|
|
13
14
|
const action = args[0] || 'show';
|
|
14
15
|
const rest = args.slice(1);
|
|
16
|
+
if (action === 'latest' && !flag(args, '--completion')) {
|
|
17
|
+
const runtime = await tryRuntimeProofSummary(root);
|
|
18
|
+
if (runtime) {
|
|
19
|
+
if (flag(args, '--json'))
|
|
20
|
+
return printJson(runtime);
|
|
21
|
+
console.log(renderRuntimeProofSummary(runtime));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
15
25
|
if (action === 'show' || action === 'latest') {
|
|
16
26
|
const proof = await withFreshSummaries(root, await readLatestProof(root));
|
|
17
27
|
if (flag(args, '--json') || action === 'latest')
|
|
@@ -122,6 +132,17 @@ export async function run(_command, args = []) {
|
|
|
122
132
|
console.error('Usage: sks proof show|latest|validate|route <mission-id|latest>|finalize <mission-id|latest> [--route route] [--strict] [--mock] [--json]|export --md|repair latest|smoke [--json]');
|
|
123
133
|
process.exitCode = 1;
|
|
124
134
|
}
|
|
135
|
+
async function tryRuntimeProofSummary(root) {
|
|
136
|
+
try {
|
|
137
|
+
const summary = await buildRuntimeProofSummary(root, 'latest');
|
|
138
|
+
if (summary.blockers.includes('parallel_runtime_proof_missing') && summary.blockers.includes('agent_scheduler_state_missing'))
|
|
139
|
+
return null;
|
|
140
|
+
return summary;
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
125
146
|
async function withFreshSummaries(root, proof) {
|
|
126
147
|
const evidence = await collectProofEvidence(root);
|
|
127
148
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { renderZellijSlotPaneFromArtifacts } from '../core/zellij/zellij-slot-pane-renderer.js';
|
|
1
|
+
import { renderZellijSlotPaneFromArtifacts, renderZellijSlotPaneStatusFromArtifacts } from '../core/zellij/zellij-slot-pane-renderer.js';
|
|
2
2
|
export async function run(_command = 'zellij-slot-pane', args = []) {
|
|
3
3
|
const artifactDir = readOption(args, '--artifact-dir', process.cwd()) || process.cwd();
|
|
4
4
|
const artifactRoot = readOption(args, '--artifact-root', artifactDir) || artifactDir;
|
|
@@ -9,7 +9,13 @@ export async function run(_command = 'zellij-slot-pane', args = []) {
|
|
|
9
9
|
const role = readOption(args, '--role', null);
|
|
10
10
|
const mode = readOption(args, '--mode', 'compact-slots');
|
|
11
11
|
const watch = hasFlag(args, '--watch');
|
|
12
|
+
const json = hasFlag(args, '--json');
|
|
12
13
|
const intervalMs = Math.max(250, Number(readOption(args, '--interval-ms', '1000') || 1000));
|
|
14
|
+
if (json) {
|
|
15
|
+
const status = await renderZellijSlotPaneStatusFromArtifacts({ artifactDir, artifactRoot, missionId, slotId, generationIndex });
|
|
16
|
+
console.log(JSON.stringify(status, null, 2));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
13
19
|
for (;;) {
|
|
14
20
|
const text = await renderZellijSlotPaneFromArtifacts({ artifactDir, artifactRoot, missionId, slotId, generationIndex, backend, role, mode });
|
|
15
21
|
process.stdout.write('\x1Bc' + text + '\n');
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { codexModelEffortCapability } from '../codex-control/codex-model-capabilities.js';
|
|
1
2
|
const XHIGH_SIGNAL_RE = /(frontier|autoresearch|novelty|hypothesis|falsif|forensic|from-chat-img|image\s*work\s*order|새로운\s*연구|가설|포렌식)/i;
|
|
2
3
|
const HIGH_SIGNAL_RE = /(database|supabase|sql|migration|security|permission|mad|release|publish|deploy|architecture|policy|schema|hook|rollback|db|보안|배포|마이그레이션|데이터베이스|권한|릴리즈)/i;
|
|
3
4
|
const MEDIUM_SIGNAL_RE = /(tmux|terminal|cli|tool(?:\s|-)?call|router|routing|orchestrat|pipeline|multi[-\s]?session|multi[-\s]?agent|lease|ledger|proof|검증|파이프라인|오케스트레이션|병렬|에이전트)/i;
|
|
@@ -26,6 +27,7 @@ export function decideAgentEffort(input = {}) {
|
|
|
26
27
|
effort = 'high';
|
|
27
28
|
reason = 'implementation_lane_capped_at_high';
|
|
28
29
|
}
|
|
30
|
+
const modelCapability = codexModelEffortCapability({ defaultEffort: effort });
|
|
29
31
|
return {
|
|
30
32
|
schema: 'sks.agent-effort-decision.v1',
|
|
31
33
|
policy_version: 1,
|
|
@@ -33,6 +35,7 @@ export function decideAgentEffort(input = {}) {
|
|
|
33
35
|
role,
|
|
34
36
|
reasoning_effort: effort,
|
|
35
37
|
model_reasoning_effort: effort,
|
|
38
|
+
model_effort_capability: modelCapability,
|
|
36
39
|
reasoning_profile: reasoningProfileName(effort),
|
|
37
40
|
service_tier: 'fast',
|
|
38
41
|
reason,
|
|
@@ -73,6 +76,7 @@ export function decideNarutoCloneEffort(input = {}) {
|
|
|
73
76
|
const writes = !readonly || /write|edit|route-local|workspace|patch|integrat/i.test(writePolicy) || hasActionTool;
|
|
74
77
|
const toolUse = writes || NARUTO_ACTION_TOOL_RE.test(prompt);
|
|
75
78
|
const effort = toolUse ? 'medium' : 'low';
|
|
79
|
+
const modelCapability = codexModelEffortCapability({ defaultEffort: effort });
|
|
76
80
|
return {
|
|
77
81
|
schema: 'sks.agent-effort-decision.v1',
|
|
78
82
|
policy_version: 1,
|
|
@@ -80,6 +84,7 @@ export function decideNarutoCloneEffort(input = {}) {
|
|
|
80
84
|
role,
|
|
81
85
|
reasoning_effort: effort,
|
|
82
86
|
model_reasoning_effort: effort,
|
|
87
|
+
model_effort_capability: modelCapability,
|
|
83
88
|
reasoning_profile: reasoningProfileName(effort),
|
|
84
89
|
service_tier: 'fast',
|
|
85
90
|
reason: toolUse ? 'naruto_tool_use_medium' : 'naruto_simple_no_tool_low',
|
|
@@ -107,7 +112,8 @@ export function buildAgentEffortPolicy(roster = {}) {
|
|
|
107
112
|
policy_version: 1,
|
|
108
113
|
dynamic: true,
|
|
109
114
|
service_tier: 'fast',
|
|
110
|
-
allowed_efforts:
|
|
115
|
+
allowed_efforts: codexModelEffortCapability().advertised_efforts,
|
|
116
|
+
model_effort_capability: codexModelEffortCapability(),
|
|
111
117
|
max_agents: roster.max_agents || 20,
|
|
112
118
|
agent_count: roster.agent_count || decisions.length,
|
|
113
119
|
concurrency: roster.concurrency || decisions.length,
|
|
@@ -476,7 +476,9 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
476
476
|
targetActiveSlots,
|
|
477
477
|
visiblePanes: visualLaneCount,
|
|
478
478
|
expectedWorkerRuntimeMs: targetActiveSlots >= 10 ? 8000 : targetActiveSlots >= 2 ? 2000 : 25,
|
|
479
|
-
minActiveWorkers: Math.min(targetActiveSlots, desiredWorkItemCount)
|
|
479
|
+
minActiveWorkers: Math.min(targetActiveSlots, desiredWorkItemCount),
|
|
480
|
+
proofMode: opts.mock === true ? 'mock-process' : 'production',
|
|
481
|
+
requireWorkerPids: opts.nativeCliSwarm !== false && targetActiveSlots >= 16
|
|
480
482
|
});
|
|
481
483
|
const results = scheduler.results;
|
|
482
484
|
const nativeCliSessionProof = await writeNativeCliSessionProof(ledgerRoot, {
|
|
@@ -21,6 +21,8 @@ export async function runAgentScheduler(input) {
|
|
|
21
21
|
const active = new Map();
|
|
22
22
|
const results = [];
|
|
23
23
|
const schedulerStartedAt = Date.now();
|
|
24
|
+
let lastUtilizationUpdateMs = schedulerStartedAt;
|
|
25
|
+
let activeSlotTimeMs = 0;
|
|
24
26
|
let batchCounter = 0;
|
|
25
27
|
let batchLaunchSpanTotalMs = 0;
|
|
26
28
|
let batchDispatchInProgress = false;
|
|
@@ -43,6 +45,7 @@ export async function runAgentScheduler(input) {
|
|
|
43
45
|
if (!entry)
|
|
44
46
|
continue;
|
|
45
47
|
const activeCountBeforeClose = active.size;
|
|
48
|
+
accumulateActiveSlotTime();
|
|
46
49
|
active.delete(settled.session_id);
|
|
47
50
|
const resultStatus = settled.result?.status === 'done' ? 'completed' : settled.result?.status === 'blocked' ? 'blocked' : 'failed';
|
|
48
51
|
completeWorkItem(queue, entry.work_item_id, settled.session_id, resultStatus, settled.error || null);
|
|
@@ -70,6 +73,7 @@ export async function runAgentScheduler(input) {
|
|
|
70
73
|
const pendingAfterClose = pendingWorkItems(queue).length;
|
|
71
74
|
if (pendingAfterClose > 0)
|
|
72
75
|
state.expected_backfill_count += 1;
|
|
76
|
+
updateUtilizationMetrics();
|
|
73
77
|
await writeAll(input.root, state, slots, queue, active, {
|
|
74
78
|
event_type: 'session_completed',
|
|
75
79
|
session_id: settled.session_id,
|
|
@@ -85,6 +89,7 @@ export async function runAgentScheduler(input) {
|
|
|
85
89
|
closed_at_ms: Date.now()
|
|
86
90
|
} : null);
|
|
87
91
|
}
|
|
92
|
+
updateUtilizationMetrics();
|
|
88
93
|
state.status = 'draining';
|
|
89
94
|
await writeAll(input.root, state, slots, queue, active, { event_type: 'scheduler_draining' }, input.onSchedulerEvent);
|
|
90
95
|
slots = closeWorkerSlotsAfterDrain(slots);
|
|
@@ -204,6 +209,7 @@ export async function runAgentScheduler(input) {
|
|
|
204
209
|
error: err instanceof Error ? err.message : String(err),
|
|
205
210
|
terminal_close_report_path: path.join(generation.artifact_dir, 'agent-terminal-close-report.json')
|
|
206
211
|
}));
|
|
212
|
+
accumulateActiveSlotTime();
|
|
207
213
|
active.set(generation.session_id, { slot_id: slot.slot_id, work_item_id: workItem.id, session_id: generation.session_id, promise });
|
|
208
214
|
}
|
|
209
215
|
await appendAgentWorkQueueEvent(input.root, 'batch_work_items_dispatched', {
|
|
@@ -317,11 +323,18 @@ export async function runAgentScheduler(input) {
|
|
|
317
323
|
return launches;
|
|
318
324
|
}
|
|
319
325
|
function updateUtilizationMetrics() {
|
|
326
|
+
accumulateActiveSlotTime();
|
|
320
327
|
state.wall_time_ms = Math.max(0, Date.now() - schedulerStartedAt);
|
|
321
|
-
state.active_slot_time_ms =
|
|
328
|
+
state.active_slot_time_ms = activeSlotTimeMs;
|
|
322
329
|
const denominator = Math.max(1, state.wall_time_ms * targetActiveSlots);
|
|
323
330
|
state.scheduler_utilization = Number(Math.min(1, state.active_slot_time_ms / denominator).toFixed(3));
|
|
324
331
|
}
|
|
332
|
+
function accumulateActiveSlotTime() {
|
|
333
|
+
const now = Date.now();
|
|
334
|
+
const delta = Math.max(0, now - lastUtilizationUpdateMs);
|
|
335
|
+
activeSlotTimeMs += active.size * delta;
|
|
336
|
+
lastUtilizationUpdateMs = now;
|
|
337
|
+
}
|
|
325
338
|
}
|
|
326
339
|
export function normalizeTargetActiveSlots(value, maxActiveSlots = MAX_AGENT_COUNT) {
|
|
327
340
|
const cap = Number.isFinite(Number(maxActiveSlots)) && Number(maxActiveSlots) >= 1 ? Math.floor(Number(maxActiveSlots)) : MAX_AGENT_COUNT;
|
|
@@ -8,7 +8,7 @@ import { closeWorkerPane, openWorkerPane } from '../zellij/zellij-worker-pane-ma
|
|
|
8
8
|
import { closeWorkerInRightColumn, recordHeadlessWorkerInRightColumn } from '../zellij/zellij-right-column-manager.js';
|
|
9
9
|
import { resolveProviderContext } from '../provider/provider-context.js';
|
|
10
10
|
import { buildZellijSlotPaneCommand } from '../zellij/zellij-slot-pane-renderer.js';
|
|
11
|
-
import {
|
|
11
|
+
import { resolveZellijWorkerPaneUiMode } from '../zellij/zellij-ui-mode.js';
|
|
12
12
|
import { appendZellijSlotTelemetry } from '../zellij/zellij-slot-telemetry.js';
|
|
13
13
|
import { appendParallelRuntimeEvent } from './parallel-runtime-proof.js';
|
|
14
14
|
export const NATIVE_CLI_SESSION_SWARM_SCHEMA = 'sks.agent-native-cli-session-swarm.v1';
|
|
@@ -278,7 +278,8 @@ class NativeCliSessionSwarmRecorder {
|
|
|
278
278
|
route: this.input.route,
|
|
279
279
|
serviceTier: this.input.fastModePolicy.service_tier
|
|
280
280
|
});
|
|
281
|
-
const uiMode =
|
|
281
|
+
const uiMode = resolveZellijWorkerPaneUiMode(Array.isArray(input.ctx.opts.args) ? input.ctx.opts.args : [], process.env);
|
|
282
|
+
const liveWorkerPane = uiMode !== 'compact-slots';
|
|
282
283
|
const workerEnv = {
|
|
283
284
|
...(input.ctx.opts.env || {}),
|
|
284
285
|
...fastModeEnv(this.input.fastModePolicy),
|
|
@@ -300,7 +301,7 @@ class NativeCliSessionSwarmRecorder {
|
|
|
300
301
|
artifacts: [path.join(input.workerDirRel, 'worker-intake.json'), input.heartbeatRel, input.resultRel],
|
|
301
302
|
logTail: `zellij=${sessionName}`
|
|
302
303
|
});
|
|
303
|
-
const workerCommand =
|
|
304
|
+
const workerCommand = liveWorkerPane
|
|
304
305
|
? buildPaneWorkerCommand({
|
|
305
306
|
args: input.args,
|
|
306
307
|
stdoutPath: path.join(this.root, input.stdoutRel),
|
|
@@ -332,7 +333,7 @@ class NativeCliSessionSwarmRecorder {
|
|
|
332
333
|
mode: uiMode,
|
|
333
334
|
watch: true
|
|
334
335
|
});
|
|
335
|
-
const processRun =
|
|
336
|
+
const processRun = liveWorkerPane
|
|
336
337
|
? null
|
|
337
338
|
: await this.spawnCompactSlotWorkerProcess({
|
|
338
339
|
args: input.args,
|
|
@@ -405,7 +406,7 @@ class NativeCliSessionSwarmRecorder {
|
|
|
405
406
|
const zellijRequired = process.env.SKS_REQUIRE_ZELLIJ === '1';
|
|
406
407
|
const launchBlockers = zellijRequired ? paneRecord.blockers || [] : [];
|
|
407
408
|
const launchWarnings = zellijRequired ? [] : paneRecord.blockers || [];
|
|
408
|
-
input.record.command_line = ['zellij', '--session', sessionName, 'action', 'new-pane', '--direction', paneRecord.direction_applied, '--name', paneRecord.pane_name, '--', 'sh', '-lc',
|
|
409
|
+
input.record.command_line = ['zellij', '--session', sessionName, 'action', 'new-pane', '--direction', paneRecord.direction_applied, '--name', paneRecord.pane_name, '--', 'sh', '-lc', liveWorkerPane ? '<native-cli-worker-command>' : '<zellij-slot-pane-renderer-command>'];
|
|
409
410
|
input.record.zellij_session_name = sessionName;
|
|
410
411
|
input.record.zellij_pane_id = paneRecord.pane_id || null;
|
|
411
412
|
input.record.zellij_pane_id_source = paneRecord.pane_id_source;
|
|
@@ -419,7 +420,7 @@ class NativeCliSessionSwarmRecorder {
|
|
|
419
420
|
input.record.provider_context = paneRecord.provider_context;
|
|
420
421
|
input.record.worktree = worktree;
|
|
421
422
|
input.record.zellij_ui_mode = uiMode;
|
|
422
|
-
input.record.slot_visualization =
|
|
423
|
+
input.record.slot_visualization = liveWorkerPane ? 'worker-command-pane' : 'zellij-slot-pane-renderer';
|
|
423
424
|
input.record.status = launchBlockers.length ? 'failed' : 'running';
|
|
424
425
|
input.record.blockers = launchBlockers;
|
|
425
426
|
input.record.warnings = [...(input.record.warnings || []), ...launchWarnings];
|
|
@@ -741,7 +742,10 @@ export function buildPaneWorkerCommand(input) {
|
|
|
741
742
|
const holdMs = Math.max(0, Number(process.env.SKS_ZELLIJ_WORKER_PANE_HOLD_MS || 1500));
|
|
742
743
|
const hold = holdMs > 0 ? `sleep ${shellQuote(String(Math.min(30, holdMs / 1000)))}` : ':';
|
|
743
744
|
const header = input.header ? `printf '%s\\n' ${shellQuote(input.header)} | tee -a ${shellQuote(input.stdoutPath)};` : '';
|
|
744
|
-
|
|
745
|
+
const exitPath = `${input.heartbeatPath}.exit`;
|
|
746
|
+
const visibleCommand = `(${command}; printf '%s' "$?" > ${shellQuote(exitPath)}) 2>&1 | tee -a ${shellQuote(input.stdoutPath)}`;
|
|
747
|
+
const readExit = `code=$(cat ${shellQuote(exitPath)} 2>/dev/null || printf '1'); rm -f ${shellQuote(exitPath)}`;
|
|
748
|
+
return `${envPrefix.join(' ')} ${header} ${visibleCommand}; ${readExit}; ${heartbeat}; ${hold}; exit $code`.trim();
|
|
745
749
|
}
|
|
746
750
|
function buildPaneWorkerHeader(input) {
|
|
747
751
|
return [
|
|
@@ -126,18 +126,33 @@ export async function runNativeCliWorker(input = {}) {
|
|
|
126
126
|
});
|
|
127
127
|
await writeJsonAtomic(path.join(workerDir, 'worker-recursion-guard.json'), guard);
|
|
128
128
|
let noPatchReason = null;
|
|
129
|
-
const
|
|
129
|
+
const progressTelemetry = startWorkerProgressTelemetry({
|
|
130
130
|
agentRoot,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
patchRel,
|
|
131
|
+
heartbeatRel,
|
|
132
|
+
intake,
|
|
134
133
|
agent,
|
|
135
134
|
slice,
|
|
136
|
-
intake: { ...intake, ...input },
|
|
137
135
|
backend,
|
|
138
|
-
|
|
139
|
-
guard
|
|
136
|
+
serviceTier: policy.service_tier
|
|
140
137
|
});
|
|
138
|
+
let routed;
|
|
139
|
+
try {
|
|
140
|
+
routed = await runNativeWorkerBackendRouter({
|
|
141
|
+
agentRoot,
|
|
142
|
+
workerDirRel,
|
|
143
|
+
resultRel,
|
|
144
|
+
patchRel,
|
|
145
|
+
agent,
|
|
146
|
+
slice,
|
|
147
|
+
intake: { ...intake, ...input },
|
|
148
|
+
backend,
|
|
149
|
+
fastModePolicy: policy,
|
|
150
|
+
guard
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
progressTelemetry.stop();
|
|
155
|
+
}
|
|
141
156
|
const patchEnvelopes = routed.patchEnvelopes;
|
|
142
157
|
if (patchEnvelopes.length) {
|
|
143
158
|
await writeJsonAtomic(path.resolve(agentRoot, patchRel), {
|
|
@@ -330,6 +345,39 @@ export async function runNativeCliWorker(input = {}) {
|
|
|
330
345
|
function delay(ms) {
|
|
331
346
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
332
347
|
}
|
|
348
|
+
function startWorkerProgressTelemetry(input) {
|
|
349
|
+
const parsed = Number(process.env.SKS_ZELLIJ_WORKER_PROGRESS_MS || 2000);
|
|
350
|
+
const intervalMs = Math.max(500, Number.isFinite(parsed) ? Math.floor(parsed) : 2000);
|
|
351
|
+
let tick = 0;
|
|
352
|
+
const timer = setInterval(() => {
|
|
353
|
+
tick += 1;
|
|
354
|
+
const progress = { done: tick, total: 0, label: 'backend running' };
|
|
355
|
+
appendJsonl(path.resolve(input.agentRoot, input.heartbeatRel), {
|
|
356
|
+
schema: 'sks.native-cli-worker-heartbeat.v1',
|
|
357
|
+
ts: nowIso(),
|
|
358
|
+
event: 'progress',
|
|
359
|
+
pid: process.pid,
|
|
360
|
+
session_id: input.agent.session_id,
|
|
361
|
+
slot_id: input.agent.slot_id || null,
|
|
362
|
+
generation_index: input.agent.generation_index || null,
|
|
363
|
+
progress
|
|
364
|
+
}).catch(() => undefined);
|
|
365
|
+
workerTelemetry(input.agentRoot, input.intake, input.agent, input.slice, {
|
|
366
|
+
eventType: 'task_progress',
|
|
367
|
+
status: 'running',
|
|
368
|
+
backend: input.backend,
|
|
369
|
+
serviceTier: input.serviceTier,
|
|
370
|
+
artifacts: [input.heartbeatRel],
|
|
371
|
+
progress,
|
|
372
|
+
logTail: `backend running ${tick}`
|
|
373
|
+
}).catch(() => undefined);
|
|
374
|
+
}, intervalMs);
|
|
375
|
+
return {
|
|
376
|
+
stop() {
|
|
377
|
+
clearInterval(timer);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
}
|
|
333
381
|
function parseNativeCliWorkerArgs(args) {
|
|
334
382
|
return {
|
|
335
383
|
intake: readOption(args, '--intake', ''),
|
|
@@ -389,6 +437,7 @@ async function workerTelemetry(agentRoot, intake, agent, slice, input) {
|
|
|
389
437
|
worktree_path: agent.worktree?.path || slice.worktree?.path || intake.worktree?.path || null,
|
|
390
438
|
task_title: String(slice.description || slice.title || slice.id || 'worker task'),
|
|
391
439
|
current_file: firstString([slice.write_paths?.[0], slice.readonly_paths?.[0], slice.input_files?.[0]]) || null,
|
|
440
|
+
...(input.progress ? { progress: input.progress } : {}),
|
|
392
441
|
artifact_paths: input.artifacts || [],
|
|
393
442
|
log_tail: input.logTail || '',
|
|
394
443
|
blockers: input.blockers || []
|