@hecer/yoke 1.16.0 → 1.18.0

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.
@@ -56,7 +56,7 @@ export const YokeConfigSchema = z.object({
56
56
  agents: z.array(AgentSchema),
57
57
  loop: z.object({
58
58
  enabled: z.boolean(),
59
- parallel: z.union([z.literal('auto'), z.number().int().positive()]).optional(),
59
+ parallel: z.union([z.literal('auto'), z.number().int().min(1).max(8)]).optional(),
60
60
  isolate: z.boolean().optional(),
61
61
  timeoutMinutes: z.number().optional(),
62
62
  maxCallMinutes: z.number().positive().max(1440).optional(),
@@ -0,0 +1,67 @@
1
+ # Continuous autonomous exploration
2
+
3
+ The normal loop stops after every accepted PRD story passes and the optional completion gate is
4
+ green. `--explore` opts into a supervisor that keeps the loop alive after that point and looks for
5
+ the next evidence-backed improvement. Exploration is off by default.
6
+
7
+ ```powershell
8
+ yoke loop run . --explore --parallel=auto
9
+ yoke loop run . --explore --explore-interval=10
10
+ yoke loop run . --explore --explore-limit=3d
11
+ yoke loop status .
12
+ yoke loop pause .
13
+ ```
14
+
15
+ ## Discovery and implementation
16
+
17
+ After the current backlog drains, a configured planning provider inspects the read-only repository
18
+ and returns either a short wait decision or up to three independent tasks. Yoke accepts a proposal
19
+ only when it has at least 0.8 declared confidence, low or medium risk, existing-file evidence,
20
+ non-overlapping relative write scopes, and two to five structured acceptance criteria. Every
21
+ criterion must contain an approved test command that names its criterion ID. Paths, duplicate
22
+ contracts, dependencies and the combined PRD are validated mechanically.
23
+
24
+ Accepted tasks are appended to `.yoke/prd.yaml` and committed with the configured commit identity
25
+ before implementation. Stories always run in isolated worktrees through the project's existing
26
+ acceptance, verify, completion, review, audit, quality and commit gates. `--parallel` works as usual
27
+ for independent tasks. When the optional integrated completion gate fails after every story passes,
28
+ the explorer receives that failure as context and can propose work to resolve it; the gate itself is
29
+ never skipped.
30
+
31
+ Completed auto-generated stories are compacted out of the active PRD before the next exploration
32
+ pass, so the working backlog does not grow forever. Up to 100 recent task fingerprints, IDs and
33
+ criterion IDs remain in `.yoke/exploration-recent.json` for duplicate avoidance. Older PRD states and
34
+ their full acceptance contracts remain in Git history.
35
+
36
+ ## Waiting, recovery and stopping
37
+
38
+ The default no-op interval is 30 minutes. Set `--explore-interval=N` to an integer from 1 to 1440
39
+ minutes. If a provider fails, returns an invalid proposal, or a story is blocked, the supervisor
40
+ keeps running, rotates through available configured providers and retries with exponential backoff
41
+ up to 15 minutes. A task that requires a human decision remains pending; the supervisor waits for
42
+ the decision instead of declaring completion. During long waits, status heartbeats keep
43
+ `yoke loop status` accurate.
44
+
45
+ `yoke loop pause .` requests a pause at the next safe story or exploration boundary. It exits with
46
+ code `3`; start `yoke loop run . --explore` again to resume. An explicit `--max=N` remains a deliberate
47
+ story-attempt cap and exits with code `1` if work remains. Without that flag, reaching the end of a
48
+ PRD is not a stop condition.
49
+
50
+ Exploration has no time limit by default. Set `--explore-limit=12h`, `--explore-limit=3d`, or
51
+ `--explore-limit=2w` to set a positive duration in hours, days, or weeks. Full unit names also work
52
+ when quoted, for example `--explore-limit="2 days"`. When it expires, Yoke pauses automatically at a safe boundary and exits with
53
+ code `3`. It stops launching new workers, lets already active workers finish their acceptance,
54
+ verification and integration gates, and preserves resumable work. Finite runs process bounded task
55
+ batches so an unfinished large backlog does not run past the deadline by draining the whole PRD.
56
+ Omitting `--explore-limit` keeps the supervisor unbounded; a later resume starts a new duration if
57
+ one is supplied.
58
+
59
+ The supervisor can retry failures while its process remains alive. Run it in a background process
60
+ for long sessions. An operating-system shutdown, forced process termination, exhausted credentials
61
+ or unavailable machine cannot be prevented by an in-process loop; after a crash, inspect
62
+ `yoke loop status .`, recover retained work if needed, then restart with `yoke loop run . --explore`.
63
+
64
+ The explorer is a proposal filter, not a guarantee of product maturity. It uses repository evidence
65
+ and strict contracts to limit speculative work; implementation still depends on the project's real
66
+ tests and any enabled independent review or quality gates. The user decides when the project is
67
+ mature enough and can stop the supervisor with `yoke loop pause .`.
@@ -134,9 +134,11 @@ Versioned local events record status, phase duration, attempts and available usa
134
134
 
135
135
  New setups enable routing, `loop.parallel: auto` and `loop.isolate: true`. Existing explicit settings remain authoritative. At execution time, automatic routing uses configured profiles; without profiles it keeps the selected parent. Explicit `--routing` without profiles still reports a configuration error. Routing rules bypass the controller and can escalate following failed independent gates, including across worktrees and restarts. Routing now also runs asynchronously inside parallel workers. An explicit task provider affinity takes precedence over routing.
136
136
 
137
- Automatic parallelism allows at most three Yoke workers when every pending task declares nonempty write scopes. Dependencies and overlapping scopes still constrain dispatch. Unknown scopes, configured tool actions and worktree recovery select serial execution. Use `--parallel=N`, `--parallel=auto`, `--no-routing` or `--no-isolate` to override defaults. Serial worktrees retain failed work and require deliberate recovery; the default does not discard an existing recovery tree. Quality repair budgets and opt-in competing candidates retain their existing policies.
137
+ Automatic parallelism uses up to the shared worker limit when every pending task declares nonempty write scopes. The shared default is three units across concurrent Yoke projects; `YOKE_MAX_PARALLEL_WORKERS=1..8` sets the user-level ceiling. Dependencies, areas and overlapping scopes still constrain dispatch. Unknown scopes, configured tool actions and worktree recovery select serial execution. Use `--parallel=N`, `--parallel=auto`, `--no-routing` or `--no-isolate` to override defaults. Serial isolated work uses the same dispatcher and shared pool; legacy in-place work reserves one shared unit around each agent call. Failed work remains recoverable; the default does not discard an existing recovery tree. Quality repair budgets and opt-in competing candidates retain their existing policies, and each simultaneous candidate consumes one worker unit.
138
138
 
139
- Integration retains an execution slot until its candidate lands. Yoke loop runners disable native delegation so it cannot multiply the default worker budget: Codex disables multi_agent; Claude disallows Agent, Task, TeamCreate and SendMessage; Gemini uses a separate temporary system-settings copy that disables experimental agents and its always-on investigator/help overrides. Existing Gemini system policy and system-default paths are preserved; unreadable or malformed policy blocks launch. Original settings are never overwritten. The temporary copy is removed on normal exit; forced process termination may leave a private temporary directory. Explicit competing candidate counts remain a separate opt-in workload.
139
+ Implementation slots and integration are separate lanes. A completed candidate frees its implementation slot, while its area and declared write scopes remain reserved until rebase, integrated-tree gates, commit and cleanup finish. The integration lane is serialized per project and also consumes one shared worker unit. Yoke loop runners disable native delegation so it cannot multiply the default worker budget: Codex disables multi_agent; Claude disallows Agent, Task, TeamCreate and SendMessage; Gemini uses a separate temporary system-settings copy that disables experimental agents and its always-on investigator/help overrides. Existing Gemini system policy and system-default paths are preserved; unreadable or malformed policy blocks launch. Original settings are never overwritten. The temporary copy is removed on normal exit; forced process termination may leave a private temporary directory.
140
+
141
+ See [parallel execution and safe task decomposition](parallel-execution.md) for the shared-pool limits, recovery steps, integration lane, task-split constraints and synthetic benchmark.
140
142
 
141
143
  ### Dashboard views
142
144
 
@@ -0,0 +1,130 @@
1
+ # Parallel execution
2
+
3
+ ## Continuous discovery
4
+
5
+ `yoke loop run . --explore --parallel=auto` applies the same scheduler and shared-pool limits to
6
+ newly discovered stories after each accepted backlog drains. Exploration itself is a single
7
+ read-only planning call. Accepted tasks need repository-file evidence, disjoint write scopes and
8
+ criterion-specific executable checks; implementation then uses the normal isolated workers and
9
+ integration lane. A no-op scan waits 30 minutes by default (`--explore-interval=1..1440`). Continuous
10
+ exploration is unbounded by default; `--explore-limit=12h|3d|2w` pauses it at a safe boundary after
11
+ the chosen duration and lets active workers finish their gates and integration.
12
+ `yoke loop pause .` stops at a safe boundary. See the [continuous exploration guide](CONTINUOUS-EXPLORATION.md)
13
+ for retries, stop detection, PRD history compaction and recovery.
14
+
15
+ Yoke parallelizes independent PRD stories. The scheduler respects declared dependencies, collision
16
+ areas and overlapping `writes` scopes. Each worker edits an isolated worktree; its result still has
17
+ to pass the integrated-tree gates before Yoke commits it.
18
+
19
+ ## Worker limits
20
+
21
+ The shared pool admits at most **three worker units by default** across Yoke loop processes running
22
+ under the same user account. Set `YOKE_MAX_PARALLEL_WORKERS` to an integer from 1 to 8 to change the
23
+ ceiling. For example:
24
+
25
+ ```powershell
26
+ $env:YOKE_MAX_PARALLEL_WORKERS = '6'
27
+ yoke loop run . --parallel=auto
28
+ ```
29
+
30
+ The environment setting is read when each Yoke process starts. Active and waiting pool records
31
+ advertise their configured ceiling; while those processes are alive, the smallest advertised limit
32
+ is used for new admissions. Lowering a limit does not cancel running work: Yoke waits for active
33
+ units to drain before admitting more. Set the same value for all long-lived Yoke processes when a
34
+ consistent ceiling is desired.
35
+
36
+ `--parallel=N` and `loop.parallel` accept values from 1 to 8. This is the per-project maximum for
37
+ simultaneous implementations; the shared pool can lower actual activity across projects. `auto`
38
+ uses up to the shared limit when every pending story has a nonempty `writes` declaration. Dependency
39
+ readiness, areas and overlapping scopes still decide which stories can start. If scopes are missing,
40
+ automatic execution uses one local implementation slot. Competing candidate runs spend one unit per
41
+ candidate, so `--candidates=3` requires a shared limit of at least three.
42
+
43
+ The pool keeps small user-local lease records under:
44
+
45
+ - Windows: `%LOCALAPPDATA%\Yoke\parallel-pool`
46
+ - Linux/macOS: `$XDG_STATE_HOME/Yoke/parallel-pool`, or `~/.yoke/Yoke/parallel-pool` when
47
+ `XDG_STATE_HOME` is unset
48
+
49
+ Records contain process identity, provider and role, worker weight, timestamps, and truncated hashes
50
+ of project and story identifiers. They do not contain prompts, file contents or absolute project
51
+ paths. They are coordinated through atomic file operations. The owner process must be known dead
52
+ before its lease is reclaimed; process identity and a 30-second stale window protect against PID
53
+ reuse and short interruptions. Admission fails closed if a record is malformed or ownership cannot
54
+ be checked. On a corruption error, stop all Yoke processes first, make a backup of the pool directory,
55
+ then inspect or move the stale pool aside before restarting. Never remove a record while its owner is
56
+ alive.
57
+
58
+ Adaptive routing can select a different provider after dispatch, so Yoke records provider use but
59
+ does not claim a hard per-provider cap. Native subagent delegation remains disabled inside loop
60
+ workers so nested agents cannot multiply the shared budget.
61
+
62
+ ## Implementation and integration lanes
63
+
64
+ `--parallel` counts implementation slots. A finished candidate releases its implementation unit
65
+ while it waits in the project's FIFO integration queue. The integration lane reserves one shared
66
+ unit while it rebases, reruns integrated-tree gates, commits, checks cleanliness and cleans up. Its
67
+ area and `writes` scopes remain reserved until that sequence ends, so overlapping or dependent work
68
+ cannot start early. Independent stories can use the freed implementation slot during integration.
69
+
70
+ The worker pool is shared across projects; each project's integration queue is serialized. A global
71
+ limit of three therefore caps combined implementation and integration work, even if several project
72
+ loops are active. Cancellation removes a waiting reservation and leaves existing recovery behavior
73
+ unchanged.
74
+
75
+ `yoke loop status` and the dashboard's **Now** view report local slots, workers waiting for capacity,
76
+ the shared active-unit count, integration activity and queued integrations. Event history records
77
+ implementation/integration resource waits, integration queue wait, integration duration and the
78
+ existing worker phases. The schedule forecast simulates dependency-aware implementation slots plus
79
+ one serial integration lane when integration measurements exist. Older runs without those events
80
+ remain visible as missing integration history; forecasts are empirical ranges, not deadlines, and do
81
+ not predict future contention from other projects.
82
+
83
+ ## Safe task decomposition
84
+
85
+ Make a preview with:
86
+
87
+ ```sh
88
+ yoke prd decompose . --story=API-1 --runner=codex
89
+ ```
90
+
91
+ The planner proposes two ordinary child stories and changes no PRD data. Applying requires the
92
+ explicit flag:
93
+
94
+ ```sh
95
+ yoke prd decompose . --story=API-1 --runner=codex --apply
96
+ ```
97
+
98
+ Yoke only accepts a split when the unfinished parent has at least four structured acceptance
99
+ criteria, at least two valid non-overlapping declared write scopes, and no shared `area`. The
100
+ proposal must allocate every original criterion and every declared scope exactly once, with 2–3
101
+ criteria per child and no overlap. Children preserve their exact criterion text and verification
102
+ commands, inherit upstream dependencies and agent affinity, and cannot depend on each other. A
103
+ parent with an area or too few scopes/criteria is refused; refine the task contract first or keep it
104
+ serial.
105
+
106
+ `--apply` acquires the project loop lock, rechecks hashes of the PRD and approved planning brief,
107
+ validates the resulting dependency graph, then atomically replaces the parent. Stories that depended
108
+ on the parent are updated to depend on both children. Task-specific assessments and quality
109
+ declarations are not copied to different work contracts: reassess with `yoke prd assess`, and add a
110
+ child-specific quality declaration before using competing candidates. A stale input or invalid
111
+ proposal is rejected without applying the split.
112
+
113
+ Write scopes remain advisory scheduling information, not filesystem permissions. A good split must
114
+ also keep each child independently verifiable and avoid hidden shared interfaces. Yoke does not
115
+ claim that splitting a task improves model quality or lowers token spend.
116
+
117
+ ## Synthetic efficiency benchmark
118
+
119
+ After building Yoke, run:
120
+
121
+ ```sh
122
+ npm run build
123
+ node bench/run-parallel-matrix.mjs
124
+ ```
125
+
126
+ The matrix uses the real dispatcher with a local deterministic runner and fixed implementation and
127
+ integration delays. It compares one, two and three implementation slots over a dependency chain,
128
+ independent scopes and conflicting scopes. It reports wall time, summed worker time, integration
129
+ queue wait, integration time, attempts and accepted stories. It makes no provider, token, quality or
130
+ large-repository claims.
@@ -0,0 +1,65 @@
1
+ # Parallel Task Efficiency Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Make Yoke's independent-task execution safer under load, easier to parallelize, less blocked by integration, and measurable by accepted result.
6
+
7
+ **Architecture:** Keep the PRD dependency graph and FIFO integration gate as the source of correctness. Add bounded cross-project worker admission, let PRD planning propose safe task splits that become ordinary stories, and separate implementation slots from the serialized integration lane while retaining scope reservations through integration. Extend event-based measurements and schedule forecasts to account for both lanes.
8
+
9
+ **Tech Stack:** TypeScript, Node.js filesystem/process APIs, Zod, YAML, current Yoke CLI and dashboard.
10
+
11
+ ---
12
+
13
+ ## File map
14
+
15
+ - `src/loop/resource-pool.ts`: user-local, cross-process weighted leases with FIFO fairness, owner identity, stale-owner recovery, and owner-checked release.
16
+ - `src/loop/run-command.ts`, `src/loop/parallel-command.ts`, `src/loop/dispatcher.ts`: bounded configuration, lease acquisition, lane scheduling, and lifecycle reporting.
17
+ - `src/retrofit/config.ts`, `src/cli.ts`, `src/prd/command.ts`, `src/prd/decompose.ts`, `src/loop/prd.ts`: bounded worker schema and safe PRD decomposition command.
18
+ - `src/observability/events.ts`, `src/loop/reporter.ts`, `src/estimation/schedule.ts`, `src/dashboard/server.ts`, `src/dashboard/panels.ts`: stage and wait measurements, resource status, and two-lane ETA.
19
+ - `bench/run-parallel-matrix.mjs`, `bench/fixtures/parallel-work/`: repeatable synthetic serial/parallel comparisons with fixed work and no paid model calls.
20
+ - `README.md`, `docs/VERIFIED-PROJECTS.md`, `docs/parallel-execution.md`, `CHANGELOG.md`: user-facing defaults, limits, recovery, and validation boundaries.
21
+
22
+ ## Task 1: Bound shared execution capacity
23
+
24
+ - [x] Cap explicit and configured per-project concurrency at eight; reject larger values with a clear limit.
25
+ - [x] Add a user-local shared pool that coordinates concurrent Yoke loop processes across projects and hosts no model prompts or project contents.
26
+ - [x] Track total active worker weight. Default to three total worker units; allow a bounded override through `YOKE_MAX_PARALLEL_WORKERS`. Provider-specific hard limits are not reliable while adaptive routing can change the selected backend after dispatch, so provider use is recorded as evidence instead of guessed.
27
+ - [x] Implement weighted FIFO admission with bounded overtakes, cancellable waits, owner process identity, atomic records, stale-owner recovery, and token-checked release. Fail closed on corrupt ownership state or unsupported atomic filesystem operations.
28
+ - [x] Reserve candidate races by the number of simultaneous candidate workers. Release implementation permits before integration and acquire a separate permit for integration/review.
29
+ - [x] Keep `auto` conservative at the shared limit only when all pending tasks declare write scopes; the shared pool may lower simultaneous work across projects.
30
+
31
+ ## Task 2: Improve task decomposition safely
32
+
33
+ - [x] Add `yoke prd decompose --story=<id>` to request a bounded child-story proposal from the configured planner.
34
+ - [x] Require structured executable acceptance criteria and nonempty, valid, pairwise-disjoint write scopes for each child; preserve the original criteria exactly as a complete union.
35
+ - [x] Keep preview as the default. `--apply` acquires the project lock, rechecks PRD/brief hashes, replaces the parent with child tasks, and rewrites downstream dependencies to require every child.
36
+ - [x] Validate IDs, story schema, dependency references, and cycles before the atomic write. Stale assessment bindings are removed. Planner output never becomes executable shell text.
37
+ - [x] Include the proposal format and refusal cases in CLI help and documentation.
38
+
39
+ ## Task 3: Pipeline implementation and integration
40
+
41
+ - [x] Count only active implementations against implementation slots; keep completed candidates in the serial integration lane without blocking unrelated, dependency-ready work.
42
+ - [x] Keep their areas and declared write scopes reserved until integration finishes, so dependent or overlapping stories cannot start early.
43
+ - [x] Keep the existing rebase, integrated-tree gates, commit, post-integration cleanliness check, cancellation, and cleanup ordering.
44
+ - [x] Report implementation activity, global-pool wait, integration queue wait, and integration duration separately in status and immutable events.
45
+
46
+ ## Task 4: Measure end-to-end efficiency
47
+
48
+ - [x] Extend event aggregation with accepted-result wall time, implementation work, queue wait, integration time, attempts, reported usage, and measurement coverage.
49
+ - [x] Update schedule simulation to model weighted implementation workers and one serialized integration lane; preserve empirical ranges and unknowns.
50
+ - [x] Show local/global capacity, resource waits, and lane utilization in CLI/dashboard status.
51
+ - [x] Add a synthetic benchmark matrix comparing one, two, and three workers over serial chains, independent scopes, and conflicting scopes. Record wall time, worker time, integration wait, total attempts, and accepted results. The fixture uses a deterministic local runner; no provider costs or model-quality claims are implied.
52
+
53
+ ## Task 5: Document operation and limits
54
+
55
+ - [x] Document bounded overrides, global environment settings, pool location/recovery, task-split preview/application, pipeline behavior, and telemetry coverage.
56
+ - [x] Add a dated unreleased changelog entry; do not change package versions, tag, publish, or claim external benchmark results.
57
+ - [x] Run TypeScript build and release documentation checks. No tests are added or run in this execution.
58
+
59
+ **Execution record:** TypeScript build and `docs:check` passed on the first run. A later check retry could not enumerate tests because Vitest's `list --json` command ran out of WebAssembly memory; no tests were executed. The synthetic matrix is recorded in `bench/RESULTS.md`.
60
+
61
+ ## Self-review
62
+
63
+ - Coverage: hard concurrency bounds, shared resource accounting, safe task decomposition, integration overlap, measurement, estimation, dashboard, benchmark harness, and documentation each have an implementation task.
64
+ - Safety: PRD writes remain lock-protected and atomic; acceptance and dependency validation remain mandatory; write scopes stay advisory scheduling inputs; pool leases are owner-bound and never reclaimed from a live process.
65
+ - Compatibility: existing serial mode and existing PRDs remain valid; new decomposition and resource overrides are opt-in or bounded defaults; no release/version change is part of this task.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yoke",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "Cross-agent coding harness for eight supported CLIs: curated skill canon, mechanical safety gates, autonomous loop with proof artifacts. CLI: npm i -g @hecer/yoke",
5
5
  "contextFileName": "GEMINI-EXTENSION.md"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hecer/yoke",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "One harness, eight agents, zero trust in \"done\" — cross-agent coding harness for Claude Code, Codex CLI, Gemini CLI, Qwen Code, OpenCode, Kilo, Pi and Hermes: one skill canon, mechanical safety gates, an autonomous loop with screenshot/video proofs.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,6 +21,7 @@
21
21
  "bench/run.mjs",
22
22
  "bench/run-large.mjs",
23
23
  "bench/run-matrix.mjs",
24
+ "bench/run-parallel-matrix.mjs",
24
25
  "bench/analyze-routing-study.mjs",
25
26
  "bench/fixtures",
26
27
  "bench/results",