sneakoscope 1.18.1 → 1.18.2

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 (61) hide show
  1. package/README.md +5 -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/.sks-build-stamp.json +4 -4
  6. package/dist/bin/sks.js +1 -1
  7. package/dist/build-manifest.json +15 -9
  8. package/dist/commands/image-ux-review.d.ts +24 -1
  9. package/dist/commands/ppt.d.ts +24 -1
  10. package/dist/core/agents/agent-command-surface.d.ts +4 -0
  11. package/dist/core/agents/agent-command-surface.js +6 -2
  12. package/dist/core/agents/agent-follow-up-work-items.d.ts +20 -0
  13. package/dist/core/agents/agent-follow-up-work-items.js +115 -0
  14. package/dist/core/agents/agent-janitor.d.ts +3 -0
  15. package/dist/core/agents/agent-janitor.js +7 -1
  16. package/dist/core/agents/agent-orchestrator.d.ts +24 -1
  17. package/dist/core/agents/agent-orchestrator.js +44 -7
  18. package/dist/core/agents/agent-output-validator.d.ts +51 -0
  19. package/dist/core/agents/agent-output-validator.js +34 -0
  20. package/dist/core/agents/agent-proof-evidence.d.ts +5 -0
  21. package/dist/core/agents/agent-proof-evidence.js +28 -2
  22. package/dist/core/agents/agent-runner-codex-exec.d.ts +1 -0
  23. package/dist/core/agents/agent-runner-fake.js +20 -0
  24. package/dist/core/agents/agent-runner-process.js +16 -1
  25. package/dist/core/agents/agent-runner-tmux.d.ts +1 -1
  26. package/dist/core/agents/agent-runner-tmux.js +9 -6
  27. package/dist/core/agents/agent-scheduler.d.ts +2 -0
  28. package/dist/core/agents/agent-scheduler.js +20 -2
  29. package/dist/core/agents/agent-schema.d.ts +16 -0
  30. package/dist/core/agents/agent-task-graph.d.ts +52 -0
  31. package/dist/core/agents/agent-task-graph.js +193 -0
  32. package/dist/core/agents/agent-terminal-session.d.ts +11 -0
  33. package/dist/core/agents/agent-terminal-session.js +48 -0
  34. package/dist/core/agents/agent-trust-report.d.ts +12 -0
  35. package/dist/core/agents/agent-trust-report.js +21 -0
  36. package/dist/core/agents/agent-work-partition.d.ts +15 -1
  37. package/dist/core/agents/agent-work-partition.js +23 -2
  38. package/dist/core/agents/agent-work-queue.js +11 -5
  39. package/dist/core/agents/agent-worker-pipeline.js +7 -1
  40. package/dist/core/agents/agent-wrongness.d.ts +1 -1
  41. package/dist/core/agents/agent-wrongness.js +2 -0
  42. package/dist/core/agents/route-collaboration-ledger.d.ts +24 -1
  43. package/dist/core/agents/tmux-lane-supervisor.d.ts +51 -0
  44. package/dist/core/agents/tmux-lane-supervisor.js +197 -0
  45. package/dist/core/agents/work-partition/task-slicer.d.ts +4 -0
  46. package/dist/core/agents/work-partition/task-slicer.js +18 -1
  47. package/dist/core/commands/agent-command.js +9 -2
  48. package/dist/core/commands/command-utils.js +2 -1
  49. package/dist/core/commands/image-ux-review-command.d.ts +24 -1
  50. package/dist/core/commands/ppt-command.d.ts +24 -1
  51. package/dist/core/commands/qa-loop-command.js +4 -2
  52. package/dist/core/commands/research-command.js +3 -1
  53. package/dist/core/commands/team-command.js +8 -2
  54. package/dist/core/fsx.d.ts +1 -1
  55. package/dist/core/fsx.js +1 -1
  56. package/dist/core/routes.js +2 -2
  57. package/dist/core/team-live.js +6 -0
  58. package/dist/core/version.d.ts +1 -1
  59. package/dist/core/version.js +1 -1
  60. package/package.json +12 -2
  61. package/schemas/codex/agent-result.schema.json +30 -0
package/README.md CHANGED
@@ -10,7 +10,7 @@ SKS does not try to clone every other harness. It focuses on one thing: making C
10
10
 
11
11
  ## Current Release
12
12
 
13
- SKS **1.18.1** adds Dynamic Agent Pool replenishment: `agents=5` now means keep up to five active worker slots running until the work queue drains, with immutable session generations, generation-aware terminal close reports, real/fake-tmux pane launch evidence, and Source Intelligence / Goal mode refs propagated to every generation.
13
+ SKS **1.18.2** completes the Dynamic Worker Pool runtime: `agents=5` means five target active worker slots, while `--work-items N` controls the route work queue. Pending work backfills empty slots immediately, tmux lanes persist as worker-slot UI until scheduler drain, follow-up work items are schema-bound, and Agent/Team/Research/QA route blackboxes prove replenishment with generation, terminal, Source Intelligence, and Goal evidence.
14
14
 
15
15
  ```bash
16
16
  sks mad-sks plan --target-root <path> --json
@@ -19,10 +19,11 @@ sks mad-sks proof --json
19
19
  sks mad-sks rollback-apply --rollback-plan <path> --yes --json
20
20
  sks features complete --json
21
21
  sks agent status latest --json
22
- sks agent run "release review" --agents 8 --concurrency 4 --mock --json
22
+ sks agent run "release review" --agents 8 --work-items 16 --concurrency 4 --mock --json
23
23
  npm run source-intelligence:all-modes
24
24
  npm run agent:background-terminals
25
- npm run agent:tmux-right-lanes
25
+ npm run agent:tmux-lane-no-flicker
26
+ npm run agent:backfill-route-blackbox
26
27
  npm run release:readiness
27
28
  ```
28
29
 
@@ -612,7 +613,7 @@ npm run release:check
612
613
  npm run publish:dry
613
614
  ```
614
615
 
615
- `release:check` runs the 1.18.1 dynamic agent pool closure DAG, writes a source digest stamp under `.sneakoscope/reports/`, then refreshes release readiness so publish commands can verify the same stamp. The DAG preserves the 1.18 baseline gates and adds dynamic pool, backfill replenishment, scheduler proof, session generation, terminal generation, tmux real right-lane, dynamic cockpit, Source Intelligence propagation, and Goal mode propagation checks. Broader live or historical gates remain explicit scripts such as `release:real-check`. Generate the human-readable registry with `sks features inventory --write-docs`. Plain `npm publish` uses the `latest` dist-tag. npm's `prepublishOnly` verifies the fresh release stamp instead of rerunning the full gate, and `prepack` only rebuilds `dist`; publish no longer repeats the expensive release suite during packaging. `npm run publish:dry` remains the explicit dry-run helper.
616
+ `release:check` runs the 1.18.2 dynamic scheduler closure DAG, writes a source digest stamp under `.sneakoscope/reports/`, then refreshes release readiness so publish commands can verify the same stamp. The DAG preserves the 1.18 baseline gates and adds task graph expansion, schema-bound follow-up work, Agent/Team/Research/QA route backfill blackboxes, scheduler proof hardening, persistent tmux lane persistence, no-flicker lane proof, session generation, terminal generation, dynamic cockpit, Source Intelligence propagation, and Goal mode propagation checks. Broader live or historical gates remain explicit scripts such as `release:real-check`. Generate the human-readable registry with `sks features inventory --write-docs`. Plain `npm publish` uses the `latest` dist-tag. npm's `prepublishOnly` verifies the fresh release stamp instead of rerunning the full gate, and `prepack` only rebuilds `dist`; publish no longer repeats the expensive release suite during packaging. `npm run publish:dry` remains the explicit dry-run helper.
616
617
 
617
618
  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.
618
619
 
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "1.18.1"
79
+ version = "1.18.2"
80
80
  dependencies = [
81
81
  "serde_json",
82
82
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "1.18.1"
3
+ version = "1.18.2"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
4
4
  fn main() {
5
5
  let mut args = std::env::args().skip(1);
6
6
  match args.next().as_deref() {
7
- Some("--version") => println!("sks-rs 1.18.1"),
7
+ Some("--version") => println!("sks-rs 1.18.2"),
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": "1.18.1",
5
- "source_digest": "6df40e82722a56a4df2efafa956011204d7a96fd218b43d19aa10672bbd0842c",
6
- "source_file_count": 1312,
7
- "built_at_source_time": 1779722031788
4
+ "package_version": "1.18.2",
5
+ "source_digest": "83db107971a9e8bec6aaca8f43bf8b49d936e5fc778ebd62121dea9b7fc228f5",
6
+ "source_file_count": 1349,
7
+ "built_at_source_time": 1779732183819
8
8
  }
package/dist/bin/sks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const FAST_PACKAGE_VERSION = '1.18.1';
2
+ const FAST_PACKAGE_VERSION = '1.18.2';
3
3
  const args = process.argv.slice(2);
4
4
  try {
5
5
  if (args[0] === '--version' || args[0] === '-v' || args[0] === 'version') {
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "schema": "sks.dist-build.v2",
3
- "version": "1.18.1",
4
- "package_version": "1.18.1",
3
+ "version": "1.18.2",
4
+ "package_version": "1.18.2",
5
5
  "typescript": true,
6
6
  "mjs_runtime_files": 0,
7
- "compiled_file_count": 858,
8
- "compiled_js_count": 429,
9
- "compiled_dts_count": 429,
10
- "source_digest": "6df40e82722a56a4df2efafa956011204d7a96fd218b43d19aa10672bbd0842c",
11
- "source_file_count": 1312,
12
- "source_files_hash": "fbe2aa994acefbdab214a17074d539960fa99369b928c3679442019ace20e7c6",
13
- "source_list_hash": "fbe2aa994acefbdab214a17074d539960fa99369b928c3679442019ace20e7c6",
7
+ "compiled_file_count": 864,
8
+ "compiled_js_count": 432,
9
+ "compiled_dts_count": 432,
10
+ "source_digest": "83db107971a9e8bec6aaca8f43bf8b49d936e5fc778ebd62121dea9b7fc228f5",
11
+ "source_file_count": 1349,
12
+ "source_files_hash": "fb0fc5d3cacbb13d3231fcf9d0566e1bad998e7bc8aeea7c7e4f10049e433c11",
13
+ "source_list_hash": "fb0fc5d3cacbb13d3231fcf9d0566e1bad998e7bc8aeea7c7e4f10049e433c11",
14
14
  "src_mjs_runtime_files": 0,
15
15
  "dist_stamp_schema": "sks.dist-build-stamp.v1",
16
16
  "files": [
@@ -198,6 +198,8 @@
198
198
  "core/agents/agent-consensus.js",
199
199
  "core/agents/agent-effort-policy.d.ts",
200
200
  "core/agents/agent-effort-policy.js",
201
+ "core/agents/agent-follow-up-work-items.d.ts",
202
+ "core/agents/agent-follow-up-work-items.js",
201
203
  "core/agents/agent-gate.d.ts",
202
204
  "core/agents/agent-gate.js",
203
205
  "core/agents/agent-heartbeat.d.ts",
@@ -242,6 +244,8 @@
242
244
  "core/agents/agent-session-generation.js",
243
245
  "core/agents/agent-session-rows.d.ts",
244
246
  "core/agents/agent-session-rows.js",
247
+ "core/agents/agent-task-graph.d.ts",
248
+ "core/agents/agent-task-graph.js",
245
249
  "core/agents/agent-task-slicer.d.ts",
246
250
  "core/agents/agent-task-slicer.js",
247
251
  "core/agents/agent-terminal-session.d.ts",
@@ -262,6 +266,8 @@
262
266
  "core/agents/route-collaboration-ledger.js",
263
267
  "core/agents/scout-policy.d.ts",
264
268
  "core/agents/scout-policy.js",
269
+ "core/agents/tmux-lane-supervisor.d.ts",
270
+ "core/agents/tmux-lane-supervisor.js",
265
271
  "core/agents/tmux-right-lane-cockpit.d.ts",
266
272
  "core/agents/tmux-right-lane-cockpit.js",
267
273
  "core/agents/work-partition/conflict-detector.d.ts",
@@ -436,6 +436,12 @@ export declare function run(command: any, args?: any): Promise<void | {
436
436
  lease_count: number;
437
437
  blockers: string[];
438
438
  };
439
+ task_graph: {
440
+ target_active_slots: number;
441
+ total_work_items: number;
442
+ generated_from_route: string;
443
+ work_items_exceed_active_slots: boolean;
444
+ };
439
445
  scheduler: {
440
446
  schema: string;
441
447
  ok: boolean;
@@ -549,12 +555,24 @@ export declare function run(command: any, args?: any): Promise<void | {
549
555
  terminal_sessions_closed: any;
550
556
  terminal_close_report: string;
551
557
  target_active_slots: any;
558
+ total_work_items: any;
559
+ pending_count: any;
560
+ active_slot_count: any;
561
+ completed_count: any;
552
562
  max_observed_active_slots: any;
553
563
  backfill_count: any;
564
+ expected_backfill_count: any;
554
565
  pending_queue_drained: any;
555
566
  generation_count: any;
556
567
  tmux_attach_command: string | null;
557
568
  tmux_lane_manifest: string;
569
+ tmux_lane_persistence: {
570
+ supervisor: string;
571
+ no_flicker_verified: boolean;
572
+ pane_survival_checked: boolean;
573
+ unexpected_close_count: number;
574
+ lane_count: number;
575
+ };
558
576
  output_schema_ok: boolean;
559
577
  output_tail_report: string;
560
578
  output_tail_records: number;
@@ -569,7 +587,7 @@ export declare function run(command: any, args?: any): Promise<void | {
569
587
  generated_at: string;
570
588
  records: {
571
589
  schema: string;
572
- kind: "xai_available_not_used" | "context7_missing" | "codex_web_search_missing" | "recursion_attempt" | "lease_conflict" | "session_not_closed" | "terminal_missing" | "terminal_not_closed" | "scheduler_starvation" | "session_generation_missing" | "schema_invalid_output" | "stale_heartbeat" | "legacy_multiagent_runtime_usage_attempt";
590
+ kind: "xai_available_not_used" | "context7_missing" | "codex_web_search_missing" | "recursion_attempt" | "lease_conflict" | "session_not_closed" | "terminal_missing" | "terminal_not_closed" | "scheduler_starvation" | "tmux_lane_flicker" | "missing_follow_up_schema" | "session_generation_missing" | "schema_invalid_output" | "stale_heartbeat" | "legacy_multiagent_runtime_usage_attempt";
573
591
  blocker: string;
574
592
  created_at: string;
575
593
  status: string;
@@ -610,6 +628,11 @@ export declare function run(command: any, args?: any): Promise<void | {
610
628
  goal_mode_generation_refs_ok: boolean;
611
629
  tmux_lane_manifest: string;
612
630
  tmux_lane_manifest_ok: boolean;
631
+ tmux_lane_supervisor: string;
632
+ tmux_lane_no_flicker_verified: boolean;
633
+ tmux_lane_survival_checked: boolean;
634
+ tmux_lane_unexpected_close_count: number;
635
+ tmux_lane_auto_reopen_count: number;
613
636
  tmux_pane_launch_ledger: string;
614
637
  tmux_pane_launch_count: number;
615
638
  ledger_hash_chain_ok: boolean;
@@ -288,6 +288,12 @@ export declare function run(command: any, args?: any): Promise<void | {
288
288
  lease_count: number;
289
289
  blockers: string[];
290
290
  };
291
+ task_graph: {
292
+ target_active_slots: number;
293
+ total_work_items: number;
294
+ generated_from_route: string;
295
+ work_items_exceed_active_slots: boolean;
296
+ };
291
297
  scheduler: {
292
298
  schema: string;
293
299
  ok: boolean;
@@ -401,12 +407,24 @@ export declare function run(command: any, args?: any): Promise<void | {
401
407
  terminal_sessions_closed: any;
402
408
  terminal_close_report: string;
403
409
  target_active_slots: any;
410
+ total_work_items: any;
411
+ pending_count: any;
412
+ active_slot_count: any;
413
+ completed_count: any;
404
414
  max_observed_active_slots: any;
405
415
  backfill_count: any;
416
+ expected_backfill_count: any;
406
417
  pending_queue_drained: any;
407
418
  generation_count: any;
408
419
  tmux_attach_command: string | null;
409
420
  tmux_lane_manifest: string;
421
+ tmux_lane_persistence: {
422
+ supervisor: string;
423
+ no_flicker_verified: boolean;
424
+ pane_survival_checked: boolean;
425
+ unexpected_close_count: number;
426
+ lane_count: number;
427
+ };
410
428
  output_schema_ok: boolean;
411
429
  output_tail_report: string;
412
430
  output_tail_records: number;
@@ -421,7 +439,7 @@ export declare function run(command: any, args?: any): Promise<void | {
421
439
  generated_at: string;
422
440
  records: {
423
441
  schema: string;
424
- kind: "xai_available_not_used" | "context7_missing" | "codex_web_search_missing" | "recursion_attempt" | "lease_conflict" | "session_not_closed" | "terminal_missing" | "terminal_not_closed" | "scheduler_starvation" | "session_generation_missing" | "schema_invalid_output" | "stale_heartbeat" | "legacy_multiagent_runtime_usage_attempt";
442
+ kind: "xai_available_not_used" | "context7_missing" | "codex_web_search_missing" | "recursion_attempt" | "lease_conflict" | "session_not_closed" | "terminal_missing" | "terminal_not_closed" | "scheduler_starvation" | "tmux_lane_flicker" | "missing_follow_up_schema" | "session_generation_missing" | "schema_invalid_output" | "stale_heartbeat" | "legacy_multiagent_runtime_usage_attempt";
425
443
  blocker: string;
426
444
  created_at: string;
427
445
  status: string;
@@ -462,6 +480,11 @@ export declare function run(command: any, args?: any): Promise<void | {
462
480
  goal_mode_generation_refs_ok: boolean;
463
481
  tmux_lane_manifest: string;
464
482
  tmux_lane_manifest_ok: boolean;
483
+ tmux_lane_supervisor: string;
484
+ tmux_lane_no_flicker_verified: boolean;
485
+ tmux_lane_survival_checked: boolean;
486
+ tmux_lane_unexpected_close_count: number;
487
+ tmux_lane_auto_reopen_count: number;
465
488
  tmux_pane_launch_ledger: string;
466
489
  tmux_pane_launch_count: number;
467
490
  ledger_hash_chain_ok: boolean;
@@ -4,6 +4,10 @@ export declare function parseAgentCommandArgs(command: string, args?: string[]):
4
4
  prompt: string;
5
5
  route: string;
6
6
  agents: number;
7
+ targetActiveSlots: number;
8
+ desiredWorkItemCount: number;
9
+ minimumWorkItems: number;
10
+ maxQueueExpansion: number;
7
11
  concurrency: number;
8
12
  backend: string;
9
13
  mock: boolean;
@@ -6,6 +6,10 @@ export function parseAgentCommandArgs(command, args = []) {
6
6
  const rest = action === first ? args.slice(1) : args;
7
7
  const json = hasFlag(args, '--json');
8
8
  const agents = Number(readOption(args, '--agents', DEFAULT_AGENT_COUNT));
9
+ const targetActiveSlots = Number(readOption(args, '--target-active-slots', agents));
10
+ const desiredWorkItemCount = Number(readOption(args, '--work-items', targetActiveSlots));
11
+ const minimumWorkItems = Number(readOption(args, '--minimum-work-items', targetActiveSlots));
12
+ const maxQueueExpansion = Number(readOption(args, '--max-queue-expansion', 10));
9
13
  const concurrency = Number(readOption(args, '--concurrency', Math.min(agents, 5)));
10
14
  const backend = String(readOption(args, '--backend', hasFlag(args, '--mock') ? 'fake' : 'codex-exec'));
11
15
  const route = String(readOption(args, '--route', '$Agent'));
@@ -13,14 +17,14 @@ export function parseAgentCommandArgs(command, args = []) {
13
17
  const real = hasFlag(args, '--real');
14
18
  const readonly = hasFlag(args, '--readonly') || hasFlag(args, '--read-only');
15
19
  const codexApp = hasFlag(args, '--codex-app');
16
- const positionals = positionalArgs(rest, new Set(['--agents', '--concurrency', '--backend', '--route', '--mission', '--mission-id', '--agent', '--lane']));
20
+ const positionals = positionalArgs(rest, new Set(['--agents', '--target-active-slots', '--work-items', '--minimum-work-items', '--max-queue-expansion', '--concurrency', '--backend', '--route', '--mission', '--mission-id', '--agent', '--lane']));
17
21
  const missionDefault = action === 'run' || action === 'spawn' || action === 'plan' ? '' : 'latest';
18
22
  const positionalMission = action === 'run' || action === 'spawn' || action === 'plan' ? '' : (positionals[0] || '');
19
23
  const missionId = String(readOption(args, '--mission', readOption(args, '--mission-id', positionalMission || missionDefault)));
20
24
  const lane = String(readOption(args, '--agent', readOption(args, '--lane', '')));
21
25
  const promptPositionals = positionalMission ? positionals.slice(1) : positionals;
22
26
  const prompt = promptPositionals.join(' ').trim() || 'Native agent run';
23
- return { command, action, prompt, route, agents, concurrency, backend, mock, real, readonly, json, missionId, lane, codexApp };
27
+ return { command, action, prompt, route, agents, targetActiveSlots, desiredWorkItemCount, minimumWorkItems, maxQueueExpansion, concurrency, backend, mock, real, readonly, json, missionId, lane, codexApp };
24
28
  }
25
29
  function hasFlag(args, flag) {
26
30
  return args.includes(flag);
@@ -0,0 +1,20 @@
1
+ export interface AgentFollowUpWorkItem {
2
+ id: string;
3
+ title: string;
4
+ description: string;
5
+ required_persona_category: string;
6
+ priority: number;
7
+ dependencies: string[];
8
+ lease_requirements: unknown[];
9
+ max_attempts: number;
10
+ reason: string;
11
+ source_agent_session_id?: string;
12
+ }
13
+ export interface AgentFollowUpValidationResult {
14
+ accepted: AgentFollowUpWorkItem[];
15
+ blockers: string[];
16
+ }
17
+ export declare function normalizeAgentFollowUpWorkItems(rawItems: unknown, input?: {
18
+ originSessionId?: string | null;
19
+ }): AgentFollowUpValidationResult;
20
+ //# sourceMappingURL=agent-follow-up-work-items.d.ts.map
@@ -0,0 +1,115 @@
1
+ import { scanAgentTextForRecursion } from './agent-recursion-guard.js';
2
+ const FOLLOW_UP_KEYS = new Set([
3
+ 'id',
4
+ 'title',
5
+ 'description',
6
+ 'required_persona_category',
7
+ 'priority',
8
+ 'dependencies',
9
+ 'lease_requirements',
10
+ 'max_attempts',
11
+ 'reason',
12
+ 'source_agent_session_id'
13
+ ]);
14
+ const PROTECTED_WRITE_PATH_RE = /^(?:\.codex|\.agents|AGENTS\.md|node_modules\/sneakoscope|\.sneakoscope\/.*policy.*\.json)(?:\/|$)/;
15
+ const MAIN_ROUTE_RECURSION_RE = /(?:\bsks\s+(?:team|agent|research|qa-loop|goal)\b|\$(?:Team|Goal|Research|QA-LOOP|Agent)\b|main\s+route\s+recursion)/i;
16
+ const GLOBAL_SCOUT_LEDGER_RE = /global\s+scout\s+ledger/i;
17
+ export function normalizeAgentFollowUpWorkItems(rawItems, input = {}) {
18
+ if (rawItems === undefined || rawItems === null)
19
+ return { accepted: [], blockers: [] };
20
+ if (!Array.isArray(rawItems))
21
+ return { accepted: [], blockers: ['follow_up_work_items_not_array'] };
22
+ const accepted = [];
23
+ const blockers = [];
24
+ rawItems.forEach((raw, index) => {
25
+ const result = normalizeAgentFollowUpWorkItem(raw, index, input.originSessionId || null);
26
+ if (result.item)
27
+ accepted.push(result.item);
28
+ blockers.push(...result.blockers);
29
+ });
30
+ return { accepted, blockers };
31
+ }
32
+ function normalizeAgentFollowUpWorkItem(raw, index, originSessionId) {
33
+ const blockers = [];
34
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
35
+ return { item: null, blockers: [`follow_up_work_item_${index + 1}_not_object`] };
36
+ }
37
+ const row = raw;
38
+ for (const key of Object.keys(row)) {
39
+ if (!FOLLOW_UP_KEYS.has(key))
40
+ blockers.push(`follow_up_work_item_${index + 1}_additional_property:${key}`);
41
+ }
42
+ const id = requiredString(row.id, 'id', index, blockers);
43
+ const title = requiredString(row.title, 'title', index, blockers);
44
+ const description = requiredString(row.description, 'description', index, blockers);
45
+ const requiredPersonaCategory = requiredString(row.required_persona_category, 'required_persona_category', index, blockers);
46
+ const reason = requiredString(row.reason, 'reason', index, blockers);
47
+ const priority = requiredInteger(row.priority, 'priority', index, blockers, 0);
48
+ const maxAttempts = requiredInteger(row.max_attempts, 'max_attempts', index, blockers, 1);
49
+ const dependencies = requiredStringArray(row.dependencies, 'dependencies', index, blockers);
50
+ const leaseRequirements = requiredArray(row.lease_requirements, 'lease_requirements', index, blockers);
51
+ const sourceAgentSessionId = typeof row.source_agent_session_id === 'string' && row.source_agent_session_id.trim()
52
+ ? row.source_agent_session_id.trim()
53
+ : originSessionId || undefined;
54
+ const serialized = JSON.stringify(row);
55
+ const recursion = scanAgentTextForRecursion(serialized);
56
+ if (!recursion.ok || MAIN_ROUTE_RECURSION_RE.test(serialized))
57
+ blockers.push(`follow_up_work_item_${index + 1}_main_route_recursion_blocked`);
58
+ if (GLOBAL_SCOUT_LEDGER_RE.test(serialized))
59
+ blockers.push(`follow_up_work_item_${index + 1}_global_scout_ledger_blocked`);
60
+ for (const lease of leaseRequirements) {
61
+ const path = leasePath(lease);
62
+ if (path && PROTECTED_WRITE_PATH_RE.test(path))
63
+ blockers.push(`follow_up_work_item_${index + 1}_protected_core_target:${path}`);
64
+ }
65
+ if (blockers.length)
66
+ return { item: null, blockers };
67
+ return {
68
+ item: {
69
+ id,
70
+ title,
71
+ description,
72
+ required_persona_category: requiredPersonaCategory,
73
+ priority,
74
+ dependencies,
75
+ lease_requirements: leaseRequirements,
76
+ max_attempts: maxAttempts,
77
+ reason,
78
+ ...(sourceAgentSessionId ? { source_agent_session_id: sourceAgentSessionId } : {})
79
+ },
80
+ blockers: []
81
+ };
82
+ }
83
+ function requiredString(value, field, index, blockers) {
84
+ const text = typeof value === 'string' ? value.trim() : '';
85
+ if (!text)
86
+ blockers.push(`follow_up_work_item_${index + 1}_missing_${field}`);
87
+ return text;
88
+ }
89
+ function requiredInteger(value, field, index, blockers, min) {
90
+ const parsed = Number(value);
91
+ if (!Number.isFinite(parsed) || Math.floor(parsed) !== parsed || parsed < min)
92
+ blockers.push(`follow_up_work_item_${index + 1}_invalid_${field}`);
93
+ return Math.max(min, Number.isFinite(parsed) ? Math.floor(parsed) : min);
94
+ }
95
+ function requiredArray(value, field, index, blockers) {
96
+ if (!Array.isArray(value)) {
97
+ blockers.push(`follow_up_work_item_${index + 1}_missing_${field}`);
98
+ return [];
99
+ }
100
+ return value;
101
+ }
102
+ function requiredStringArray(value, field, index, blockers) {
103
+ const rows = requiredArray(value, field, index, blockers);
104
+ const out = rows.map((entry) => String(entry || '')).filter(Boolean);
105
+ if (out.length !== rows.length)
106
+ blockers.push(`follow_up_work_item_${index + 1}_invalid_${field}`);
107
+ return out;
108
+ }
109
+ function leasePath(lease) {
110
+ if (!lease || typeof lease !== 'object')
111
+ return '';
112
+ const row = lease;
113
+ return String(row.path || row.file || row.target_path || '').replace(/\\/g, '/').replace(/^\.?\//, '');
114
+ }
115
+ //# sourceMappingURL=agent-follow-up-work-items.js.map
@@ -8,6 +8,9 @@ export interface AgentJanitorReport {
8
8
  zombie_process_sessions: string[];
9
9
  stale_tmux_sessions: string[];
10
10
  active_generation_sessions: string[];
11
+ active_generation_count: number;
12
+ cleaned_generation_count: number;
13
+ skipped_active_generations: string[];
11
14
  orphan_generation_dirs: string[];
12
15
  slot_generation_cleanup: string[];
13
16
  orphan_temp_dirs: string[];
@@ -34,7 +34,10 @@ export async function runAgentJanitor(input) {
34
34
  statusBySession.set(String(row.session_id), status);
35
35
  }
36
36
  const zombieProcesses = await detectZombieProcessSessions(agentRoot, statusByAgent, statusBySession);
37
- const staleTmuxSessions = await detectStaleTmuxSessions(agentRoot, staleMs);
37
+ const rawStaleTmuxSessions = await detectStaleTmuxSessions(agentRoot, staleMs);
38
+ const activeGenerationSet = new Set(activeGenerationSessions);
39
+ const staleTmuxSessions = rawStaleTmuxSessions.filter((id) => !activeGenerationSet.has(id));
40
+ const skippedActiveGenerations = rawStaleTmuxSessions.filter((id) => activeGenerationSet.has(id));
38
41
  const orphanGenerationDirs = await detectOrphanGenerationDirs(agentRoot, new Set(generationRows.map((row) => String(row.artifact_dir || ''))));
39
42
  const orphanTempDirs = await scopedExistingPaths(Array.isArray(namespace?.orphan_temp_dirs) ? namespace.orphan_temp_dirs : [], projectHash);
40
43
  const staleLocks = await scopedStaleLockPaths(namespace?.lock_dir ? [namespace.lock_dir] : [], projectHash, staleMs);
@@ -65,6 +68,9 @@ export async function runAgentJanitor(input) {
65
68
  zombie_process_sessions: zombieProcesses,
66
69
  stale_tmux_sessions: staleTmuxSessions,
67
70
  active_generation_sessions: activeGenerationSessions,
71
+ active_generation_count: activeGenerationSessions.length,
72
+ cleaned_generation_count: cleaned.filter((entry) => entry.includes(`${path.sep}sessions${path.sep}`)).length,
73
+ skipped_active_generations: skippedActiveGenerations,
68
74
  orphan_generation_dirs: orphanGenerationDirs,
69
75
  slot_generation_cleanup: cleaned.filter((entry) => entry.includes(`${path.sep}sessions${path.sep}`)),
70
76
  orphan_temp_dirs: orphanTempDirs,
@@ -55,6 +55,12 @@ export declare function runNativeAgentOrchestrator(opts?: AgentRunOptions): Prom
55
55
  lease_count: number;
56
56
  blockers: string[];
57
57
  };
58
+ task_graph: {
59
+ target_active_slots: number;
60
+ total_work_items: number;
61
+ generated_from_route: string;
62
+ work_items_exceed_active_slots: boolean;
63
+ };
58
64
  scheduler: {
59
65
  schema: string;
60
66
  ok: boolean;
@@ -168,12 +174,24 @@ export declare function runNativeAgentOrchestrator(opts?: AgentRunOptions): Prom
168
174
  terminal_sessions_closed: any;
169
175
  terminal_close_report: string;
170
176
  target_active_slots: any;
177
+ total_work_items: any;
178
+ pending_count: any;
179
+ active_slot_count: any;
180
+ completed_count: any;
171
181
  max_observed_active_slots: any;
172
182
  backfill_count: any;
183
+ expected_backfill_count: any;
173
184
  pending_queue_drained: any;
174
185
  generation_count: any;
175
186
  tmux_attach_command: string | null;
176
187
  tmux_lane_manifest: string;
188
+ tmux_lane_persistence: {
189
+ supervisor: string;
190
+ no_flicker_verified: boolean;
191
+ pane_survival_checked: boolean;
192
+ unexpected_close_count: number;
193
+ lane_count: number;
194
+ };
177
195
  output_schema_ok: boolean;
178
196
  output_tail_report: string;
179
197
  output_tail_records: number;
@@ -188,7 +206,7 @@ export declare function runNativeAgentOrchestrator(opts?: AgentRunOptions): Prom
188
206
  generated_at: string;
189
207
  records: {
190
208
  schema: string;
191
- kind: "xai_available_not_used" | "context7_missing" | "codex_web_search_missing" | "recursion_attempt" | "lease_conflict" | "session_not_closed" | "terminal_missing" | "terminal_not_closed" | "scheduler_starvation" | "session_generation_missing" | "schema_invalid_output" | "stale_heartbeat" | "legacy_multiagent_runtime_usage_attempt";
209
+ kind: "xai_available_not_used" | "context7_missing" | "codex_web_search_missing" | "recursion_attempt" | "lease_conflict" | "session_not_closed" | "terminal_missing" | "terminal_not_closed" | "scheduler_starvation" | "tmux_lane_flicker" | "missing_follow_up_schema" | "session_generation_missing" | "schema_invalid_output" | "stale_heartbeat" | "legacy_multiagent_runtime_usage_attempt";
192
210
  blocker: string;
193
211
  created_at: string;
194
212
  status: string;
@@ -229,6 +247,11 @@ export declare function runNativeAgentOrchestrator(opts?: AgentRunOptions): Prom
229
247
  goal_mode_generation_refs_ok: boolean;
230
248
  tmux_lane_manifest: string;
231
249
  tmux_lane_manifest_ok: boolean;
250
+ tmux_lane_supervisor: string;
251
+ tmux_lane_no_flicker_verified: boolean;
252
+ tmux_lane_survival_checked: boolean;
253
+ tmux_lane_unexpected_close_count: number;
254
+ tmux_lane_auto_reopen_count: number;
232
255
  tmux_pane_launch_ledger: string;
233
256
  tmux_pane_launch_count: number;
234
257
  ledger_hash_chain_ok: boolean;