sneakoscope 2.0.11 → 2.0.13
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 +9 -3
- 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 +27 -8
- package/dist/core/agents/agent-orchestrator.js +279 -1
- package/dist/core/agents/agent-scheduler.js +12 -1
- package/dist/core/agents/agent-slot-pane-binding-proof.js +3 -3
- package/dist/core/agents/agent-work-queue.js +26 -2
- package/dist/core/agents/agent-worker-pipeline.js +2 -0
- package/dist/core/agents/native-cli-session-swarm.js +2 -2
- package/dist/core/codex-control/codex-sdk-adapter.js +10 -0
- package/dist/core/codex-control/codex-task-runner.js +4 -2
- package/dist/core/commands/naruto-command.js +104 -51
- package/dist/core/commands/research-command.js +43 -4
- package/dist/core/fsx.js +1 -1
- package/dist/core/git/git-worktree-merge-queue.js +34 -14
- package/dist/core/naruto/naruto-rebalance-policy.js +15 -3
- package/dist/core/naruto/naruto-work-graph.js +13 -0
- package/dist/core/research/claim-evidence-matrix.js +160 -0
- package/dist/core/research/experiment-plan.js +53 -0
- package/dist/core/research/falsification.js +18 -0
- package/dist/core/research/implementation-blueprint-markdown.js +31 -0
- package/dist/core/research/implementation-blueprint.js +66 -0
- package/dist/core/research/replication-pack.js +50 -0
- package/dist/core/research/research-cycle-runner.js +25 -0
- package/dist/core/research/research-final-reviewer.js +58 -0
- package/dist/core/research/research-handoff.js +51 -0
- package/dist/core/research/research-prompt-contract.js +24 -0
- package/dist/core/research/research-quality-contract.js +61 -0
- package/dist/core/research/research-report-quality.js +67 -0
- package/dist/core/research/research-stage-runner.js +16 -0
- package/dist/core/research/research-work-graph.js +75 -0
- package/dist/core/research/source-quality-report.js +94 -0
- package/dist/core/research.js +344 -44
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-slot-column-anchor.js +165 -4
- package/dist/core/zellij/zellij-slot-pane-renderer.js +259 -16
- package/dist/core/zellij/zellij-worker-pane-manager.js +13 -7
- package/dist/scripts/agent-real-codex-in-zellij-worker-pane-check.js +8 -2
- package/dist/scripts/agent-slot-pane-binding-proof-check.js +4 -4
- package/dist/scripts/codex-sdk-release-review-pipeline-check.js +2 -1
- package/dist/scripts/codex-sdk-research-pipeline-check.js +7 -0
- package/dist/scripts/codex-sdk-zellij-pane-binding-check.js +2 -2
- package/dist/scripts/git-worktree-cross-rebase-check.js +13 -1
- package/dist/scripts/git-worktree-merge-queue-check.js +1 -0
- package/dist/scripts/local-collab-worktree-gpt-final-apply-policy-check.js +63 -0
- package/dist/scripts/naruto-actual-worker-control-plane-check.js +30 -3
- package/dist/scripts/naruto-allocation-runtime-wiring-check.js +92 -0
- package/dist/scripts/naruto-orchestrator-runtime-source-check.js +65 -6
- package/dist/scripts/naruto-rebalance-policy-check.js +15 -2
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +1 -1
- package/dist/scripts/packlist-performance-check.js +1 -1
- package/dist/scripts/release-dag-full-coverage-check.js +4 -0
- package/dist/scripts/release-real-check.js +258 -77
- package/dist/scripts/research-quality-gate-check.js +86 -0
- package/dist/scripts/zellij-first-slot-down-stack-check.js +1 -1
- package/dist/scripts/zellij-first-slot-down-stack-real-check.js +344 -4
- package/dist/scripts/zellij-right-column-manager-check.js +1 -1
- package/dist/scripts/zellij-slot-column-anchor-check.js +45 -3
- package/dist/scripts/zellij-slot-only-ui-check.js +3 -1
- package/dist/scripts/zellij-slot-pane-renderer-check.js +73 -5
- package/dist/scripts/zellij-slot-renderer-proof-semantics-check.js +59 -0
- package/dist/scripts/zellij-worker-pane-manager-check.js +23 -1
- package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +21 -4
- package/package.json +17 -2
- package/schemas/research/claim-evidence-matrix.schema.json +37 -0
- package/schemas/research/experiment-plan.schema.json +17 -0
- package/schemas/research/implementation-blueprint.schema.json +30 -0
- package/schemas/research/replication-pack.schema.json +17 -0
- package/schemas/research/research-final-review.schema.json +16 -0
- package/schemas/research/research-quality-contract.schema.json +37 -0
- package/schemas/research/source-quality-report.schema.json +18 -0
package/README.md
CHANGED
|
@@ -16,12 +16,14 @@ 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.13** is the public-ready research pipeline stabilization release. It closes the Research quality contract, claim-evidence matrix, source-quality report, implementation handoff, experiment/replication pack, final-reviewer, and read-only stage-aware work graph path while preserving the 2.0.12 parallel runtime stabilization work.
|
|
20
20
|
|
|
21
21
|
What changed:
|
|
22
22
|
|
|
23
|
-
- Zellij slot panes
|
|
24
|
-
- Naruto
|
|
23
|
+
- Zellij slot panes distinguish `slot_status_renderer` panes from Codex worker panes, and the first visible worker now stacks downward below the `SLOTS` anchor with real geometry proof available under `real-check`.
|
|
24
|
+
- Naruto allocation owners now flow into work graph items, scheduler slices, queue ownership, and worker runtime proof; inactive owners are rebalanced and active write conflicts stay out of concurrent execution.
|
|
25
|
+
- Naruto active-pool checks now exercise actual child-worker spawn/result collection paths while production source-of-truth stays with the agent orchestrator scheduler.
|
|
26
|
+
- Worktree candidate output requires GPT Final approval before apply; GPT `modified` output replaces candidate patches and GPT `rejected` blocks apply.
|
|
25
27
|
- Visible Zellij reservations are capped before pane launch so concurrent worker starts cannot over-open the right column.
|
|
26
28
|
- Git worktree integration now proves the primary repo receives validated worktree diffs, with rollback hash evidence recorded around the apply step.
|
|
27
29
|
- Agent role config repair detects stale generated role files and rewrites structured GPT-5.5-compatible configs atomically.
|
|
@@ -464,6 +466,8 @@ sks code-structure scan --json
|
|
|
464
466
|
|
|
465
467
|
`sks research` prepares a named genius-lens agent council, requires every agent to run at `xhigh`, records one literal `Eureka!` idea per agent, runs an evidence-bound debate, and creates `research-source-skill.md` as a route-local source collection skill before synthesis. Research is not a code-change route: real runs may write only their own mission artifacts under `.sneakoscope/missions/<id>/`, and source/package/docs/config mutations block the run with `research-code-mutation-blocker.json`. The required Research persona lenses are Einstein Agent, Feynman Agent, Turing Agent, von Neumann Agent, and Skeptic Agent; they are cognitive roles, not impersonations, and `agent-ledger.json` must include `display_name`, `persona`, `persona_boundary`, `reasoning_effort`, falsifiers, cheap probes, and `challenge_or_response`. Normal Research is not a fixed three-cycle flow: it repeats source gathering, Eureka ideas, debate, falsification, and synthesis pressure until every agent records final agreement, or pauses at the explicit max-cycle safety cap with an unpassed gate. `debate-ledger.json` must include `consensus_iterations`, `unanimous_consensus`, and per-agent agreements; `research-gate.json` cannot pass until unanimous consensus is true for all agents. Normal Research is intentionally allowed to take one or two hours when the problem needs it; `--mock` is only for selftests or dry harness checks, and a real run blocks with `research-blocker.json` instead of silently substituting mock output when the Codex execution path is unavailable. The source layer contract separates latest papers, official/government or leading-institution sources, standards/primary docs, current news such as BBC/CNN/GDELT-style sources, public discourse such as X/Reddit, developer/practitioner knowledge such as Stack Overflow/GitHub, traditional background sources, and counterevidence/fact-checking; `source-ledger.json` must record layer coverage, source quality, blockers, citations, and cross-layer triangulation. Context7 is optional for `$Research` and only becomes relevant when the research topic specifically depends on package, API, framework, or SDK documentation. Research runs require `research-report.md`, `research-paper.md`, `genius-opinion-summary.md`, `research-source-skill.md`, `source-ledger.json`, `agent-ledger.json`, `debate-ledger.json`, `novelty-ledger.json`, `falsification-ledger.json`, and `research-gate.json` so they stay source-backed, adversarially checked, falsifiable, paper-ready, and clear about every agent lens opinion. `research status` reports source entries, source-layer coverage, triangulation checks, counterevidence, xhigh agent count, Eureka moments, debate exchanges, consensus iterations, unanimous consensus, paper presence/sections, genius-opinion summary coverage, agent findings, and falsification cases alongside the gate.
|
|
466
468
|
|
|
469
|
+
In 2.0.13, Research also writes a quality contract and handoff package: `research-quality-contract.json`, `claim-evidence-matrix.json`, `source-quality-report.json`, `implementation-blueprint.json`/`.md`, `experiment-plan.json`/`.md`, `replication-pack.json`, `research-work-graph.json`, and `research-final-review.json`. The default gate requires 12 total sources, 5 source layers, 2 counterevidence sources, 8 key claims, 6 triangulated claims, 8 blueprint sections, 4 falsification cases, 5 experiment steps, and a 2200-word report before `research-gate.json` can pass. See `docs/research-pipeline.md`, `docs/research-artifacts.md`, and `docs/research-implementation-handoff.md`.
|
|
470
|
+
|
|
467
471
|
`sks recallpulse` is the 0.8.0 report-only RecallPulse utility. It writes `recallpulse-decision.json`, `mission-status-ledger.json`, `route-proof-capsule.json`, `evidence-envelope.json`, `recallpulse-governance-report.json`, `recallpulse-task-goal-ledger.json`, and `recallpulse-eval-report.json` for the current mission. RecallPulse does not replace route gates, Honest Mode, DB safety, imagegen evidence, or TriWiki validation; it records cache hits, hydration needs, duplicate suppression, route-governance risks, and final-summary-ready durable status so later releases can promote only measured improvements. Checklist updates are sequential: every `Txxx` row is treated as a child `$Goal` checkpoint, and `sks recallpulse checklist ... --task T001 --apply` refuses out-of-order checks unless explicitly overridden.
|
|
468
472
|
|
|
469
473
|
`sks pipeline plan` shows the active route lane, kept/skipped stages, verification commands, and no-unrequested-fallback invariant. The 0.9.0 Decision Lattice augments this planning surface with report-only A*/proof-debt evidence: frontier paths considered, the selected path, and rejected paths with rejection reasons. `sks proof-field scan` remains the lightweight rubric for small changes; risky or broad signals return to the full Team/Honest path, and no speedup claim is valid without replay or eval evidence.
|
|
@@ -529,6 +533,8 @@ $DB inspect this migration for destructive risk
|
|
|
529
533
|
|
|
530
534
|
Local model workers are off by default, so SKS stays GPT-only unless you explicitly enable them. Use the Codex App prompt commands:
|
|
531
535
|
|
|
536
|
+

|
|
537
|
+
|
|
532
538
|
```text
|
|
533
539
|
$with-local-llm-on
|
|
534
540
|
$with-local-llm-off
|
|
@@ -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.13"),
|
|
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.13",
|
|
5
|
+
"source_digest": "4e6d812c7572cee4b51a8e1d0374fff3b908c58e2173b6255122b87ce9e8b83e",
|
|
6
|
+
"source_file_count": 2090,
|
|
7
|
+
"built_at_source_time": 1780843454792
|
|
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": "2.0.
|
|
4
|
-
"package_version": "2.0.
|
|
3
|
+
"version": "2.0.13",
|
|
4
|
+
"package_version": "2.0.13",
|
|
5
5
|
"typescript": true,
|
|
6
6
|
"mjs_runtime_files": 0,
|
|
7
|
-
"compiled_file_count":
|
|
8
|
-
"compiled_js_count":
|
|
7
|
+
"compiled_file_count": 1127,
|
|
8
|
+
"compiled_js_count": 1127,
|
|
9
9
|
"compiled_dts_count": 0,
|
|
10
|
-
"source_digest": "
|
|
11
|
-
"source_file_count":
|
|
12
|
-
"source_files_hash": "
|
|
13
|
-
"source_list_hash": "
|
|
10
|
+
"source_digest": "4e6d812c7572cee4b51a8e1d0374fff3b908c58e2173b6255122b87ce9e8b83e",
|
|
11
|
+
"source_file_count": 2090,
|
|
12
|
+
"source_files_hash": "07ac9249be0189c641861e02515d575578156357d6a92cd33869ae8cc4a38691",
|
|
13
|
+
"source_list_hash": "07ac9249be0189c641861e02515d575578156357d6a92cd33869ae8cc4a38691",
|
|
14
14
|
"src_mjs_runtime_files": 0,
|
|
15
15
|
"dist_stamp_schema": "sks.dist-build-stamp.v1",
|
|
16
16
|
"files": [
|
|
@@ -538,6 +538,21 @@
|
|
|
538
538
|
"core/release/release-gate-scheduler.js",
|
|
539
539
|
"core/reporting/markdown-table.js",
|
|
540
540
|
"core/research.js",
|
|
541
|
+
"core/research/claim-evidence-matrix.js",
|
|
542
|
+
"core/research/experiment-plan.js",
|
|
543
|
+
"core/research/falsification.js",
|
|
544
|
+
"core/research/implementation-blueprint-markdown.js",
|
|
545
|
+
"core/research/implementation-blueprint.js",
|
|
546
|
+
"core/research/replication-pack.js",
|
|
547
|
+
"core/research/research-cycle-runner.js",
|
|
548
|
+
"core/research/research-final-reviewer.js",
|
|
549
|
+
"core/research/research-handoff.js",
|
|
550
|
+
"core/research/research-prompt-contract.js",
|
|
551
|
+
"core/research/research-quality-contract.js",
|
|
552
|
+
"core/research/research-report-quality.js",
|
|
553
|
+
"core/research/research-stage-runner.js",
|
|
554
|
+
"core/research/research-work-graph.js",
|
|
555
|
+
"core/research/source-quality-report.js",
|
|
541
556
|
"core/responses-retry-policy.js",
|
|
542
557
|
"core/retention.js",
|
|
543
558
|
"core/router/capability-card.js",
|
|
@@ -905,6 +920,7 @@
|
|
|
905
920
|
"scripts/local-collab-gpt-final-availability-check.js",
|
|
906
921
|
"scripts/local-collab-no-local-only-final-check.js",
|
|
907
922
|
"scripts/local-collab-policy-check.js",
|
|
923
|
+
"scripts/local-collab-worktree-gpt-final-apply-policy-check.js",
|
|
908
924
|
"scripts/local-llm-all-pipelines-check.js",
|
|
909
925
|
"scripts/local-llm-cache-performance-check.js",
|
|
910
926
|
"scripts/local-llm-capability-check.js",
|
|
@@ -942,6 +958,7 @@
|
|
|
942
958
|
"scripts/naruto-active-pool-check.js",
|
|
943
959
|
"scripts/naruto-actual-worker-control-plane-check.js",
|
|
944
960
|
"scripts/naruto-allocation-policy-check.js",
|
|
961
|
+
"scripts/naruto-allocation-runtime-wiring-check.js",
|
|
945
962
|
"scripts/naruto-concurrency-governor-check.js",
|
|
946
963
|
"scripts/naruto-extreme-parallelism-check.js",
|
|
947
964
|
"scripts/naruto-extreme-parallelism-real-check.js",
|
|
@@ -1036,6 +1053,7 @@
|
|
|
1036
1053
|
"scripts/repo-audit.js",
|
|
1037
1054
|
"scripts/research-actual-route-backfill-check.js",
|
|
1038
1055
|
"scripts/research-backfill-route-blackbox.js",
|
|
1056
|
+
"scripts/research-quality-gate-check.js",
|
|
1039
1057
|
"scripts/responses-retry-policy-centralized-check.js",
|
|
1040
1058
|
"scripts/retention-cleanup-safety-check.js",
|
|
1041
1059
|
"scripts/route-blackbox-realism-check.js",
|
|
@@ -1117,6 +1135,7 @@
|
|
|
1117
1135
|
"scripts/zellij-slot-column-anchor-check.js",
|
|
1118
1136
|
"scripts/zellij-slot-only-ui-check.js",
|
|
1119
1137
|
"scripts/zellij-slot-pane-renderer-check.js",
|
|
1138
|
+
"scripts/zellij-slot-renderer-proof-semantics-check.js",
|
|
1120
1139
|
"scripts/zellij-spawn-on-demand-layout-check.js",
|
|
1121
1140
|
"scripts/zellij-ui-design-check.js",
|
|
1122
1141
|
"scripts/zellij-worker-pane-manager-check.js",
|
|
@@ -3,6 +3,8 @@ import { createMission, missionDir, setCurrent } from '../mission.js';
|
|
|
3
3
|
import { exists, nowIso, readJson, readText, sha256, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
|
|
4
4
|
import { buildAgentRoster, normalizeAgentConcurrency } from './agent-roster.js';
|
|
5
5
|
import { buildAgentWorkPartition } from './agent-work-partition.js';
|
|
6
|
+
import { detectAgentLeaseConflicts } from './work-partition/conflict-detector.js';
|
|
7
|
+
import { buildNoOverlapProof } from './work-partition/no-overlap-proof.js';
|
|
6
8
|
import { initializeAgentCentralLedger, appendAgentLedgerEvent, compactAgentLedger } from './agent-central-ledger.js';
|
|
7
9
|
import { detectStaleAgentSessions, killTimedOutAgentSessions, openAgentSession, heartbeatAgentSession, collectAgentSession, completeAgentSession, closeAgentSession, writeAgentLifecycleAggregate, writeAgentLifecyclePolicy } from './agent-lifecycle.js';
|
|
8
10
|
import { writeAgentConsensus } from './agent-consensus.js';
|
|
@@ -59,6 +61,8 @@ import { checkpointWorkerWorktree } from '../git/git-worktree-checkpoint.js';
|
|
|
59
61
|
import { cleanupGitWorktree } from '../git/git-worktree-cleanup.js';
|
|
60
62
|
import { createGitIntegrationWorktree } from '../git/git-integration-worktree.js';
|
|
61
63
|
import { applyGitWorktreeMergeQueue } from '../git/git-worktree-merge-queue.js';
|
|
64
|
+
import { crossRebaseIdleWorktrees } from '../git/git-worktree-cross-rebase.js';
|
|
65
|
+
import { gitOutputLine, runGitCommand } from '../git/git-worktree-runner.js';
|
|
62
66
|
export async function runNativeAgentOrchestrator(opts = {}) {
|
|
63
67
|
const root = path.resolve(opts.root || process.cwd());
|
|
64
68
|
const prompt = String(opts.prompt || 'Native agent run');
|
|
@@ -193,7 +197,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
193
197
|
}
|
|
194
198
|
};
|
|
195
199
|
}
|
|
196
|
-
|
|
200
|
+
let partition = await buildAgentWorkPartition(root, roster, prompt, {
|
|
197
201
|
route,
|
|
198
202
|
targetActiveSlots,
|
|
199
203
|
desiredWorkItemCount,
|
|
@@ -204,12 +208,24 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
204
208
|
strategyOwnershipPlan: strategyCompiled.file_ownership_plan,
|
|
205
209
|
microWins: strategyCompiled.gate.micro_wins
|
|
206
210
|
});
|
|
211
|
+
if (opts.narutoWorkGraph?.work_items?.length) {
|
|
212
|
+
partition = applyNarutoWorkGraphToPartition(partition, opts.narutoWorkGraph, roster, targetActiveSlots);
|
|
213
|
+
augmentVerificationRollbackDagForNaruto(strategyCompiled.verification_rollback_dag, partition.slices);
|
|
214
|
+
}
|
|
207
215
|
await runAgentJanitor({ missionDir: dir, missionId, projectHash: namespace.root_hash });
|
|
208
216
|
const ledgerRoot = await initializeAgentCentralLedger(dir, { missionId, roster, partition, route, prompt, dynamicScheduler: true });
|
|
209
217
|
// Consult the TriWiki context pack (read-only) before dispatching workers, and
|
|
210
218
|
// persist it as a proof artifact so the kernel proof references the wiki it acted on.
|
|
211
219
|
const triwikiContext = await loadTriWikiRuntimeContext(root);
|
|
212
220
|
await writeTriWikiContextArtifact(ledgerRoot, triwikiContext);
|
|
221
|
+
if (opts.narutoWorkGraph?.work_items?.length) {
|
|
222
|
+
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-work-graph.json'), opts.narutoWorkGraph);
|
|
223
|
+
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-runtime-wiring.json'), buildNarutoRuntimeWiringProof(partition, opts.narutoWorkGraph, roster, targetActiveSlots));
|
|
224
|
+
}
|
|
225
|
+
if (opts.narutoAllocationPolicy)
|
|
226
|
+
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-allocation-policy.json'), opts.narutoAllocationPolicy);
|
|
227
|
+
if (opts.narutoRebalancePolicy)
|
|
228
|
+
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-rebalance-policy.json'), opts.narutoRebalancePolicy);
|
|
213
229
|
await writeAgentTaskGraph(ledgerRoot, partition.task_graph);
|
|
214
230
|
await writeAdhdOrchestrationArtifacts(ledgerRoot, strategyCompiled.gate);
|
|
215
231
|
await writeStrategyCompilerArtifacts(ledgerRoot, strategyCompiled);
|
|
@@ -344,6 +360,8 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
344
360
|
const result = opts.nativeCliSwarm === false
|
|
345
361
|
? await runAgentByBackend(backend, runtimeAgent, runtimeSlice, backendOpts)
|
|
346
362
|
: await nativeCliSwarm.launchWorker({ agent: runtimeAgent, slice: runtimeSlice, opts: backendOpts });
|
|
363
|
+
if (route === '$Naruto')
|
|
364
|
+
attachNarutoRuntimeProof(result, runtimeAgent, runtimeSlice);
|
|
347
365
|
if (workerWorktree)
|
|
348
366
|
await finalizeWorkerGitWorktree({
|
|
349
367
|
root,
|
|
@@ -602,6 +620,247 @@ function withFinalGptPatchEnvelopes(results, patchEnvelopes = []) {
|
|
|
602
620
|
next[0] = { ...next[0], patch_envelopes: patchEnvelopes };
|
|
603
621
|
return next;
|
|
604
622
|
}
|
|
623
|
+
function applyNarutoWorkGraphToPartition(partition, graph, roster, targetActiveSlots) {
|
|
624
|
+
const activeRoster = (Array.isArray(roster?.roster) ? roster.roster : []).slice(0, Math.max(1, targetActiveSlots));
|
|
625
|
+
const activeAgentIds = new Set(activeRoster.map((row) => String(row.id || '')).filter(Boolean));
|
|
626
|
+
const fallbackOwners = activeRoster.length ? activeRoster : [{ id: 'naruto_clone_001', role: 'verifier' }];
|
|
627
|
+
const referenceWorkItem = Array.isArray(partition?.task_graph?.work_items) ? partition.task_graph.work_items.find(Boolean) : null;
|
|
628
|
+
const sourceIntelligenceRefs = referenceWorkItem?.source_intelligence_refs || partition?.source_intelligence_refs || null;
|
|
629
|
+
const goalModeRef = referenceWorkItem?.goal_mode_ref || partition?.goal_mode_ref || null;
|
|
630
|
+
const strategyRefs = referenceWorkItem?.strategy_refs || partition?.strategy_refs || null;
|
|
631
|
+
const slices = (graph.work_items || []).map((item, index) => {
|
|
632
|
+
const requestedOwner = item.owner ? String(item.owner) : '';
|
|
633
|
+
const owner = requestedOwner && activeAgentIds.has(requestedOwner)
|
|
634
|
+
? requestedOwner
|
|
635
|
+
: String(fallbackOwners[index % fallbackOwners.length]?.id || requestedOwner || `naruto_clone_${String(index + 1).padStart(3, '0')}`);
|
|
636
|
+
const sliceId = String(item.id || `NW-${String(index + 1).padStart(6, '0')}`);
|
|
637
|
+
const writePaths = normalizePathList(item.write_paths);
|
|
638
|
+
const readonlyPaths = normalizePathList(item.readonly_paths);
|
|
639
|
+
const targetPaths = normalizePathList(item.target_paths);
|
|
640
|
+
const verificationNodeId = writePaths.length ? `verify:${sliceId}` : null;
|
|
641
|
+
const rollbackNodeId = writePaths.length ? `rollback:${sliceId}` : null;
|
|
642
|
+
return {
|
|
643
|
+
id: sliceId,
|
|
644
|
+
owner_agent_id: owner,
|
|
645
|
+
owner,
|
|
646
|
+
lane: owner,
|
|
647
|
+
role: String(item.required_role || 'verifier'),
|
|
648
|
+
domain: String(item.allocation_hints?.domains?.[0] || item.kind || 'naruto'),
|
|
649
|
+
title: String(item.title || item.id || `Naruto work ${index + 1}`),
|
|
650
|
+
dependencies: Array.isArray(item.dependencies) ? item.dependencies.map(String) : [],
|
|
651
|
+
priority: index + 1,
|
|
652
|
+
required_persona_category: String(item.required_role || 'verifier'),
|
|
653
|
+
lease_requirements: Array.isArray(item.lease_requirements) ? item.lease_requirements : [],
|
|
654
|
+
generated_by: 'sks.naruto-work-graph.v1',
|
|
655
|
+
route_domain: String(item.kind || 'naruto'),
|
|
656
|
+
work_item_kind: String(item.kind || 'verification'),
|
|
657
|
+
target_paths: targetPaths,
|
|
658
|
+
readonly_paths: readonlyPaths,
|
|
659
|
+
write_paths: writePaths,
|
|
660
|
+
allocation_reason: item.allocation_reason || null,
|
|
661
|
+
allocation_score: item.allocation_score ?? null,
|
|
662
|
+
allocation_hints: item.allocation_hints || null,
|
|
663
|
+
allocation_original_owner: requestedOwner || null,
|
|
664
|
+
allocation_owner_rebalanced: Boolean(requestedOwner && owner !== requestedOwner),
|
|
665
|
+
micro_win_id: sliceId,
|
|
666
|
+
verification_node_id: verificationNodeId,
|
|
667
|
+
rollback_node_id: rollbackNodeId,
|
|
668
|
+
verification_required: item.verification_required === true,
|
|
669
|
+
source_intelligence_refs: sourceIntelligenceRefs,
|
|
670
|
+
goal_mode_ref: goalModeRef,
|
|
671
|
+
strategy_refs: strategyRefs,
|
|
672
|
+
max_attempts: 1,
|
|
673
|
+
description: [
|
|
674
|
+
String(item.title || item.id || 'Naruto work item'),
|
|
675
|
+
`Naruto owner: ${owner}`,
|
|
676
|
+
item.allocation_reason ? `Allocation: ${item.allocation_reason}` : null,
|
|
677
|
+
writePaths.length ? `Write paths: ${writePaths.join(', ')}` : 'Read-only or no-write work item.'
|
|
678
|
+
].filter(Boolean).join('\n')
|
|
679
|
+
};
|
|
680
|
+
});
|
|
681
|
+
const workItems = (graph.work_items || []).map((item) => ({
|
|
682
|
+
...item,
|
|
683
|
+
source_intelligence_refs: item.source_intelligence_refs || sourceIntelligenceRefs,
|
|
684
|
+
goal_mode_ref: item.goal_mode_ref || goalModeRef,
|
|
685
|
+
strategy_refs: item.strategy_refs || strategyRefs
|
|
686
|
+
}));
|
|
687
|
+
const leases = slices.flatMap((slice) => [
|
|
688
|
+
...slice.write_paths.map((file, index) => ({
|
|
689
|
+
id: `${slice.id}:write:${index + 1}`,
|
|
690
|
+
agent_id: slice.owner_agent_id,
|
|
691
|
+
kind: 'write',
|
|
692
|
+
path: file,
|
|
693
|
+
domain: slice.domain,
|
|
694
|
+
status: 'active',
|
|
695
|
+
owner_agent: slice.owner_agent_id,
|
|
696
|
+
write_paths: slice.write_paths,
|
|
697
|
+
strategy_task_id: slice.id,
|
|
698
|
+
micro_win_id: slice.micro_win_id || slice.id,
|
|
699
|
+
verification_node_id: slice.verification_node_id || null,
|
|
700
|
+
rollback_node_id: slice.rollback_node_id || null,
|
|
701
|
+
protected_path_check: { ok: true, blockers: [] }
|
|
702
|
+
})),
|
|
703
|
+
...slice.readonly_paths.map((file, index) => ({
|
|
704
|
+
id: `${slice.id}:read:${index + 1}`,
|
|
705
|
+
agent_id: slice.owner_agent_id,
|
|
706
|
+
kind: 'read',
|
|
707
|
+
path: file,
|
|
708
|
+
domain: slice.domain,
|
|
709
|
+
status: 'active',
|
|
710
|
+
owner_agent: slice.owner_agent_id,
|
|
711
|
+
write_paths: slice.write_paths,
|
|
712
|
+
strategy_task_id: slice.id,
|
|
713
|
+
micro_win_id: slice.micro_win_id || slice.id,
|
|
714
|
+
verification_node_id: slice.verification_node_id || null,
|
|
715
|
+
rollback_node_id: slice.rollback_node_id || null,
|
|
716
|
+
protected_path_check: { ok: true, blockers: [] }
|
|
717
|
+
}))
|
|
718
|
+
]);
|
|
719
|
+
const conflict_report = detectAgentLeaseConflicts(leases);
|
|
720
|
+
const no_overlap_proof = buildNoOverlapProof(leases);
|
|
721
|
+
const taskGraph = partition.task_graph
|
|
722
|
+
? {
|
|
723
|
+
...partition.task_graph,
|
|
724
|
+
total_work_items: slices.length,
|
|
725
|
+
work_items: workItems,
|
|
726
|
+
route_work_count_summary: {
|
|
727
|
+
...(partition.task_graph.route_work_count_summary || {}),
|
|
728
|
+
naruto_work_graph_items: slices.length,
|
|
729
|
+
allocation_owner_rebalanced_count: slices.filter((slice) => slice.allocation_owner_rebalanced).length
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
: null;
|
|
733
|
+
return {
|
|
734
|
+
...partition,
|
|
735
|
+
ok: conflict_report.ok && no_overlap_proof.ok,
|
|
736
|
+
task_graph: taskGraph,
|
|
737
|
+
slices,
|
|
738
|
+
leases,
|
|
739
|
+
conflict_report,
|
|
740
|
+
no_overlap_proof,
|
|
741
|
+
source_intelligence_refs: sourceIntelligenceRefs,
|
|
742
|
+
goal_mode_ref: goalModeRef,
|
|
743
|
+
strategy_refs: strategyRefs,
|
|
744
|
+
blockers: [...(conflict_report.blockers || []), ...(no_overlap_proof.blockers || [])]
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
function augmentVerificationRollbackDagForNaruto(dag, slices) {
|
|
748
|
+
if (!dag || !Array.isArray(dag.nodes) || !Array.isArray(slices))
|
|
749
|
+
return dag;
|
|
750
|
+
const byId = new Set(dag.nodes.map((node) => String(node.id || '')).filter(Boolean));
|
|
751
|
+
for (const slice of slices) {
|
|
752
|
+
const sliceId = String(slice?.id || '');
|
|
753
|
+
if (!sliceId)
|
|
754
|
+
continue;
|
|
755
|
+
const writePaths = normalizePathList(slice.write_paths);
|
|
756
|
+
if (!byId.has(sliceId)) {
|
|
757
|
+
dag.nodes.push({
|
|
758
|
+
id: sliceId,
|
|
759
|
+
kind: writePaths.length ? 'write' : 'verification',
|
|
760
|
+
depends_on: [],
|
|
761
|
+
proof_artifact: writePaths.length ? 'agent-patch-queue.json' : 'agent-worker-result.json'
|
|
762
|
+
});
|
|
763
|
+
byId.add(sliceId);
|
|
764
|
+
}
|
|
765
|
+
if (!writePaths.length)
|
|
766
|
+
continue;
|
|
767
|
+
const verificationNodeId = String(slice.verification_node_id || `verify:${sliceId}`);
|
|
768
|
+
const rollbackNodeId = String(slice.rollback_node_id || `rollback:${sliceId}`);
|
|
769
|
+
if (!byId.has(verificationNodeId)) {
|
|
770
|
+
dag.nodes.push({
|
|
771
|
+
id: verificationNodeId,
|
|
772
|
+
kind: 'verification',
|
|
773
|
+
depends_on: [sliceId],
|
|
774
|
+
proof_artifact: 'agent-patch-verification-results.json'
|
|
775
|
+
});
|
|
776
|
+
byId.add(verificationNodeId);
|
|
777
|
+
}
|
|
778
|
+
if (!byId.has(rollbackNodeId)) {
|
|
779
|
+
dag.nodes.push({
|
|
780
|
+
id: rollbackNodeId,
|
|
781
|
+
kind: 'rollback',
|
|
782
|
+
depends_on: [sliceId, verificationNodeId],
|
|
783
|
+
proof_artifact: 'agent-patch-rollback-proof.json'
|
|
784
|
+
});
|
|
785
|
+
byId.add(rollbackNodeId);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
dag.rollback_ready = true;
|
|
789
|
+
dag.verification_ready = true;
|
|
790
|
+
if (dag.validation?.blockers?.length)
|
|
791
|
+
dag.validation = { ok: true, blockers: [] };
|
|
792
|
+
return dag;
|
|
793
|
+
}
|
|
794
|
+
function buildNarutoRuntimeWiringProof(partition, graph, roster, targetActiveSlots) {
|
|
795
|
+
const activeAgentIds = new Set((Array.isArray(roster?.roster) ? roster.roster : []).slice(0, Math.max(1, targetActiveSlots)).map((row) => String(row.id || '')).filter(Boolean));
|
|
796
|
+
const slices = Array.isArray(partition?.slices) ? partition.slices : [];
|
|
797
|
+
const activeWriteConflicts = slices.flatMap((slice) => normalizePathList(slice.write_paths));
|
|
798
|
+
const duplicateActiveWrites = activeWriteConflicts.filter((file, index, all) => all.indexOf(file) !== index);
|
|
799
|
+
const ownerPreserved = slices.every((slice) => !slice.allocation_original_owner || slice.allocation_owner_rebalanced || slice.owner_agent_id === slice.allocation_original_owner);
|
|
800
|
+
const inactiveOwnersRebalanced = slices.every((slice) => !slice.allocation_original_owner || activeAgentIds.has(slice.allocation_original_owner) || slice.allocation_owner_rebalanced);
|
|
801
|
+
const blockers = [
|
|
802
|
+
...(slices.length === Number(graph?.work_items?.length || 0) ? [] : ['naruto_runtime_slice_count_mismatch']),
|
|
803
|
+
...(ownerPreserved ? [] : ['naruto_runtime_owner_not_preserved']),
|
|
804
|
+
...(inactiveOwnersRebalanced ? [] : ['naruto_runtime_inactive_owner_not_rebalanced']),
|
|
805
|
+
...(duplicateActiveWrites.length ? ['naruto_runtime_duplicate_write_paths_in_partition'] : [])
|
|
806
|
+
];
|
|
807
|
+
return {
|
|
808
|
+
schema: 'sks.naruto-runtime-wiring.v1',
|
|
809
|
+
generated_at: nowIso(),
|
|
810
|
+
ok: blockers.length === 0,
|
|
811
|
+
source_of_truth: 'naruto-work-graph',
|
|
812
|
+
scheduler_slice_count: slices.length,
|
|
813
|
+
work_graph_item_count: Number(graph?.work_items?.length || 0),
|
|
814
|
+
owner_preserved: ownerPreserved,
|
|
815
|
+
inactive_owners_rebalanced: inactiveOwnersRebalanced,
|
|
816
|
+
write_conflict_free_partition: duplicateActiveWrites.length === 0,
|
|
817
|
+
slice_owners: slices.map((slice) => ({
|
|
818
|
+
id: slice.id,
|
|
819
|
+
owner_agent_id: slice.owner_agent_id,
|
|
820
|
+
original_owner: slice.allocation_original_owner || null,
|
|
821
|
+
rebalanced: slice.allocation_owner_rebalanced === true,
|
|
822
|
+
write_paths: slice.write_paths || [],
|
|
823
|
+
dependencies: slice.dependencies || []
|
|
824
|
+
})),
|
|
825
|
+
blockers
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
function attachNarutoRuntimeProof(result, agent, slice) {
|
|
829
|
+
const controlPlane = result?.codex_child_report || result?.codex_sdk_thread || result?.backend_router_report || null;
|
|
830
|
+
const selectedBackend = String(result?.backend_router_report?.selected_backend || result?.backend || '');
|
|
831
|
+
const actualWorkerControlPlane = selectedBackend === 'codex-sdk' || selectedBackend === 'local-llm'
|
|
832
|
+
? Boolean(controlPlane?.sdk_thread_id || controlPlane?.worker_result_path || result?.codex_child_report?.worker_result_path)
|
|
833
|
+
: false;
|
|
834
|
+
result.naruto_runtime = {
|
|
835
|
+
schema: 'sks.naruto-worker-runtime-proof.v1',
|
|
836
|
+
source_of_truth: 'agent-orchestrator-scheduler',
|
|
837
|
+
actual_worker_control_plane: actualWorkerControlPlane,
|
|
838
|
+
work_item_id: String(slice?.id || result?.task_slice_id || ''),
|
|
839
|
+
owner: String(slice?.owner_agent_id || slice?.owner || agent?.id || ''),
|
|
840
|
+
allocation_reason: slice?.allocation_reason || null,
|
|
841
|
+
rebalance_generation: Number(slice?.allocation_owner_rebalanced === true ? 1 : 0),
|
|
842
|
+
selected_backend: selectedBackend || null,
|
|
843
|
+
explicit_fake_backend: selectedBackend === 'fake',
|
|
844
|
+
control_plane_result: controlPlane
|
|
845
|
+
? {
|
|
846
|
+
worker_result_path: controlPlane.worker_result_path || null,
|
|
847
|
+
sdk_thread_id: controlPlane.sdk_thread_id || null,
|
|
848
|
+
sdk_run_id: controlPlane.sdk_run_id || null,
|
|
849
|
+
structured_output_valid: controlPlane.structured_output_valid === true,
|
|
850
|
+
stream_event_count: Number(controlPlane.stream_event_count || 0)
|
|
851
|
+
}
|
|
852
|
+
: null
|
|
853
|
+
};
|
|
854
|
+
if (result.naruto_runtime.control_plane_result)
|
|
855
|
+
result.control_plane_result = result.naruto_runtime.control_plane_result;
|
|
856
|
+
result.verification = {
|
|
857
|
+
status: result.verification?.status || 'not_run',
|
|
858
|
+
checks: [...(result.verification?.checks || []), 'naruto-agent-orchestrator-scheduler-source-of-truth']
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
function normalizePathList(values) {
|
|
862
|
+
return (Array.isArray(values) ? values : []).map((file) => String(file || '').replace(/\\/g, '/').replace(/^\.\/+/, '').replace(/\/+$/, '')).filter(Boolean);
|
|
863
|
+
}
|
|
605
864
|
async function prepareWorkerGitWorktree(input) {
|
|
606
865
|
if (input.policy?.mode !== 'git-worktree')
|
|
607
866
|
return null;
|
|
@@ -1075,6 +1334,24 @@ async function runGitWorktreeIntegrationPrimary(root, ledgerRoot, missionId, ent
|
|
|
1075
1334
|
checkpoints
|
|
1076
1335
|
})
|
|
1077
1336
|
: null;
|
|
1337
|
+
const integrationHead = mainApplyReport?.ok
|
|
1338
|
+
? gitOutputLine(await runGitCommand(repoRoot, ['rev-parse', 'HEAD']).catch(() => ({ ok: false, stdout: '' })))
|
|
1339
|
+
: null;
|
|
1340
|
+
const crossRebase = integrationHead
|
|
1341
|
+
? await crossRebaseIdleWorktrees({
|
|
1342
|
+
integrationHead,
|
|
1343
|
+
workers: diffs
|
|
1344
|
+
.filter((diff) => diff.worktree_path)
|
|
1345
|
+
.map((diff) => ({
|
|
1346
|
+
worker_id: diff.worker_id,
|
|
1347
|
+
worktree_path: diff.worktree_path,
|
|
1348
|
+
branch: diff.branch,
|
|
1349
|
+
state: 'done'
|
|
1350
|
+
}))
|
|
1351
|
+
})
|
|
1352
|
+
: null;
|
|
1353
|
+
if (crossRebase)
|
|
1354
|
+
await writeJsonAtomic(path.join(ledgerRoot, 'git-worktree-cross-rebase-report.json'), crossRebase);
|
|
1078
1355
|
const rollbackEvidence = mainApplyReport?.ok
|
|
1079
1356
|
? await completeGitWorktreeRollbackPlan(repoRoot, rollbackPlan.rollback)
|
|
1080
1357
|
: rollbackPlan;
|
|
@@ -1120,6 +1397,7 @@ async function runGitWorktreeIntegrationPrimary(root, ledgerRoot, missionId, ent
|
|
|
1120
1397
|
conflicted_entry_ids: conflictedEntryIds,
|
|
1121
1398
|
merge_queue: queueReport,
|
|
1122
1399
|
main_repo_apply: mainApplyReport,
|
|
1400
|
+
cross_rebase: crossRebase,
|
|
1123
1401
|
rollback_evidence: rollbackEvidence,
|
|
1124
1402
|
apply_results: applyResults,
|
|
1125
1403
|
blockers: reportBlockers
|
|
@@ -115,7 +115,11 @@ export async function runAgentScheduler(input) {
|
|
|
115
115
|
break;
|
|
116
116
|
const generationIndex = slot.generation_count + 1;
|
|
117
117
|
const provisionalSessionId = `${slot.slot_id}-gen-${generationIndex}`;
|
|
118
|
-
const workItem = leaseNextWorkItem(queue, provisionalSessionId
|
|
118
|
+
const workItem = leaseNextWorkItem(queue, provisionalSessionId, {
|
|
119
|
+
slotId: slot.slot_id,
|
|
120
|
+
agentId: String(slot.persona_assignment?.agent_id || ''),
|
|
121
|
+
activeWritePaths: activeWritePaths(queue)
|
|
122
|
+
});
|
|
119
123
|
if (!workItem)
|
|
120
124
|
break;
|
|
121
125
|
const generation = createAgentSessionGeneration({
|
|
@@ -314,6 +318,13 @@ function buildAgentForGeneration(slot, generation, workItem) {
|
|
|
314
318
|
goal_mode_ref: generation.goal_mode_ref
|
|
315
319
|
};
|
|
316
320
|
}
|
|
321
|
+
function activeWritePaths(queue) {
|
|
322
|
+
return queue.items
|
|
323
|
+
.filter((item) => item.status === 'running')
|
|
324
|
+
.flatMap((item) => Array.isArray(item.slice?.write_paths) ? item.slice.write_paths : [])
|
|
325
|
+
.map((file) => String(file || '').replace(/\\/g, '/').replace(/^\.\/+/, '').replace(/\/+$/, ''))
|
|
326
|
+
.filter(Boolean);
|
|
327
|
+
}
|
|
317
328
|
function delay(ms) {
|
|
318
329
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
319
330
|
}
|
|
@@ -14,9 +14,9 @@ export async function evaluateAgentSlotPaneBindingProof(root, input = {}) {
|
|
|
14
14
|
const summary = await readJson(path.join(root, 'agent-native-cli-session-swarm.json'), null);
|
|
15
15
|
const ledger = await readJsonl(path.join(root, 'agent-zellij-pane-launch-ledger.jsonl'));
|
|
16
16
|
const zellijRecords = Array.isArray(summary?.records)
|
|
17
|
-
? summary.records.filter((record) => record.scaling_primitive === 'native_cli_process_in_zellij_worker_pane')
|
|
17
|
+
? summary.records.filter((record) => record.scaling_primitive === 'native_cli_process_in_zellij_worker_pane' || record.scaling_primitive === 'native_cli_process_with_zellij_slot_renderer')
|
|
18
18
|
: [];
|
|
19
|
-
const paneLedgers = ledger.filter((row) => row.scaling_primitive === 'native_cli_process_in_zellij_worker_pane' || row.pane_kind === 'worker_codex_sdk');
|
|
19
|
+
const paneLedgers = ledger.filter((row) => row.scaling_primitive === 'native_cli_process_in_zellij_worker_pane' || row.scaling_primitive === 'native_cli_process_with_zellij_slot_renderer' || row.pane_kind === 'worker_codex_sdk' || row.pane_kind === 'slot_status_renderer');
|
|
20
20
|
const uniqueKeys = new Set();
|
|
21
21
|
const duplicates = [];
|
|
22
22
|
for (const row of zellijRecords) {
|
|
@@ -29,7 +29,7 @@ export async function evaluateAgentSlotPaneBindingProof(root, input = {}) {
|
|
|
29
29
|
const zellijPaneWorkerSessions = Number(summary?.zellij_pane_worker_sessions || 0);
|
|
30
30
|
const blockers = [
|
|
31
31
|
...(input.requireZellij && !zellijRecords.length ? ['slot_pane_binding_zellij_records_missing'] : []),
|
|
32
|
-
...(zellijRecords.some((record) => record.pane_kind !== 'worker_codex_sdk') ? ['slot_pane_binding_wrong_pane_kind'] : []),
|
|
32
|
+
...(zellijRecords.some((record) => record.pane_kind !== 'worker_codex_sdk' && record.pane_kind !== 'slot_status_renderer') ? ['slot_pane_binding_wrong_pane_kind'] : []),
|
|
33
33
|
...(zellijRecords.some((record) => !isRealZellijWorkerPaneIdSource(record.zellij_pane_id_source)) ? ['slot_pane_binding_synthetic_or_missing_pane_id_source'] : []),
|
|
34
34
|
...(zellijRecords.some((record) => !record.zellij_pane_id) ? ['slot_pane_binding_pane_id_missing'] : []),
|
|
35
35
|
...(zellijRecords.some((record) => !record.sdk_thread_id) ? ['slot_pane_binding_sdk_thread_id_missing'] : []),
|
|
@@ -44,8 +44,15 @@ export function pendingWorkItems(queue) {
|
|
|
44
44
|
.filter((item) => item.status === 'pending' && item.dependencies.every((dep) => completed.has(dep)))
|
|
45
45
|
.sort((a, b) => a.priority - b.priority || a.id.localeCompare(b.id));
|
|
46
46
|
}
|
|
47
|
-
export function leaseNextWorkItem(queue, sessionId) {
|
|
48
|
-
const
|
|
47
|
+
export function leaseNextWorkItem(queue, sessionId, opts = {}) {
|
|
48
|
+
const activeWritePaths = new Set((opts.activeWritePaths || []).map(normalizePath).filter(Boolean));
|
|
49
|
+
const ready = pendingWorkItems(queue).filter((candidate) => {
|
|
50
|
+
const writePaths = sliceWritePaths(candidate);
|
|
51
|
+
return writePaths.every((file) => !activeWritePaths.has(file));
|
|
52
|
+
});
|
|
53
|
+
const item = ready.find((candidate) => ownerMatches(candidate, opts))
|
|
54
|
+
|| ready.find((candidate) => !candidateOwner(candidate))
|
|
55
|
+
|| ready[0];
|
|
49
56
|
if (!item)
|
|
50
57
|
return null;
|
|
51
58
|
item.status = 'running';
|
|
@@ -54,6 +61,23 @@ export function leaseNextWorkItem(queue, sessionId) {
|
|
|
54
61
|
queue.updated_at = nowIso();
|
|
55
62
|
return item;
|
|
56
63
|
}
|
|
64
|
+
function ownerMatches(item, opts) {
|
|
65
|
+
const owner = candidateOwner(item);
|
|
66
|
+
if (!owner)
|
|
67
|
+
return false;
|
|
68
|
+
return owner === opts.slotId || owner === opts.agentId;
|
|
69
|
+
}
|
|
70
|
+
function candidateOwner(item) {
|
|
71
|
+
const slice = item.slice || {};
|
|
72
|
+
return String(slice.owner_agent_id || slice.owner || slice.lane || '').trim();
|
|
73
|
+
}
|
|
74
|
+
function sliceWritePaths(item) {
|
|
75
|
+
const paths = Array.isArray(item.slice?.write_paths) ? item.slice.write_paths : [];
|
|
76
|
+
return paths.map((file) => normalizePath(String(file))).filter(Boolean);
|
|
77
|
+
}
|
|
78
|
+
function normalizePath(file) {
|
|
79
|
+
return String(file || '').replace(/\\/g, '/').replace(/^\.\/+/, '').replace(/\/+$/, '');
|
|
80
|
+
}
|
|
57
81
|
export function completeWorkItem(queue, itemId, sessionId, status, reason = null) {
|
|
58
82
|
const item = queue.items.find((row) => row.id === itemId);
|
|
59
83
|
if (!item)
|
|
@@ -55,6 +55,8 @@ export function validateAgentWorkerResult(result) {
|
|
|
55
55
|
...(result?.source_intelligence_refs === undefined ? {} : { source_intelligence_refs: result.source_intelligence_refs }),
|
|
56
56
|
...(result?.goal_mode_ref === undefined ? {} : { goal_mode_ref: result.goal_mode_ref }),
|
|
57
57
|
...(result?.follow_up_work_items === undefined ? {} : { follow_up_work_items: followUps.accepted }),
|
|
58
|
+
...(result?.naruto_runtime === undefined ? {} : { naruto_runtime: result.naruto_runtime }),
|
|
59
|
+
...(result?.control_plane_result === undefined ? {} : { control_plane_result: result.control_plane_result }),
|
|
58
60
|
recursion_guard: { ok: guard.ok, violations: guard.violations },
|
|
59
61
|
verification: normalizeVerification(result?.verification)
|
|
60
62
|
};
|
|
@@ -336,8 +336,8 @@ class NativeCliSessionSwarmRecorder {
|
|
|
336
336
|
input.record.zellij_create_session = paneRecord.create_session;
|
|
337
337
|
input.record.zellij_launch = paneRecord.launch;
|
|
338
338
|
input.record.zellij_worker_pane = path.join(input.workerDirRel, 'zellij-worker-pane.json');
|
|
339
|
-
input.record.pane_kind =
|
|
340
|
-
input.record.scaling_primitive =
|
|
339
|
+
input.record.pane_kind = paneRecord.pane_kind;
|
|
340
|
+
input.record.scaling_primitive = paneRecord.scaling_primitive;
|
|
341
341
|
input.record.provider = paneRecord.provider;
|
|
342
342
|
input.record.service_tier = paneRecord.service_tier;
|
|
343
343
|
input.record.provider_context = paneRecord.provider_context;
|