rl-workspaces 0.5.0 → 0.6.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.
package/README.md CHANGED
@@ -18,7 +18,7 @@ Install from npm:
18
18
  npm install --global rl-workspaces
19
19
  ```
20
20
 
21
- The first npm release is pending; see Development below to build the unpublished version.
21
+ See Development below to build and try unpublished changes.
22
22
 
23
23
  Add one line to your shell configuration, then open a new terminal:
24
24
 
@@ -173,21 +173,14 @@ deleted automatically.
173
173
 
174
174
  ## Finish a feature
175
175
 
176
+ Use Git directly to inspect changes, commit, rebase, or squash feature history.
177
+ RL handles merging across checkouts and removing the finished workspace:
178
+
176
179
  ```sh
177
- rl git diff --base origin/test -- --stat
178
- rl git log --base origin/test -- --graph
179
- rl git commit -m "Add login" # staged changes
180
- rl git commit --all -m "Fix login" # tracked changes; untracked files require git add
181
- rl git rebase --base origin/test
182
- rl git squash --base origin/test -m "Add login"
183
180
  rl git merge test --dry-run
184
181
  rl git merge test --cleanup
185
182
  ```
186
183
 
187
- Git mutation commands also accept `--dry-run`. Rebase and squash require a clean
188
- workspace. Squash preserves the original HEAD under a printed
189
- `refs/rl/backups/<UUID>` ref; it rewrites local feature history without pushing.
190
-
191
184
  Merge targets a checked-out local branch in the main or a managed checkout.
192
185
  It requires clean source and target workspaces and defaults to fast-forward only.
193
186
  For an explicit squash merge, use `rl git merge test --squash -m "Add login"`.
@@ -388,176 +381,215 @@ and [Claude hooks](https://code.claude.com/docs/en/hooks) contracts.
388
381
 
389
382
  ## Session-driven agent workflows
390
383
 
391
- Your current Codex or Claude session owns its native subagents. RL supplies
392
- reusable roles, workflow dependencies, trigger rules, policies and durable run
393
- records. RL never launches a provider CLI, model API or check process for a
394
- workflow. The parent session claims ready steps, creates native children and
395
- reports their evidence; it runs configured checks itself.
384
+ An adopted workspace has a built-in `writer-reviewer-dry` workflow immediately,
385
+ without creating configuration files. Your current Codex or Claude session
386
+ creates and controls its native children. RL supplies their editable roles,
387
+ handoff rules, review policy and durable run records. RL never launches a
388
+ provider CLI, model API or check process for a workflow.
389
+
390
+ The default team starts together and stays available for the task:
391
+
392
+ - **Writer** implements scoped changes. Before adding a function, it asks DRY
393
+ about existing implementations and waits for the answer. It submits stable
394
+ file groups to the reviewer, then fixes and resubmits rejected work.
395
+ - **Reviewer** stays read-only, reviews writer checkpoints and returns a rating
396
+ with evidence and actionable feedback. On suspected duplication it asks the
397
+ same DRY agent before returning its review.
398
+ - **DRY** stays read-only and serves both peers, returning paths, symbols,
399
+ behavioral differences and reuse options, or explicitly reporting that no
400
+ suitable implementation was found.
401
+
402
+ Submitted files stay frozen while awaiting review; the writer can work on
403
+ unrelated files meanwhile. Ratings apply to saved file contents and staged
404
+ versions. RL rejects changed or superseded checkpoints and requires current
405
+ accepted reviews for the writer's changes before completion. The defaults are
406
+ **90/100** and at most **five review rounds** per file group. Required fixes
407
+ and incomplete coverage block acceptance regardless of rating. Pending check
408
+ requests or routing leads must be resolved before a checkpoint can be accepted.
396
409
 
397
410
  ```sh
398
- rl workflow init # configure this adopted workspace and refresh hooks
399
- rl agent add auth --instructions auth-review.md --description "Authentication reviewer"
411
+ rl workflow context --json # discover active definitions and their source
400
412
  rl agent list
401
- rl agent show auth
402
- rl workflow add auth-review --file auth-workflow.json
403
- rl workflow set auth-review --file auth-workflow.json
404
- rl workflow context --json # discover definitions and trigger rules
405
- rl workflow status # latest saved run
406
- rl workflow metrics
413
+ rl agent show writer
407
414
  rl policy show review
415
+ rl workflow init # write editable copies and refresh workspace hooks
416
+ rl agent set writer --instructions writer.md
417
+ rl workflow set writer-reviewer-dry --file workflow.json --default
418
+ rl workflow status # latest saved run and checkpoint ratings
419
+ rl workflow metrics
408
420
  ```
409
421
 
410
- Configuration stays in this worktree:
422
+ Export a definition before editing it:
423
+ `rl workflow show writer-reviewer-dry --json > workflow.json`.
424
+ `agent set --instructions` preserves the profile's other settings. Complete
425
+ profiles can be saved with `rl agent set writer --file profile.json`.
426
+ Use `rl agent add` and `rl workflow add` to create additional definitions.
427
+
428
+ Configuration stays in this worktree. The three concerns remain separate:
411
429
 
412
430
  | File | Owns |
413
431
  | --- | --- |
414
- | `.rl/agents.json` | Roles: description, instructions, optional model/reasoning and `access` preferences; provider defaults to `inherit` |
415
- | `.rl/agent-workflows.json` | Trigger rules, ordered/parallel steps, concurrency, retry budget, report deadlines and selected policy |
416
- | `.rl/policies.json` | Criteria, severity deduction weights and acceptance requirements |
432
+ | `.rl/agents.json` | Roles: description, instructions, optional model/reasoning and access preferences; provider defaults to inherit |
433
+ | `.rl/agent-workflows.json` | Default workflow, triggers, dependencies, concurrency, retries, deadlines, collaboration routes and review rounds |
434
+ | `.rl/policies.json` | Review criteria, rating scale/threshold, severity deduction weights and acceptance requirements |
417
435
 
418
436
  Each file has `"version": 1` and a named `agents`, `workflows` or `policies` map.
419
- `rl agent add/set <name> --file profile.json` also saves complete profiles.
420
- Missing files use preset definitions for discovery, but automatic trigger
421
- handling requires at least one explicit configuration file. Existing legacy
422
- provider preferences remain readable; they never authorize starting a separate
423
- Codex/Claude process. Native model and reasoning options are applied by the
424
- parent where supported; unavailable settings must be reported explicitly.
425
-
426
- Session-start hooks detect configuration and teach the parent the protocol.
427
- Prompt hooks refresh it after configuration changes, including after compaction.
428
- Tool hooks deliver matching requests as the parent works. Before-edit/tool rules
429
- deny the pending tool until their request completes or is explicitly dismissed
430
- (or the user cancels its run), so the parent can delegate before retrying.
431
- Workflow coordination tools are excluded from this gate. The preset queues
432
- `triple-review` before finishing changed work: behavior/security, reuse/complexity
433
- and implementation-quality roles, all read-only. Child hooks do not recursively
434
- queue workflows. Normal session resume and task checkpoints remain independent.
435
-
436
- For example, save the following as `auth-workflow.json`, then add it using the
437
- command above:
437
+ The workflow file also accepts `"default": "writer-reviewer-dry"`; use
438
+ `workflow add/set --default` to select a different default. Existing explicit
439
+ configurations are preserved, including workspaces with partial legacy settings.
440
+ A missing file uses built-in definitions, which
441
+ are active for automatic triggers too. Run `workflow init` only when you want
442
+ editable copies and none of the three files exists yet.
443
+
444
+ The default workflow's `collaboration` section is editable:
438
445
 
439
446
  ```json
440
447
  {
441
- "description": "Review authentication changes before finishing",
442
- "policy": "review",
443
- "concurrency": 2,
444
- "retries": 1,
445
- "timeoutSeconds": 600,
446
- "triggers": [
447
- { "event": "before_edit", "tools": ["Edit", "apply_patch"], "paths": ["src/auth/**"] },
448
- { "event": "before_finish", "changes": true },
449
- { "event": "task_planned" }
450
- ],
451
- "steps": [
452
- { "id": "types", "command": ["pnpm", "tsc", "--noEmit"], "after": [] },
453
- { "id": "auth", "agent": "auth", "after": ["types"] },
454
- { "id": "quality", "agent": "quality", "after": ["types"] }
448
+ "writer": "writer",
449
+ "reviewer": "reviewer",
450
+ "dry": "dry",
451
+ "maxRounds": 5,
452
+ "rules": [
453
+ { "from": "writer", "event": "new_function", "to": "dry", "required": true },
454
+ { "from": "reviewer", "event": "suspected_duplicate", "to": "dry", "required": true }
455
455
  ]
456
456
  }
457
457
  ```
458
458
 
459
+ These names refer to step IDs. All three collaboration steps must be ready at
460
+ startup with concurrency at least three; reviewer and DRY must be read-only.
461
+ Change routes, requirements, review rounds, triggers and profiles as needed.
462
+ Required gates support writer `new_function` and reviewer `suspected_duplicate`;
463
+ additional event routes can be added with `required: false` for optional messaging.
464
+ Other workflows can use sequential/parallel dependencies and parent-run command
465
+ steps without collaboration. A writing stage runs exclusively in those workflows;
466
+ explicit dependency results are shared and independent reviews remain isolated.
467
+
468
+ The separate policy has a `rating` object with `min`, `max`, `minimum` and
469
+ `instructions`. Agents use that rubric to rate checkpoints. RL also calculates
470
+ a separate score from findings: the default deducts 50/20/10/2 for
471
+ critical/high/medium/low findings, deduplicates exact file/line/root-cause matches,
472
+ and blocks readiness on required fixes or coverage gaps. `rl workflow score`
473
+ rescores saved evidence without agent calls. Native model/reasoning settings are
474
+ preferences applied by the parent where supported; unsupported settings must be
475
+ reported. Provider preferences never authorize another provider process.
476
+
477
+ Session-start hooks identify the active configuration and teach the parent the
478
+ protocol. Prompt hooks refresh it after configuration changes and compaction.
479
+ The default queues the team at the parent's `task_planned` coding milestone or
480
+ before its first edit. Before-edit/tool rules deny the pending tool until their
481
+ request completes, is explicitly dismissed or its run is cancelled. Coordination
482
+ tools are excluded from this gate. Child hooks do not recursively queue teams.
483
+ Normal session resume and task checkpoints remain independent.
484
+
459
485
  Automatic events are `session_start`, `prompt`, `before_edit`, `after_edit`,
460
- `before_tool`, `after_tool`, and `before_finish`. Edit events recognize
486
+ `before_tool`, `after_tool` and `before_finish`. Edit events recognize
461
487
  Edit/Write/MultiEdit/apply_patch; other tools, including shell commands, use the
462
488
  tool events. `tools` matches exact hook tool names; `paths` matches workspace
463
- relative file paths with `*` (one path segment) and `**` (across segments).
464
- Path filtering uses structured edit paths/patch headers, not guesses about shell
465
- commands. `changes: true` requires changes in the locally available comparison
466
- scope. Semantic events such as `task_planned` are explicitly reported by the
467
- parent, since RL cannot observe private reasoning. All conditions on a rule
468
- must match; multiple rules are alternatives.
469
-
470
- Matching events queue requests for that parent conversation only. Identical
489
+ relative paths with `*` and `**`. Path filtering reads structured edit paths
490
+ and patch headers, without guessing about shell commands. `changes: true`
491
+ requires changes in the local comparison scope. Semantic events such as
492
+ `task_planned` are reported by the parent, since RL cannot observe private
493
+ reasoning. All conditions on a rule must match; multiple rules are alternatives.
494
+
495
+ Matching requests belong to that parent conversation only. Identical
471
496
  scope/configuration events are deduplicated; newer changes coalesce into an
472
- unclaimed request. Before-finish hooks can continue the turn once with the
473
- request, and guard against repeated Stop-hook loops. They cannot force a client
474
- to offer or use native delegation. If unavailable or disallowed by current
475
- instructions, the session must dismiss the request with its concrete reason
476
- and report that limitation. Current permissions and workspace boundaries apply
477
- to every child. Read-only roles receive instructions to remain read-only; host
478
- permissions are enforced by the host, not by RL.
497
+ unclaimed request. Before-finish hooks can continue the turn once, guarding
498
+ against repeated Stop-hook loops. If native delegation is unavailable or
499
+ disallowed, the session must dismiss the request with its concrete reason and
500
+ report that limitation. Current permissions and workspace boundaries apply to
501
+ every child. Host permissions are enforced by the host.
479
502
 
480
503
  The MCP server (`rl agent mcp`) exposes:
481
504
 
482
- 1. `rl_workflow_context`: discover roles, workflows, triggers and policies.
483
- 2. `rl_workflow_pending`: read this parent session's queued requests.
484
- 3. `rl_workflow_event`: report an explicit milestone and match trigger rules.
485
- 4. `rl_workflow_start`: create a session-owned run, optionally from a request ID.
486
- 5. `rl_workflow_claim`: atomically claim one ready stage and receive its prompt,
487
- dependencies, scope path, output schema and native settings.
488
- 6. `rl_workflow_report`: submit the claim token and child findings, an actual
489
- check result, or a failure. RL validates the report and calculates the score.
490
- 7. `rl_workflow_dismiss`: decline a queued request with a recorded reason.
491
-
492
- Supply `agent` and the parent conversation's full `sessionId`; Codex may infer
493
- its ID from the environment, while Claude supplies its UUID explicitly. Observed
494
- Codex `thr_` IDs also coordinate workflows, but never enter UUID-based resumable
495
- session history. These are
496
- coordination identities within the local workspace, not an authentication
497
- boundary against a process that already has access to its state files.
498
- CLI equivalents are available when the session has no MCP connection:
505
+ | Tool | Purpose |
506
+ | --- | --- |
507
+ | `rl_workflow_context` | Discover roles, workflows, triggers, policies and configuration source |
508
+ | `rl_workflow_pending` | Read this parent's queued requests |
509
+ | `rl_workflow_event` | Report a milestone and match trigger rules |
510
+ | `rl_workflow_start` | Prepare a session-owned run, optionally from a request |
511
+ | `rl_workflow_claim` | Claim a ready step and receive its prompt, scope, result schema and native settings |
512
+ | `rl_workflow_report` | Return final evidence, actual check output or failure with the claim token |
513
+ | `rl_workflow_dismiss` | Decline a queued request with a recorded reason |
514
+ | `rl_workflow_bind` | Bind a claimed role to its unique native child ID |
515
+ | `rl_workflow_inbox` | Read that role's consultations, submissions, ratings and peer handles |
516
+ | `rl_workflow_consult` | Ask an existing peer through a configured route |
517
+ | `rl_workflow_answer` | Answer a consultation addressed to that role |
518
+ | `rl_workflow_submit` | Submit a writer checkpoint and declare new functions as path#function subjects |
519
+ | `rl_workflow_review` | Return a rating, rationale, evidence and declared duplicate suspicions |
520
+
521
+ The parent claims, spawns and binds all three peers, then announces readiness.
522
+ Handoff tools return a `notify` destination with the peer's native handle. The
523
+ caller delivers it through native messaging or asks the parent to relay it.
524
+ RL persists the handoff; it cannot wake native children on its own. Peers use
525
+ native wait/messaging tools while idle. Finish the writer first, then reviewer,
526
+ then DRY, reporting final evidence through `rl_workflow_report`.
527
+
528
+ RL verifies answered consultations for declared new functions and duplicate
529
+ suspicions. Identifying those semantic events and declaring them honestly is
530
+ the agents' responsibility; RL cannot independently prove that every new
531
+ function was declared.
532
+
533
+ Supply `agent` and the parent's full `sessionId`; Codex may infer its ID from
534
+ the environment, while Claude supplies its UUID explicitly. Observed Codex
535
+ `thr_` IDs also coordinate workflows, but never enter UUID-based resumable
536
+ history. These are local coordination identities, not an authentication boundary
537
+ against a process that already has access to the state files.
538
+
539
+ CLI equivalents are available without an MCP connection:
499
540
 
500
541
  ```sh
501
542
  rl workflow pending --agent claude --session <UUID>
502
- rl workflow run --request <request-UUID> --agent claude --session <UUID>
503
543
  rl workflow event --file event.json --agent claude --session <UUID>
504
- rl workflow run auth-review --base origin/test --agent claude --session <UUID>
505
- rl workflow claim <run> --agent claude --session <UUID>
544
+ rl workflow run --request <request-UUID> --agent claude --session <UUID>
545
+ rl workflow claim <run> --step writer --agent claude --session <UUID>
546
+ rl workflow bind <run> --file binding.json --agent claude --session <UUID>
547
+ rl workflow inbox <run> --step writer --claim <token> --agent claude --session <UUID>
506
548
  rl workflow report <run> --file report.json --agent claude --session <UUID>
507
549
  ```
508
550
 
509
- An event file contains `{ "event": "task_planned" }`; report files contain
510
- `step`, `claim`, and `result` (the returned schema), or `check` with actual
511
- `stdout`, `stderr`, `exitCode`, or `error`. Reports may include `childId` and
512
- parent-reported token/cost usage. Commands and reports return data for the parent;
513
- `workflow run` prepares work and returns without spawning agents. `--dry-run`
514
- previews scope without creating a run.
515
-
516
- Dependencies and concurrency are enforced when stages are claimed. Explicit
517
- predecessor results are supplied to dependent agents; independent roles receive
518
- no peer reports. A failed check blocks dependents. Reported agent failures may
519
- be retried within the configured budget. Routing leads receive one focused
520
- follow-up by their owning role. Further leads remain coverage limitations.
551
+ An event file contains `{ "event": "task_planned" }`. Binding files contain
552
+ `step`, `claim` and `childId`. CLI equivalents for `consult`, `answer`,
553
+ `submit` and `review` take `--file` with the same tool fields. Each role's
554
+ prompt supplies its claim token and parent conversation identity. Final reports
555
+ contain `step`, `claim` and `result` (the supplied schema), or an actual
556
+ `check` result or `error`. Reports may include native `childId` and token/cost
557
+ usage. `workflow run` prepares work without spawning agents; `--dry-run`
558
+ previews the scope without creating a run.
521
559
 
522
560
  Review scope includes committed branch changes from the merge-base, staged,
523
- unstaged and non-ignored untracked changes, capped at 4 MiB. The selected base
524
- uses local refs, without fetching; event detection uses HEAD if the saved base
525
- is not locally resolvable. RL checks fingerprints before claims and reports.
526
- Unexpected changed scope requires a new run. Roles default to read-only. A profile with `"access": "workspace-write"` may
527
- implement its assigned changes within the host's existing permissions. Writing
528
- stages run exclusively. RL refreshes scope after the writer reports, so later
529
- reviewers inspect its changes. Earlier checks/reviews remain historical; they
530
- cannot justify readiness for changed code unless refreshed after writing. Place
531
- final validation after the writer in the workflow. Unexpected edits during a
532
- read-only stage still invalidate its result.
533
-
534
- Policies remain separate. The default deducts 50/20/10/2 for
535
- critical/high/medium/low findings, deduplicates exact file/line/root-cause matches,
536
- and blocks readiness on required fixes or coverage gaps. Agents return evidence
537
- without assigning scores. `rl workflow score --policy review` rescores recorded
538
- findings and preserves assessment history without agent calls.
539
-
540
- `workflow pause` stops new claims but accepts reports from already claimed
541
- children. The parent owns child cancellation and must stop its native agents.
542
- After existing children have reported, that parent can `workflow resume` using
543
- the saved configuration. Cancellation rejects further results and requires a
544
- new run. Neither command sends process signals. Runs retain their parent UUID,
545
- claim tokens, native child IDs, evidence, scope and policy assessments under the
546
- current instance's `workflow-runs/` directory. RL measures claim-to-report elapsed
547
- time; token/cost usage is parent-reported and missing totals remain unknown.
561
+ unstaged and non-ignored untracked changes, capped at 4 MiB. Bases use local refs
562
+ without fetching; event detection falls back to HEAD if the saved base is
563
+ unresolvable. Generic workflows validate whole-scope fingerprints; collaborative
564
+ reviews validate each saved file group while implementation continues. Initial
565
+ unrelated dirty files need no submission unless changed during the run. RL
566
+ refreshes the whole scope when the writer closes and verifies it for remaining
567
+ final reports. Earlier checks/reviews in generic workflows remain historical
568
+ after writing; place final validation after the writer. Failed checks block
569
+ dependents. Reported failures can be retried within the configured budget.
570
+ Generic routing leads receive one focused follow-up; further leads remain
571
+ limitations. Collaborative peers handle consultations without replacement stages.
572
+
573
+ `workflow pause` stops new claims and submissions but lets claimed children
574
+ report and finish pending answers/reviews. The parent owns child cancellation.
575
+ `workflow resume` lets collaborative peers continue with the same claims and
576
+ native handles. Generic workflows require running children to report first.
577
+ Cancellation rejects further results and requires a new run. Neither command
578
+ sends process signals. Run records retain the parent identity, native IDs,
579
+ claims, evidence, checkpoints and assessments under this instance's
580
+ `workflow-runs/` directory. RL measures claim-to-report elapsed time; token/cost
581
+ usage is parent-reported and missing totals remain unknown.
548
582
 
549
583
  After upgrading existing workspaces, run `rl doctor --repair` to add tool hooks,
550
- and restart/review hooks as required by your host. Native hook integration follows
551
- the [Codex hooks](https://learn.chatgpt.com/docs/hooks) and
552
- [Claude hooks](https://code.claude.com/docs/en/hooks) contracts. Automated tests
553
- exercise hook payloads and MCP/CLI coordination; they do not certify live model
554
- compliance or native delegation availability in every client.
584
+ and restart/review hooks as required by your host. Automated tests exercise
585
+ hook payloads and MCP/CLI coordination; they do not certify live model compliance
586
+ or native delegation availability in every client.
555
587
 
556
588
  ## Let agents use notes through MCP
557
589
 
558
590
  `rl agent mcp` serves workspace-scoped tools over stdio: `rl_status`, `rl_context`,
559
591
  `rl_progress`, `rl_context_append`, `rl_progress_append`, `rl_session_save`,
560
- `rl_task_pause`, and the seven `rl_workflow_*` coordination tools described above.
592
+ `rl_task_pause`, and the thirteen `rl_workflow_*` coordination tools described above.
561
593
  `rl_task_pause` accepts the handoff JSON described above and atomically saves
562
594
  the session and task checkpoint. `rl_status` includes task state and handoff history.
563
595
  `rl_status` automatically discovers Codex sessions for this workspace.
@@ -672,7 +704,7 @@ keep one primary spelling for each operation:
672
704
 
673
705
  | Previous command | Primary command |
674
706
  | --- | --- |
675
- | `rl step commit/rebase/squash`, `rl diff/log/merge` | `rl git commit/rebase/squash/diff/log/merge` |
707
+ | `rl merge` | `rl git merge` |
676
708
  | `rl context/progress show/set/append/path` | `rl notes show/set/append/path context/progress` |
677
709
  | `rl summary` | `rl notes summary` |
678
710
  | `rl session list/save/add` | `rl agent sessions/save` |
@@ -1,45 +1,70 @@
1
1
  export const PRESET = {
2
+ defaultWorkflow: "writer-reviewer-dry",
2
3
  agents: {
3
- behavior: {
4
+ writer: {
4
5
  provider: "inherit",
5
6
  reasoning: "high",
6
- description: "Runtime correctness, user journeys, persistence and security",
7
- instructions: "Investigate supported end-to-end user journeys: input, validation, serialization, persistence, queries, subscriptions, caches, rendering and downstream consumers. Own runtime bugs, regressions, concurrency, error behavior, tenant isolation and demonstrable runtime performance failures. Check current code and intended behavior; history and old comments are leads, not proof. Distinguish current defects from fixed regressions, intentional boundaries and unverified hypotheses. Findings need prerequisites, reproducible steps, expected versus actual behavior, and evidence; label code-inferred reproductions. Do not review type hygiene without runtime impact, test design, debug cleanup, duplication or structural simplification. Attach regression advice to the corresponding bug rather than filing duplicate missing-test findings.",
7
+ access: "workspace-write",
8
+ description: "Implement scoped changes and submit review checkpoints",
9
+ instructions: "Own implementation in the assigned workspace and files. You are not alone: preserve other people's work and coordinate changes with the parent. Start alongside the reviewer and DRY peer; do not spawn replacement reviewers or searchers. Follow the workflow's configured consultation rules. By default, before adding any new function consult the existing DRY peer using event new_function and a precise subject such as src/file.ts#functionName, then wait for its answer and reuse existing behavior when appropriate. Submit bounded, stable file groups to the reviewer with all newFunctions declared. Freeze submitted files while a review is pending; you may continue on unrelated files. Address feedback and resubmit until the configured rating and policy requirements pass. Report actual checks, remaining work and limitations honestly. Do not close your stage until current changes have accepted reviews and your consultations are answered.",
8
10
  },
9
- reuse: {
11
+ reviewer: {
10
12
  provider: "inherit",
11
13
  reasoning: "high",
12
- description: "Reuse, duplicated behavior and avoidable complexity",
13
- instructions: "Search the repository for existing components, hooks, services, utilities, dependencies and alternate implementations before judging a new capability. Own duplicated business behavior, unnecessary abstractions/features, redundant state and misplaced responsibilities with concrete maintenance cost. Prefer reuse, extension, composition, then a small focused implementation. Cite both the reviewed implementation and existing counterpart, the behavioral overlap and a viable smaller solution. For pure simplification, name removable machinery and explain how requirements are preserved. Small duplication and different presentations can be justified. Do not investigate runtime/security bugs, type-only duplication, logging cleanup or test quality. Labels such as DRY, YAGNI and code smell are not evidence.",
14
+ access: "read-only",
15
+ description: "Review writer submissions and return evidence-backed ratings",
16
+ instructions: "Stay read-only and available alongside the writer and DRY peer. Review each writer submission against its saved checkpoint, surrounding source, intended behavior and the separate policy. Assess correctness, authorization, persistence, concurrency, type contracts and meaningful validation. Return a rating and rationale using the configured rating scale, with structured findings, coverage limitations and required fixes. Follow the workflow's configured consultation rules. By default, if you suspect duplication consult the existing DRY peer using event suspected_duplicate and a precise subject before returning the review. Declare every duplicateSuspicions subject. Incorporate its evidence rather than treating similarity as proof. Send actionable feedback to the writer, re-review resubmissions, and never equate missing evidence with a clean result. Do not edit code, silently replace peers, or finish before the writer and all submitted work are settled.",
14
17
  },
15
- quality: {
18
+ dry: {
16
19
  provider: "inherit",
17
20
  reasoning: "high",
18
- description: "Type contracts, static checks, debug leftovers and test quality",
19
- instructions: "Own unjustified any, casts and suppressions, overly broad contracts, failure to reuse applicable types, accidental debug leftovers, attributable static-check failures, and tests that cannot protect their claimed behavior. Distinguish safe unknown narrowing and justified dependency escape hatches from weakened checking. Preserve intentional operational logging. For test findings name a specific material contract and a useful assertion, not a coverage percentage. Do not review runtime correctness/security, architecture or duplicated business behavior. A test failure is not automatically a product bug. Request configured checks from the coordinator instead of running duplicate commands. Omit style preferences and broad cleanup of existing code.",
21
+ access: "read-only",
22
+ description: "Shared reuse and duplication specialist for writer and reviewer",
23
+ instructions: "Stay read-only and available as the single DRY peer for both writer and reviewer. You may map relevant existing utilities while waiting for requests. Answer new_function consultations from the writer before it adds behavior, and suspected_duplicate consultations from the reviewer before it returns a rating. Search current source for existing functions, components, services, types and dependencies. Cite concrete paths/symbols, behavioral overlap, relevant differences and a viable reuse approach; state explicitly when no suitable implementation was found or coverage is incomplete. Small or superficial similarity alone is not evidence of harmful duplication. Respond to the requesting peer through its consultation record; do not edit files, assign ratings, create more agents, or close while requests or either peer remain active.",
20
24
  },
21
25
  },
22
26
  policies: {
23
27
  review: {
24
- instructions: "Report only evidence-backed problems caused or materially worsened by the reviewed changes. Separate required fixes from optional quick wins with reasons. Critical means security exposure, destructive data loss or outage; high means broken core behavior or substantial structural cost; medium means a contained defect or worthwhile required quality fix; low means an optional quick win. Do not block on stylistic preference, tiny duplication, justified type escape hatches, intentional operational logging, speculative flexibility or generic demands for tests. Missing dependencies, unverified critical paths and unresolved material questions are coverage limitations. Do not invent findings or treat a score as a probability of correctness.",
28
+ instructions: "Report evidence-backed defects caused or materially worsened by the submitted work. Separate required fixes from optional improvements, and explain prerequisites, expected behavior and observed or inferred failures. Evaluate reuse against concrete alternatives. Avoid style-only blockers and invented findings. Missing checks, dependencies and unverified material paths are coverage limitations. Review ratings are judgments supported by evidence; RL's policy score is calculated separately and is not a probability of correctness.",
25
29
  weights: { critical: 50, high: 20, medium: 10, low: 2 },
26
30
  minimumScore: 0,
27
31
  blockRequired: true,
32
+ rating: {
33
+ min: 0,
34
+ max: 100,
35
+ minimum: 90,
36
+ instructions: "Rate each submission from 0 to 100. 90–100 means ready with verified material behavior and no required fixes; 70–89 needs contained corrections or validation; below 70 needs substantial corrections. Explain the rating and uncertainty. A high rating never overrides required fixes, failed checks or incomplete coverage.",
37
+ },
28
38
  },
29
39
  },
30
40
  workflows: {
31
- "triple-review": {
32
- description: "Three independent reviewers, owner follow-ups and a policy-based verdict",
41
+ "writer-reviewer-dry": {
42
+ description: "Parallel writer, reviewer and DRY peers with rated review checkpoints",
33
43
  policy: "review",
34
44
  concurrency: 3,
35
45
  retries: 1,
36
- timeoutSeconds: 600,
37
- triggers: [{ event: "before_finish", changes: true }],
46
+ timeoutSeconds: 3600,
47
+ triggers: [{ event: "task_planned" }, { event: "before_edit" }],
38
48
  steps: [
39
- { id: "behavior", agent: "behavior", after: [] },
40
- { id: "reuse", agent: "reuse", after: [] },
41
- { id: "quality", agent: "quality", after: [] },
49
+ { id: "writer", agent: "writer", after: [] },
50
+ { id: "reviewer", agent: "reviewer", after: [] },
51
+ { id: "dry", agent: "dry", after: [] },
42
52
  ],
53
+ collaboration: {
54
+ writer: "writer",
55
+ reviewer: "reviewer",
56
+ dry: "dry",
57
+ maxRounds: 5,
58
+ rules: [
59
+ { from: "writer", event: "new_function", to: "dry", required: true },
60
+ {
61
+ from: "reviewer",
62
+ event: "suspected_duplicate",
63
+ to: "dry",
64
+ required: true,
65
+ },
66
+ ],
67
+ },
43
68
  },
44
69
  },
45
70
  };
@@ -6,6 +6,7 @@ import { readJsonObject } from "./json.js";
6
6
  import { validateAutomation, } from "./automation-config.js";
7
7
  import { evaluate, validateResult, } from "./review-policy.js";
8
8
  import { agentAdapter } from "./agent-registry.js";
9
+ import { collaborationAssessment, initializeCollaboration, validateCollaborationState, } from "./workflow-collaboration.js";
9
10
  export function captureScope(cwd, base) {
10
11
  if (!base || base.startsWith("-") || /[\x00-\x20\x7f]/.test(base))
11
12
  throw new Error("Expected a literal base ref");
@@ -126,6 +127,8 @@ function load(directory) {
126
127
  if (!Object.hasOwn(raw.config.workflows, raw.workflow))
127
128
  throw new Error("Invalid saved workflow");
128
129
  const definition = raw.config.workflows[raw.workflow];
130
+ if (definition.collaboration)
131
+ validateCollaborationState(raw.collaboration);
129
132
  const seen = new Set();
130
133
  for (const stage of raw.stages) {
131
134
  if (!object(stage) ||
@@ -213,11 +216,14 @@ export function evaluation(run, policy = run.config.policies[run.config.workflow
213
216
  stage.result !== undefined &&
214
217
  currentScope(stage))
215
218
  .map((stage) => ({ owner: stage.id, result: stage.result }));
219
+ const collaboration = collaborationAssessment(run);
220
+ reports.push(...collaboration.reports);
216
221
  const limitations = run.stages
217
222
  .filter((stage) => stage.status !== "completed")
218
223
  .map((stage) => `${stage.id}: ${stage.error ?? stage.status}`);
219
224
  if (run.status !== "completed")
220
225
  limitations.push(`Run ${run.status}`);
226
+ limitations.push(...collaboration.limitations);
221
227
  for (const stage of run.stages.filter((stage) => stage.status === "completed" && !currentScope(stage))) {
222
228
  if (stage.agent &&
223
229
  run.config.agents[stage.agent].access === "workspace-write")
@@ -269,6 +275,19 @@ export function runMetrics(run) {
269
275
  outputTokens: total("outputTokens"),
270
276
  costUsd: total("costUsd"),
271
277
  usageCoverage: `${reported.length}/${run.stages.filter((step) => step.agent && step.attempts).length} agent stages`,
278
+ ...(run.collaboration
279
+ ? {
280
+ collaboration: {
281
+ consultations: run.collaboration.consultations.length,
282
+ awaitingAnswers: run.collaboration.consultations.filter((item) => !item.answer).length,
283
+ submissions: run.collaboration.submissions.length,
284
+ accepted: run.collaboration.submissions.filter((item) => !item.supersededBy && item.review?.accepted).length,
285
+ latestRating: [...run.collaboration.submissions]
286
+ .reverse()
287
+ .find((item) => item.review)?.review?.rating ?? null,
288
+ },
289
+ }
290
+ : {}),
272
291
  stages: run.stages.map(({ id, status, attempts, durationMs, usage }) => ({
273
292
  id,
274
293
  status,
@@ -326,6 +345,7 @@ export function createRunLocked(store, config, workflow, base, prompt) {
326
345
  durationMs: 0,
327
346
  })),
328
347
  };
348
+ initializeCollaboration(run);
329
349
  fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
330
350
  fs.writeFileSync(path.join(directory, "scope.json"), context, {
331
351
  mode: 0o600,