sneakoscope 1.18.8 → 1.18.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 +6 -2
- 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/build-manifest.json +11 -9
- package/dist/commands/image-ux-review.d.ts +64 -0
- package/dist/commands/ppt.d.ts +64 -0
- package/dist/core/agents/agent-codex-cockpit.d.ts +7 -0
- package/dist/core/agents/agent-codex-cockpit.js +33 -0
- package/dist/core/agents/agent-command-surface.js +1 -1
- package/dist/core/agents/agent-merge-coordinator.d.ts +62 -1
- package/dist/core/agents/agent-merge-coordinator.js +130 -19
- package/dist/core/agents/agent-orchestrator.d.ts +64 -0
- package/dist/core/agents/agent-orchestrator.js +166 -1
- package/dist/core/agents/agent-output-validator.d.ts +143 -0
- package/dist/core/agents/agent-output-validator.js +58 -0
- package/dist/core/agents/agent-patch-apply-worker.d.ts +44 -0
- package/dist/core/agents/agent-patch-apply-worker.js +120 -52
- package/dist/core/agents/agent-patch-proof.d.ts +13 -0
- package/dist/core/agents/agent-patch-proof.js +44 -1
- package/dist/core/agents/agent-patch-queue-store.d.ts +23 -0
- package/dist/core/agents/agent-patch-queue-store.js +66 -0
- package/dist/core/agents/agent-patch-queue.d.ts +48 -16
- package/dist/core/agents/agent-patch-queue.js +28 -7
- package/dist/core/agents/agent-patch-schema.d.ts +21 -1
- package/dist/core/agents/agent-patch-schema.js +47 -2
- package/dist/core/agents/agent-proof-evidence.d.ts +22 -0
- package/dist/core/agents/agent-proof-evidence.js +77 -1
- package/dist/core/agents/agent-runner-codex-exec.d.ts +4 -0
- package/dist/core/agents/agent-runner-fake.d.ts +1 -0
- package/dist/core/agents/agent-runner-fake.js +42 -0
- package/dist/core/agents/agent-runner-process.js +3 -0
- package/dist/core/agents/agent-runner-tmux.js +3 -0
- package/dist/core/agents/agent-schema.d.ts +18 -0
- package/dist/core/agents/agent-task-graph.d.ts +13 -11
- package/dist/core/agents/agent-task-graph.js +12 -2
- package/dist/core/agents/agent-work-partition.d.ts +22 -1
- package/dist/core/agents/agent-work-partition.js +1 -1
- package/dist/core/agents/agent-worker-pipeline.d.ts +7 -0
- package/dist/core/agents/agent-worker-pipeline.js +46 -1
- package/dist/core/agents/route-collaboration-ledger.d.ts +64 -0
- package/dist/core/agents/work-partition/lease-planner.d.ts +21 -1
- package/dist/core/agents/work-partition/lease-planner.js +26 -3
- package/dist/core/codex/appshots-detector.d.ts +35 -0
- package/dist/core/codex/appshots-detector.js +55 -5
- package/dist/core/commands/agent-command.js +26 -2
- package/dist/core/commands/image-ux-review-command.d.ts +64 -0
- package/dist/core/commands/ppt-command.d.ts +64 -0
- package/dist/core/fsx.d.ts +1 -1
- package/dist/core/fsx.js +1 -1
- package/dist/core/mcp/mcp-0-134-policy.d.ts +32 -0
- package/dist/core/mcp/mcp-0-134-policy.js +63 -0
- package/dist/core/source-intelligence/appshots-evidence.d.ts +11 -1
- package/dist/core/source-intelligence/appshots-evidence.js +19 -2
- package/dist/core/source-intelligence/source-intelligence-runner.d.ts +14 -0
- package/dist/core/source-intelligence/source-intelligence-runner.js +1 -0
- package/dist/core/strategy/adhd-orchestrating-gate.js +1 -1
- package/dist/core/strategy/strategy-compiler.d.ts +9 -0
- package/dist/core/strategy/strategy-compiler.js +29 -3
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/scripts/release-parallel-check.js +14 -1
- package/package.json +18 -3
- package/schemas/codex/agent-result.schema.json +64 -0
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
|
|
|
16
16
|
|
|
17
17
|
## Current Release
|
|
18
18
|
|
|
19
|
-
SKS **1.18.
|
|
19
|
+
SKS **1.18.9** closes the Patch Swarm runtime surface: Appshots evidence now records Codex thread attachment provenance without claiming CLI-created screenshots, MCP `readOnlyHint` gates require runtime overlap/serialization proof, Codex 0.134 runner truth covers profile, proxy, history, and process reports, and release gates expose these checks alongside the patch queue/apply/proof work.
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
sks mad-sks plan --target-root <path> --json
|
|
@@ -44,8 +44,10 @@ npm run strategy:adhd-orchestrating-gate
|
|
|
44
44
|
npm run strategy:parallel-modification-plan
|
|
45
45
|
npm run appshots:evidence
|
|
46
46
|
npm run appshots:source-intelligence
|
|
47
|
+
npm run appshots:thread-attachment-discovery
|
|
47
48
|
npm run mcp:0.134-modernization
|
|
48
|
-
npm run mcp:readonly-
|
|
49
|
+
npm run mcp:readonly-runtime-scheduler
|
|
50
|
+
npm run codex:0.134-runner-truth
|
|
49
51
|
npm run source-intelligence:codex-history-search
|
|
50
52
|
npm run agent:parallel-write-kernel
|
|
51
53
|
npm run release:gate-existence-audit
|
|
@@ -111,6 +113,8 @@ The cleanup contract is policy-backed in `.sneakoscope/policy.json`, but the def
|
|
|
111
113
|
- ADHD orchestration gate: [docs/adhd-orchestrating-gate.md](docs/adhd-orchestrating-gate.md)
|
|
112
114
|
- Strategy-first parallel write: [docs/strategy-first-parallel-write.md](docs/strategy-first-parallel-write.md)
|
|
113
115
|
- Appshots pipeline: [docs/appshots-pipeline.md](docs/appshots-pipeline.md)
|
|
116
|
+
- Appshots thread attachments: [docs/appshots-thread-attachments.md](docs/appshots-thread-attachments.md)
|
|
117
|
+
- MCP readOnly scheduler: [docs/mcp-readonly-scheduler.md](docs/mcp-readonly-scheduler.md)
|
|
114
118
|
- Parallel write agents: [docs/parallel-write-agents.md](docs/parallel-write-agents.md)
|
|
115
119
|
- Agent patch queue: [docs/agent-patch-queue.md](docs/agent-patch-queue.md)
|
|
116
120
|
- Migration 1.18.7 to 1.18.8: [docs/migration-1.18.7-to-1.18.8.md](docs/migration-1.18.7-to-1.18.8.md)
|
|
@@ -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.
|
|
7
|
+
Some("--version") => println!("sks-rs 1.18.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": "1.18.
|
|
5
|
-
"source_digest": "
|
|
6
|
-
"source_file_count":
|
|
7
|
-
"built_at_source_time":
|
|
4
|
+
"package_version": "1.18.9",
|
|
5
|
+
"source_digest": "6eee8ecc34d3c7ce9e86cabc59e92764287b996a5387f26f12ec3253fee6869e",
|
|
6
|
+
"source_file_count": 1537,
|
|
7
|
+
"built_at_source_time": 1779893098646
|
|
8
8
|
}
|
package/dist/bin/sks.js
CHANGED
package/dist/build-manifest.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "sks.dist-build.v2",
|
|
3
|
-
"version": "1.18.
|
|
4
|
-
"package_version": "1.18.
|
|
3
|
+
"version": "1.18.9",
|
|
4
|
+
"package_version": "1.18.9",
|
|
5
5
|
"typescript": true,
|
|
6
6
|
"mjs_runtime_files": 0,
|
|
7
|
-
"compiled_file_count":
|
|
8
|
-
"compiled_js_count":
|
|
9
|
-
"compiled_dts_count":
|
|
10
|
-
"source_digest": "
|
|
11
|
-
"source_file_count":
|
|
12
|
-
"source_files_hash": "
|
|
13
|
-
"source_list_hash": "
|
|
7
|
+
"compiled_file_count": 910,
|
|
8
|
+
"compiled_js_count": 455,
|
|
9
|
+
"compiled_dts_count": 455,
|
|
10
|
+
"source_digest": "6eee8ecc34d3c7ce9e86cabc59e92764287b996a5387f26f12ec3253fee6869e",
|
|
11
|
+
"source_file_count": 1537,
|
|
12
|
+
"source_files_hash": "3475322f249a9a6a5286d536a5e69dfe6f2b06ad2d64a1b0bd9c408b19257f10",
|
|
13
|
+
"source_list_hash": "3475322f249a9a6a5286d536a5e69dfe6f2b06ad2d64a1b0bd9c408b19257f10",
|
|
14
14
|
"src_mjs_runtime_files": 0,
|
|
15
15
|
"dist_stamp_schema": "sks.dist-build-stamp.v1",
|
|
16
16
|
"files": [
|
|
@@ -226,6 +226,8 @@
|
|
|
226
226
|
"core/agents/agent-patch-apply-worker.js",
|
|
227
227
|
"core/agents/agent-patch-proof.d.ts",
|
|
228
228
|
"core/agents/agent-patch-proof.js",
|
|
229
|
+
"core/agents/agent-patch-queue-store.d.ts",
|
|
230
|
+
"core/agents/agent-patch-queue-store.js",
|
|
229
231
|
"core/agents/agent-patch-queue.d.ts",
|
|
230
232
|
"core/agents/agent-patch-queue.js",
|
|
231
233
|
"core/agents/agent-patch-schema.d.ts",
|
|
@@ -511,6 +511,7 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
511
511
|
status: string;
|
|
512
512
|
blockers: string[];
|
|
513
513
|
};
|
|
514
|
+
patch_swarm?: never;
|
|
514
515
|
} | {
|
|
515
516
|
schema: string;
|
|
516
517
|
ok: boolean;
|
|
@@ -781,6 +782,48 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
781
782
|
appshots_operator_action_required: boolean;
|
|
782
783
|
};
|
|
783
784
|
};
|
|
785
|
+
patch_swarm: {
|
|
786
|
+
schema: string;
|
|
787
|
+
generated_at: string;
|
|
788
|
+
ok: boolean;
|
|
789
|
+
mission_id: string;
|
|
790
|
+
route: string;
|
|
791
|
+
route_command: string;
|
|
792
|
+
write_capable: boolean;
|
|
793
|
+
dry_run: boolean;
|
|
794
|
+
patch_envelope_count: number;
|
|
795
|
+
apply_started_at: string;
|
|
796
|
+
apply_finished_at: string;
|
|
797
|
+
apply_latency_ms: number;
|
|
798
|
+
parallel_apply_count: number;
|
|
799
|
+
parallel_apply_groups: {
|
|
800
|
+
group_id: string;
|
|
801
|
+
entry_ids: string[];
|
|
802
|
+
agents: string[];
|
|
803
|
+
expected_speedup: number;
|
|
804
|
+
}[];
|
|
805
|
+
serial_merge_groups: {
|
|
806
|
+
group_id: string;
|
|
807
|
+
entry_ids: string[];
|
|
808
|
+
agents: string[];
|
|
809
|
+
reason: string;
|
|
810
|
+
file: string;
|
|
811
|
+
}[];
|
|
812
|
+
wall_clock_parallel_evidence: string[];
|
|
813
|
+
expected_speedup: number;
|
|
814
|
+
conflicted_agent_count: number;
|
|
815
|
+
artifacts: {
|
|
816
|
+
queue: string;
|
|
817
|
+
events: string;
|
|
818
|
+
ownership: string;
|
|
819
|
+
merge: string;
|
|
820
|
+
apply_results: string;
|
|
821
|
+
verification: string;
|
|
822
|
+
rollback: string;
|
|
823
|
+
proof: string;
|
|
824
|
+
};
|
|
825
|
+
blockers: string[];
|
|
826
|
+
};
|
|
784
827
|
proof: {
|
|
785
828
|
schema: string;
|
|
786
829
|
ok: boolean;
|
|
@@ -801,6 +844,27 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
801
844
|
parallel_write_apply_patches: boolean;
|
|
802
845
|
parallel_write_dry_run_patches: boolean;
|
|
803
846
|
parallel_write_max_write_agents: number;
|
|
847
|
+
patch_swarm_runtime: string | null;
|
|
848
|
+
patch_queue: string | null;
|
|
849
|
+
patch_queue_events: string | null;
|
|
850
|
+
patch_queue_event_count: number;
|
|
851
|
+
patch_proof: string | null;
|
|
852
|
+
patch_queue_ok: boolean;
|
|
853
|
+
patch_apply_ok: any;
|
|
854
|
+
patch_verification_ok: any;
|
|
855
|
+
patch_rollback_ok: any;
|
|
856
|
+
parallel_patch_apply_verified: boolean;
|
|
857
|
+
patch_conflict_count: number;
|
|
858
|
+
serial_bottleneck_count: number;
|
|
859
|
+
changed_files_by_agent: Record<string, string[]>;
|
|
860
|
+
lease_compliance_by_patch: {
|
|
861
|
+
patch_entry_id: any;
|
|
862
|
+
agent_id: any;
|
|
863
|
+
lease_id: any;
|
|
864
|
+
ok: boolean;
|
|
865
|
+
write_paths: any;
|
|
866
|
+
}[];
|
|
867
|
+
rollback_digest_count: any;
|
|
804
868
|
real_parallel_claim: boolean;
|
|
805
869
|
fake_backend_disclaimer: string | null;
|
|
806
870
|
agent_count: any;
|
package/dist/commands/ppt.d.ts
CHANGED
|
@@ -360,6 +360,7 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
360
360
|
status: string;
|
|
361
361
|
blockers: string[];
|
|
362
362
|
};
|
|
363
|
+
patch_swarm?: never;
|
|
363
364
|
} | {
|
|
364
365
|
schema: string;
|
|
365
366
|
ok: boolean;
|
|
@@ -630,6 +631,48 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
630
631
|
appshots_operator_action_required: boolean;
|
|
631
632
|
};
|
|
632
633
|
};
|
|
634
|
+
patch_swarm: {
|
|
635
|
+
schema: string;
|
|
636
|
+
generated_at: string;
|
|
637
|
+
ok: boolean;
|
|
638
|
+
mission_id: string;
|
|
639
|
+
route: string;
|
|
640
|
+
route_command: string;
|
|
641
|
+
write_capable: boolean;
|
|
642
|
+
dry_run: boolean;
|
|
643
|
+
patch_envelope_count: number;
|
|
644
|
+
apply_started_at: string;
|
|
645
|
+
apply_finished_at: string;
|
|
646
|
+
apply_latency_ms: number;
|
|
647
|
+
parallel_apply_count: number;
|
|
648
|
+
parallel_apply_groups: {
|
|
649
|
+
group_id: string;
|
|
650
|
+
entry_ids: string[];
|
|
651
|
+
agents: string[];
|
|
652
|
+
expected_speedup: number;
|
|
653
|
+
}[];
|
|
654
|
+
serial_merge_groups: {
|
|
655
|
+
group_id: string;
|
|
656
|
+
entry_ids: string[];
|
|
657
|
+
agents: string[];
|
|
658
|
+
reason: string;
|
|
659
|
+
file: string;
|
|
660
|
+
}[];
|
|
661
|
+
wall_clock_parallel_evidence: string[];
|
|
662
|
+
expected_speedup: number;
|
|
663
|
+
conflicted_agent_count: number;
|
|
664
|
+
artifacts: {
|
|
665
|
+
queue: string;
|
|
666
|
+
events: string;
|
|
667
|
+
ownership: string;
|
|
668
|
+
merge: string;
|
|
669
|
+
apply_results: string;
|
|
670
|
+
verification: string;
|
|
671
|
+
rollback: string;
|
|
672
|
+
proof: string;
|
|
673
|
+
};
|
|
674
|
+
blockers: string[];
|
|
675
|
+
};
|
|
633
676
|
proof: {
|
|
634
677
|
schema: string;
|
|
635
678
|
ok: boolean;
|
|
@@ -650,6 +693,27 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
650
693
|
parallel_write_apply_patches: boolean;
|
|
651
694
|
parallel_write_dry_run_patches: boolean;
|
|
652
695
|
parallel_write_max_write_agents: number;
|
|
696
|
+
patch_swarm_runtime: string | null;
|
|
697
|
+
patch_queue: string | null;
|
|
698
|
+
patch_queue_events: string | null;
|
|
699
|
+
patch_queue_event_count: number;
|
|
700
|
+
patch_proof: string | null;
|
|
701
|
+
patch_queue_ok: boolean;
|
|
702
|
+
patch_apply_ok: any;
|
|
703
|
+
patch_verification_ok: any;
|
|
704
|
+
patch_rollback_ok: any;
|
|
705
|
+
parallel_patch_apply_verified: boolean;
|
|
706
|
+
patch_conflict_count: number;
|
|
707
|
+
serial_bottleneck_count: number;
|
|
708
|
+
changed_files_by_agent: Record<string, string[]>;
|
|
709
|
+
lease_compliance_by_patch: {
|
|
710
|
+
patch_entry_id: any;
|
|
711
|
+
agent_id: any;
|
|
712
|
+
lease_id: any;
|
|
713
|
+
ok: boolean;
|
|
714
|
+
write_paths: any;
|
|
715
|
+
}[];
|
|
716
|
+
rollback_digest_count: any;
|
|
653
717
|
real_parallel_claim: boolean;
|
|
654
718
|
fake_backend_disclaimer: string | null;
|
|
655
719
|
agent_count: any;
|
|
@@ -43,6 +43,13 @@ export interface AgentCodexCockpitState {
|
|
|
43
43
|
pending_queue_count: number | null;
|
|
44
44
|
backfill_count: number | null;
|
|
45
45
|
scheduler_status: string | null;
|
|
46
|
+
patch_swarm_phase: string | null;
|
|
47
|
+
patch_queue_depth: number | null;
|
|
48
|
+
patch_apply_groups: Array<Record<string, unknown>>;
|
|
49
|
+
patch_changed_files_by_agent: Record<string, unknown>;
|
|
50
|
+
patch_verification_status: Array<Record<string, unknown>>;
|
|
51
|
+
patch_rollback_status: Array<Record<string, unknown>>;
|
|
52
|
+
patch_micro_win_links: Array<Record<string, unknown>>;
|
|
46
53
|
worker_slots: Array<Record<string, unknown>>;
|
|
47
54
|
session_generations: Array<Record<string, unknown>>;
|
|
48
55
|
blockers: string[];
|
|
@@ -40,6 +40,12 @@ export async function buildAgentCodexCockpitState(missionDir, opts = {}) {
|
|
|
40
40
|
const scheduler = await readJson(path.join(root, 'agent-scheduler-state.json'), null);
|
|
41
41
|
const workerSlots = await readJson(path.join(root, 'agent-worker-slots.json'), null);
|
|
42
42
|
const generations = await readJson(path.join(root, 'agent-session-generations.json'), null);
|
|
43
|
+
const patchSwarm = await readJson(path.join(root, 'agent-patch-swarm-runtime.json'), null);
|
|
44
|
+
const patchQueue = await readJson(path.join(root, 'agent-patch-queue.json'), null);
|
|
45
|
+
const patchMerge = await readJson(path.join(root, 'agent-merge-coordinator-report.json'), null);
|
|
46
|
+
const patchVerification = await readJson(path.join(root, 'agent-patch-verification-results.json'), null);
|
|
47
|
+
const patchRollback = await readJson(path.join(root, 'agent-patch-rollback-proof.json'), null);
|
|
48
|
+
const patchProof = await readJson(path.join(root, 'agent-patch-proof.json'), null);
|
|
43
49
|
const terminalClosed = proof?.terminal_sessions_closed === true;
|
|
44
50
|
const eventsTail = await readTailLines(path.join(root, 'agent-events.jsonl'), 8);
|
|
45
51
|
const cockpitEventsTail = await readTailLines(path.join(root, AGENT_CODEX_COCKPIT_EVENTS), 8);
|
|
@@ -76,6 +82,13 @@ export async function buildAgentCodexCockpitState(missionDir, opts = {}) {
|
|
|
76
82
|
pending_queue_count: scheduler?.pending_count ?? null,
|
|
77
83
|
backfill_count: scheduler?.backfill_count ?? null,
|
|
78
84
|
scheduler_status: scheduler?.status || null,
|
|
85
|
+
patch_swarm_phase: patchSwarm ? (patchSwarm.ok === true ? 'passed' : 'blocked') : null,
|
|
86
|
+
patch_queue_depth: patchQueue?.queued_count ?? null,
|
|
87
|
+
patch_apply_groups: Array.isArray(patchMerge?.parallel_apply_groups) ? patchMerge.parallel_apply_groups : [],
|
|
88
|
+
patch_changed_files_by_agent: patchProof?.changed_files_by_agent || {},
|
|
89
|
+
patch_verification_status: Array.isArray(patchVerification?.results) ? patchVerification.results : [],
|
|
90
|
+
patch_rollback_status: Array.isArray(patchRollback?.entries) ? patchRollback.entries : [],
|
|
91
|
+
patch_micro_win_links: buildPatchMicroWinLinks(patchQueue),
|
|
79
92
|
worker_slots: Array.isArray(workerSlots?.slots) ? workerSlots.slots : [],
|
|
80
93
|
session_generations: generations?.generations ? Object.values(generations.generations) : [],
|
|
81
94
|
blockers,
|
|
@@ -109,6 +122,9 @@ export function renderAgentCodexDashboard(state) {
|
|
|
109
122
|
`- tmux attach: ${state.tmux_attach_command || 'unknown'}`,
|
|
110
123
|
`- All sessions closed: ${state.all_sessions_closed ?? 'unknown'}`,
|
|
111
124
|
`- Scheduler: ${state.scheduler_status || 'unknown'}`,
|
|
125
|
+
`- Patch swarm: ${state.patch_swarm_phase || 'unknown'}`,
|
|
126
|
+
`- Patch queue depth: ${state.patch_queue_depth ?? 'unknown'}`,
|
|
127
|
+
`- Patch apply groups: ${state.patch_apply_groups.length}`,
|
|
112
128
|
`- Target active slots: ${state.target_active_slots ?? 'unknown'}`,
|
|
113
129
|
`- Active slots: ${state.active_slot_count ?? 'unknown'}`,
|
|
114
130
|
`- Pending queue: ${state.pending_queue_count ?? 'unknown'}`,
|
|
@@ -168,6 +184,13 @@ function summarizeLiveState(state) {
|
|
|
168
184
|
pending_queue_count: state.pending_queue_count,
|
|
169
185
|
backfill_count: state.backfill_count,
|
|
170
186
|
scheduler_status: state.scheduler_status,
|
|
187
|
+
patch_swarm_phase: state.patch_swarm_phase,
|
|
188
|
+
patch_queue_depth: state.patch_queue_depth,
|
|
189
|
+
patch_apply_groups: state.patch_apply_groups,
|
|
190
|
+
patch_changed_files_by_agent: state.patch_changed_files_by_agent,
|
|
191
|
+
patch_verification_status: state.patch_verification_status,
|
|
192
|
+
patch_rollback_status: state.patch_rollback_status,
|
|
193
|
+
patch_micro_win_links: state.patch_micro_win_links,
|
|
171
194
|
worker_slot_count: state.worker_slots.length,
|
|
172
195
|
session_generation_count: state.session_generations.length,
|
|
173
196
|
proof_status: state.proof_status,
|
|
@@ -180,6 +203,16 @@ function summarizeLiveState(state) {
|
|
|
180
203
|
blockers: state.blockers,
|
|
181
204
|
};
|
|
182
205
|
}
|
|
206
|
+
function buildPatchMicroWinLinks(patchQueue) {
|
|
207
|
+
const entries = Array.isArray(patchQueue?.entries) ? patchQueue.entries : [];
|
|
208
|
+
return entries.map((entry) => ({
|
|
209
|
+
patch_entry_id: entry.id,
|
|
210
|
+
agent_id: entry.agent_id,
|
|
211
|
+
micro_win_id: entry.envelope?.lease_proof?.micro_win_id || null,
|
|
212
|
+
strategy_task_id: entry.envelope?.lease_proof?.strategy_task_id || null,
|
|
213
|
+
write_paths: entry.write_paths || []
|
|
214
|
+
}));
|
|
215
|
+
}
|
|
183
216
|
function mergeAgentRows(sessions, roster, leases, events) {
|
|
184
217
|
const byId = new Map();
|
|
185
218
|
for (const row of roster)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_AGENT_COUNT } from './agent-schema.js';
|
|
2
2
|
export function parseAgentCommandArgs(command, args = []) {
|
|
3
3
|
const first = args[0] && !String(args[0]).startsWith('--') ? String(args[0]) : '';
|
|
4
|
-
const actions = new Set(['run', 'status', 'plan', 'spawn', 'watch', 'dashboard', 'cockpit', 'lane', 'board', 'ledger', 'collect', 'consensus', 'close', 'cleanup', 'proof', 'explain']);
|
|
4
|
+
const actions = new Set(['run', 'status', 'plan', 'spawn', 'watch', 'dashboard', 'cockpit', 'lane', 'board', 'ledger', 'collect', 'consensus', 'close', 'cleanup', 'proof', 'explain', 'rollback-patches']);
|
|
5
5
|
const action = actions.has(first) ? first : 'run';
|
|
6
6
|
const rest = action === first ? args.slice(1) : args;
|
|
7
7
|
const json = hasFlag(args, '--json');
|
|
@@ -1,23 +1,84 @@
|
|
|
1
1
|
import type { AgentPatchEnvelope } from './agent-patch-schema.js';
|
|
2
|
+
import type { AgentPatchQueueEntry } from './agent-patch-queue.js';
|
|
2
3
|
export declare const AGENT_MERGE_COORDINATOR_SCHEMA = "sks.agent-merge-coordinator.v1";
|
|
3
|
-
export
|
|
4
|
+
export type AgentPatchMergeInput = AgentPatchEnvelope | AgentPatchQueueEntry;
|
|
5
|
+
export interface AgentPatchMergeCoordinatorOptions {
|
|
6
|
+
artifactsDir?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function coordinateAgentPatchMerge(inputs: AgentPatchMergeInput[], opts?: AgentPatchMergeCoordinatorOptions): {
|
|
4
9
|
schema: string;
|
|
5
10
|
ok: boolean;
|
|
6
11
|
merge_order: string[];
|
|
12
|
+
apply_order: string[];
|
|
7
13
|
touched_files: string[];
|
|
8
14
|
conflicts: {
|
|
15
|
+
type: string;
|
|
9
16
|
file: string;
|
|
17
|
+
entries: string[];
|
|
10
18
|
agents: string[];
|
|
19
|
+
reason: string;
|
|
20
|
+
}[];
|
|
21
|
+
conflict_graph: {
|
|
22
|
+
nodes: {
|
|
23
|
+
entry_id: string;
|
|
24
|
+
agent_id: string;
|
|
25
|
+
lease_id: string | null;
|
|
26
|
+
}[];
|
|
27
|
+
edges: {
|
|
28
|
+
file: string;
|
|
29
|
+
entries: string[];
|
|
30
|
+
reason: string;
|
|
31
|
+
}[];
|
|
32
|
+
};
|
|
33
|
+
parallel_apply_groups: {
|
|
34
|
+
group_id: string;
|
|
35
|
+
entry_ids: string[];
|
|
36
|
+
agents: string[];
|
|
37
|
+
expected_speedup: number;
|
|
38
|
+
}[];
|
|
39
|
+
serial_merge_groups: {
|
|
40
|
+
group_id: string;
|
|
41
|
+
entry_ids: string[];
|
|
42
|
+
agents: string[];
|
|
43
|
+
reason: string;
|
|
44
|
+
file: string;
|
|
45
|
+
}[];
|
|
46
|
+
blocked_conflicts: {
|
|
47
|
+
type: string;
|
|
48
|
+
file: string;
|
|
49
|
+
entries: string[];
|
|
50
|
+
agents: string[];
|
|
51
|
+
reason: string;
|
|
11
52
|
}[];
|
|
12
53
|
parallel_batches: {
|
|
13
54
|
batch_id: string;
|
|
14
55
|
agents: string[];
|
|
15
56
|
}[];
|
|
16
57
|
serial_conflicts: {
|
|
58
|
+
type: string;
|
|
17
59
|
file: string;
|
|
60
|
+
entries: string[];
|
|
18
61
|
agents: string[];
|
|
62
|
+
reason: string;
|
|
19
63
|
}[];
|
|
64
|
+
apply_plan: {
|
|
65
|
+
parallel_apply_groups: {
|
|
66
|
+
group_id: string;
|
|
67
|
+
entry_ids: string[];
|
|
68
|
+
agents: string[];
|
|
69
|
+
expected_speedup: number;
|
|
70
|
+
}[];
|
|
71
|
+
serial_merge_groups: {
|
|
72
|
+
group_id: string;
|
|
73
|
+
entry_ids: string[];
|
|
74
|
+
agents: string[];
|
|
75
|
+
reason: string;
|
|
76
|
+
file: string;
|
|
77
|
+
}[];
|
|
78
|
+
retry_policy: string;
|
|
79
|
+
};
|
|
20
80
|
wall_clock_parallel_evidence: string[];
|
|
21
81
|
blockers: string[];
|
|
22
82
|
};
|
|
83
|
+
export declare function writeAgentMergeCoordinatorArtifacts(artifactDir: string, report: ReturnType<typeof coordinateAgentPatchMerge>): Promise<void>;
|
|
23
84
|
//# sourceMappingURL=agent-merge-coordinator.d.ts.map
|
|
@@ -1,46 +1,146 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { writeJsonAtomic } from '../fsx.js';
|
|
1
3
|
export const AGENT_MERGE_COORDINATOR_SCHEMA = 'sks.agent-merge-coordinator.v1';
|
|
2
|
-
export function coordinateAgentPatchMerge(
|
|
4
|
+
export function coordinateAgentPatchMerge(inputs, opts = {}) {
|
|
5
|
+
const items = normalizeInputs(inputs);
|
|
3
6
|
const writers = new Map();
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
const blockedConflicts = [];
|
|
8
|
+
for (const item of items) {
|
|
9
|
+
if (item.status && item.status !== 'pending') {
|
|
10
|
+
blockedConflicts.push({ type: 'status', file: '.', entries: [item.entry_id], agents: [item.agent_id], reason: `entry_not_pending:${item.status}` });
|
|
11
|
+
}
|
|
12
|
+
for (const operation of item.envelope.operations || []) {
|
|
6
13
|
const key = normalizePatchPath(operation.path || '');
|
|
7
14
|
if (!writers.has(key))
|
|
8
15
|
writers.set(key, []);
|
|
9
|
-
writers.get(key)?.push(
|
|
16
|
+
writers.get(key)?.push(item);
|
|
17
|
+
if (protectedPath(key)) {
|
|
18
|
+
blockedConflicts.push({ type: 'protected_path', file: key, entries: [item.entry_id], agents: [item.agent_id], reason: `protected_path:${key}` });
|
|
19
|
+
}
|
|
20
|
+
if (!pathAllowedByLease(key, item.envelope)) {
|
|
21
|
+
blockedConflicts.push({ type: 'lease', file: key, entries: [item.entry_id], agents: [item.agent_id], reason: `lease_path_not_allowed:${key}` });
|
|
22
|
+
}
|
|
10
23
|
}
|
|
11
24
|
}
|
|
25
|
+
for (const conflict of domainConflicts(items))
|
|
26
|
+
blockedConflicts.push(conflict);
|
|
12
27
|
const conflicts = mergeConflicts(writers);
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
28
|
+
const allBlockedConflicts = [...blockedConflicts, ...conflicts];
|
|
29
|
+
const serialConflictEntries = new Set(allBlockedConflicts.flatMap((conflict) => conflict.entries));
|
|
30
|
+
const parallelEntries = items.filter((item) => !serialConflictEntries.has(item.entry_id));
|
|
31
|
+
const parallelApplyGroups = parallelEntries.length ? [{
|
|
32
|
+
group_id: 'parallel-001',
|
|
33
|
+
entry_ids: parallelEntries.map((item) => item.entry_id),
|
|
34
|
+
agents: parallelEntries.map((item) => item.agent_id),
|
|
35
|
+
expected_speedup: parallelEntries.length
|
|
36
|
+
}] : [];
|
|
37
|
+
const serialMergeGroups = allBlockedConflicts.map((conflict, index) => ({
|
|
38
|
+
group_id: `serial-${String(index + 1).padStart(3, '0')}`,
|
|
39
|
+
entry_ids: conflict.entries,
|
|
40
|
+
agents: conflict.agents,
|
|
41
|
+
reason: conflict.reason,
|
|
42
|
+
file: conflict.file
|
|
43
|
+
}));
|
|
44
|
+
const result = {
|
|
16
45
|
schema: AGENT_MERGE_COORDINATOR_SCHEMA,
|
|
17
|
-
ok:
|
|
18
|
-
merge_order:
|
|
46
|
+
ok: allBlockedConflicts.length === 0,
|
|
47
|
+
merge_order: items.map((item) => item.agent_id),
|
|
48
|
+
apply_order: [...parallelApplyGroups.map((group) => group.group_id), ...serialMergeGroups.map((group) => group.group_id)],
|
|
19
49
|
touched_files: [...writers.keys()].sort(),
|
|
20
|
-
conflicts,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
50
|
+
conflicts: allBlockedConflicts,
|
|
51
|
+
conflict_graph: {
|
|
52
|
+
nodes: items.map((item) => ({ entry_id: item.entry_id, agent_id: item.agent_id, lease_id: item.lease_id })),
|
|
53
|
+
edges: allBlockedConflicts.map((conflict) => ({ file: conflict.file, entries: conflict.entries, reason: conflict.reason }))
|
|
54
|
+
},
|
|
55
|
+
parallel_apply_groups: parallelApplyGroups,
|
|
56
|
+
serial_merge_groups: serialMergeGroups,
|
|
57
|
+
blocked_conflicts: allBlockedConflicts,
|
|
58
|
+
parallel_batches: parallelApplyGroups.map((group) => ({ batch_id: group.group_id, agents: group.agents })),
|
|
59
|
+
serial_conflicts: allBlockedConflicts,
|
|
60
|
+
apply_plan: {
|
|
61
|
+
parallel_apply_groups: parallelApplyGroups,
|
|
62
|
+
serial_merge_groups: serialMergeGroups,
|
|
63
|
+
retry_policy: 'rebase_stale_context_then_requeue'
|
|
64
|
+
},
|
|
65
|
+
wall_clock_parallel_evidence: parallelApplyGroups.length ? [`parallel-001:${parallelEntries.length}_entries_can_apply_without_overlapping_paths`] : [],
|
|
66
|
+
blockers: allBlockedConflicts.map((conflict) => conflict.reason)
|
|
25
67
|
};
|
|
68
|
+
if (opts.artifactsDir)
|
|
69
|
+
void writeAgentMergeCoordinatorArtifacts(opts.artifactsDir, result);
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
export async function writeAgentMergeCoordinatorArtifacts(artifactDir, report) {
|
|
73
|
+
await writeJsonAtomic(path.join(artifactDir, 'agent-merge-coordinator-report.json'), report);
|
|
74
|
+
await writeJsonAtomic(path.join(artifactDir, 'agent-patch-conflict-graph.json'), report.conflict_graph);
|
|
75
|
+
await writeJsonAtomic(path.join(artifactDir, 'agent-patch-apply-plan.json'), report.apply_plan);
|
|
76
|
+
await writeJsonAtomic(path.join(artifactDir, 'agent-patch-apply-order.json'), {
|
|
77
|
+
schema: 'sks.agent-patch-apply-order.v1',
|
|
78
|
+
order: report.apply_order
|
|
79
|
+
});
|
|
26
80
|
}
|
|
27
81
|
function mergeConflicts(writers) {
|
|
28
82
|
const rows = [...writers.entries()].sort(([left], [right]) => left.localeCompare(right));
|
|
29
83
|
const conflicts = [];
|
|
30
84
|
for (let i = 0; i < rows.length; i += 1) {
|
|
31
|
-
const [leftFile,
|
|
85
|
+
const [leftFile, leftItems] = rows[i];
|
|
32
86
|
for (let j = i; j < rows.length; j += 1) {
|
|
33
|
-
const [rightFile,
|
|
87
|
+
const [rightFile, rightItems] = rows[j];
|
|
34
88
|
if (!pathsOverlap(leftFile, rightFile))
|
|
35
89
|
continue;
|
|
36
|
-
const
|
|
37
|
-
if (
|
|
90
|
+
const entries = [...new Set([...leftItems, ...rightItems].map((item) => item.entry_id))];
|
|
91
|
+
if (entries.length <= 1)
|
|
38
92
|
continue;
|
|
39
|
-
|
|
93
|
+
const agents = [...new Set([...leftItems, ...rightItems].map((item) => item.agent_id))];
|
|
94
|
+
const file = leftFile === rightFile ? leftFile : `${leftFile}<->${rightFile}`;
|
|
95
|
+
const reason = leftFile === rightFile ? `parallel_write_conflict:${file}` : `subtree_write_conflict:${file}`;
|
|
96
|
+
conflicts.push({ type: leftFile === rightFile ? 'path' : 'subtree', file, entries, agents, reason });
|
|
40
97
|
}
|
|
41
98
|
}
|
|
42
99
|
return conflicts;
|
|
43
100
|
}
|
|
101
|
+
function domainConflicts(items) {
|
|
102
|
+
const byPrediction = new Map();
|
|
103
|
+
for (const item of items) {
|
|
104
|
+
const prediction = item.envelope.lease_proof?.conflict_prediction_id;
|
|
105
|
+
if (!prediction)
|
|
106
|
+
continue;
|
|
107
|
+
const key = String(prediction);
|
|
108
|
+
if (!byPrediction.has(key))
|
|
109
|
+
byPrediction.set(key, []);
|
|
110
|
+
byPrediction.get(key)?.push(item);
|
|
111
|
+
}
|
|
112
|
+
return [...byPrediction.entries()].flatMap(([prediction, rows]) => {
|
|
113
|
+
const entries = [...new Set(rows.map((item) => item.entry_id))];
|
|
114
|
+
if (entries.length <= 1)
|
|
115
|
+
return [];
|
|
116
|
+
return [{
|
|
117
|
+
type: 'domain',
|
|
118
|
+
file: prediction,
|
|
119
|
+
entries,
|
|
120
|
+
agents: [...new Set(rows.map((item) => item.agent_id))],
|
|
121
|
+
reason: `domain_conflict:${prediction}`
|
|
122
|
+
}];
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function normalizeInputs(inputs) {
|
|
126
|
+
return inputs.map((input, index) => {
|
|
127
|
+
if ('envelope' in input) {
|
|
128
|
+
return {
|
|
129
|
+
entry_id: input.id,
|
|
130
|
+
agent_id: input.agent_id,
|
|
131
|
+
lease_id: input.lease_id || input.envelope.lease_id || input.envelope.lease_proof?.lease_id || null,
|
|
132
|
+
status: input.status,
|
|
133
|
+
envelope: input.envelope
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
entry_id: `${input.agent_id}-${String(index + 1).padStart(4, '0')}`,
|
|
138
|
+
agent_id: input.agent_id,
|
|
139
|
+
lease_id: input.lease_id || input.lease_proof?.lease_id || null,
|
|
140
|
+
envelope: input
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
}
|
|
44
144
|
function pathsOverlap(left, right) {
|
|
45
145
|
return left === right || left.startsWith(`${right}/`) || right.startsWith(`${left}/`);
|
|
46
146
|
}
|
|
@@ -49,4 +149,15 @@ function normalizePatchPath(value) {
|
|
|
49
149
|
const compact = normalized.split('/').filter((part) => part && part !== '.').join('/');
|
|
50
150
|
return compact || '.';
|
|
51
151
|
}
|
|
152
|
+
const PROTECTED_PATH_RE = /^(?:\.codex\/|\.agents\/skills\/|\.codex\/agents\/|AGENTS\.md$|node_modules\/sneakoscope\/|\.sneakoscope\/.*policy.*\.json$)/;
|
|
153
|
+
function protectedPath(value) {
|
|
154
|
+
return PROTECTED_PATH_RE.test(value);
|
|
155
|
+
}
|
|
156
|
+
function pathAllowedByLease(operationPath, envelope) {
|
|
157
|
+
const allowedPaths = envelope.lease_proof?.allowed_paths;
|
|
158
|
+
if (!allowedPaths?.length)
|
|
159
|
+
return true;
|
|
160
|
+
const rel = normalizePatchPath(operationPath);
|
|
161
|
+
return allowedPaths.map(normalizePatchPath).some((allowed) => rel === allowed || rel.startsWith(`${allowed}/`));
|
|
162
|
+
}
|
|
52
163
|
//# sourceMappingURL=agent-merge-coordinator.js.map
|