@exaudeus/workrail 3.70.1 → 3.70.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/console-ui/assets/{index-BcZJOyVG.js → index-Cr14LfsQ.js} +1 -1
- package/dist/console-ui/index.html +1 -1
- package/dist/daemon/daemon-events.d.ts +1 -1
- package/dist/daemon/workflow-runner.js +4 -2
- package/dist/manifest.json +13 -13
- package/dist/trigger/polling-scheduler.d.ts +2 -1
- package/dist/trigger/polling-scheduler.js +3 -2
- package/dist/v2/durable-core/domain/prompt-renderer.js +6 -6
- package/docs/discovery/design-review-findings.md +62 -65
- package/docs/ideas/backlog.md +222 -106
- package/docs/plans/workflow-modernization-design.md +177 -59
- package/docs/tickets/next-up.md +7 -15
- package/package.json +1 -1
- package/workflows/adaptive-ticket-creation.json +53 -18
- package/workflows/mr-review-workflow.agentic.v2.json +10 -4
package/docs/ideas/backlog.md
CHANGED
|
@@ -4,6 +4,55 @@ Workflow and feature ideas that are worth capturing but not yet planned or desig
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## `jumpIf`: conditional step jumps with per-target jump counter (Apr 23, 2026)
|
|
8
|
+
|
|
9
|
+
**Problem:** Workflows with investigation or iterative refinement patterns (bug-investigation, mr-review) can exhaust their hypothesis set and reach an `inconclusive_but_narrowed` state with no structural way to restart an earlier phase. The only current options are: (1) prose guidance inside loop decision steps telling the agent to "reopen the shortlist" (unreliable), or (2) nested loops (not yet supported by the schema). A `jumpIf` primitive would let any step conditionally restart execution from an earlier step when a context condition is met.
|
|
10
|
+
|
|
11
|
+
**Proposed design:**
|
|
12
|
+
|
|
13
|
+
A `jumpIf` field on any step declaration:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"id": "phase-4b-loop-decision",
|
|
18
|
+
"jumpIf": {
|
|
19
|
+
"condition": { "var": "diagnosisType", "equals": "inconclusive_but_narrowed" },
|
|
20
|
+
"target": "phase-2-hypothesis-generation-and-shortlist",
|
|
21
|
+
"maxJumps": 2
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Engine behavior:**
|
|
27
|
+
- When a step completes and its `jumpIf.condition` is met, the engine checks the per-session jump counter for `target`
|
|
28
|
+
- Counter is derived from the event log: count `jump_recorded` events where `toStepId === target` -- fully append-only and replayable
|
|
29
|
+
- If `counter < maxJumps`: append `jump_recorded` event, create fresh nodeIds for `target` and all subsequent steps, mint a new continueToken pointing at the fresh target node
|
|
30
|
+
- If `counter >= maxJumps`: jump is blocked, execution falls through to the next step after the `jumpIf` step (safety cap, not an error)
|
|
31
|
+
- Fresh nodeIds mean no dedupeKey collisions and no DAG cycles -- the same step definition can appear multiple times in the session DAG as distinct nodes, same as loop iterations
|
|
32
|
+
|
|
33
|
+
**Why this is safe:**
|
|
34
|
+
- `maxJumps` is a required field -- no unbounded loops possible
|
|
35
|
+
- Counter is derivable from the append-only event log -- no mutable state
|
|
36
|
+
- The token system is unaffected -- each jump produces a fresh continueToken encoding a fresh nodeId
|
|
37
|
+
- Fall-through on limit reached is predictable and operator-visible
|
|
38
|
+
|
|
39
|
+
**Open design questions:**
|
|
40
|
+
- `maxJumps` default if omitted -- probably require it explicitly (same as `maxIterations` on loops, which is also required)
|
|
41
|
+
- DAG console rendering -- backward jumps create "re-entry" edges. Needs a distinct visual treatment (dashed edge? "JUMP x2" label?) -- tracked separately under console execution trace work
|
|
42
|
+
- Interaction with `runCondition` -- if a jumped-to step has a `runCondition` that evaluates false at re-entry time, does the engine skip it and advance? Probably yes, same as first-time evaluation.
|
|
43
|
+
- Whether `jumpIf` and loop `body` can coexist on the same step -- probably yes, they're independent control-flow mechanisms
|
|
44
|
+
|
|
45
|
+
**Scope when ready to implement:**
|
|
46
|
+
- `spec/workflow.schema.json`: add `jumpIf` to `standardStep`
|
|
47
|
+
- `spec/authoring-spec.json`: add authoring rule
|
|
48
|
+
- Compiler: validate `target` resolves to a reachable earlier step, `maxJumps >= 1`
|
|
49
|
+
- Engine (`src/v2/durable-core/`): new `jump_recorded` event kind, counter derivation, fresh nodeId creation on jump
|
|
50
|
+
- Console DAG: render jump edges distinctly
|
|
51
|
+
|
|
52
|
+
**Motivation workflow:** `wr.bug-investigation` -- when all hypotheses are eliminated and `diagnosisType === 'inconclusive_but_narrowed'`, jump back to phase 2 (hypothesis generation) with the eliminated theories in context, up to 2 times before falling through to validation/handoff.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
7
56
|
## Research Notes: Autonomous Platform Vision (Apr 14, 2026)
|
|
8
57
|
|
|
9
58
|
### Common-Ground relationship + cross-repo execution model
|
|
@@ -4542,22 +4591,22 @@ worktrain console --workspace ~/git/myproject # workspace-scoped view
|
|
|
4542
4591
|
### What shipped (Apr 17-18)
|
|
4543
4592
|
|
|
4544
4593
|
**Daemon stabilization:**
|
|
4545
|
-
-
|
|
4546
|
-
-
|
|
4547
|
-
-
|
|
4548
|
-
-
|
|
4549
|
-
-
|
|
4594
|
+
- `report_issue` tool -- agents call this instead of dying silently; structured JSON written to `~/.workrail/issues/<sessionId>.jsonl`, event emitted to daemon stream, WORKTRAIN_STUCK marker in `WorkflowRunResult`
|
|
4595
|
+
- Richer `BASE_SYSTEM_PROMPT` -- baked-in behavioral principles (oracle hierarchy, self-directed reasoning, workflow-as-contract, silent failure policy) rather than relying on soul file alone
|
|
4596
|
+
- `/bin/bash` for Bash tool -- process substitution `<(...)` and other bash-specific syntax now works
|
|
4597
|
+
- `DaemonEventEmitter` -- structured event stream at `~/.workrail/events/daemon/YYYY-MM-DD.jsonl`
|
|
4598
|
+
- Self-configuration -- `triggers.yml`, upgraded `daemon-soul.md` (WorkRail-specific rules + coding philosophy), `AGENTS.md` WorkTrain section
|
|
4550
4599
|
|
|
4551
4600
|
**Workflow library:**
|
|
4552
|
-
-
|
|
4553
|
-
-
|
|
4554
|
-
-
|
|
4555
|
-
-
|
|
4601
|
+
- mr-review v2.6 -- `philosophy_alignment` reviewer family; scoped philosophy extraction in fact packet; 7th coverage domain; "is this the right design?" framing
|
|
4602
|
+
- wfw v2.5 -- phases 2 and 3 split into dedicated prep-step design steps (2a/2b, 3a/3b); principle: assessments need dedicated prep steps, not on-the-fly evidence gathering
|
|
4603
|
+
- Clean workflow display names across library (removed `v2 •`, `Lean •`, etc.)
|
|
4604
|
+
- `philosophy.mdc` created at `~/.firebender/commands/philosophy.mdc` -- MR review subagents now evaluate findings against coding philosophy
|
|
4556
4605
|
|
|
4557
4606
|
**Integrations and infrastructure:**
|
|
4558
|
-
-
|
|
4559
|
-
-
|
|
4560
|
-
-
|
|
4607
|
+
- GitLab polling triggers fully merged (#404) -- zero-webhook MR polling
|
|
4608
|
+
- TS6 forward-compat tsconfig fixes (#401) -- unblocks TypeScript 6 dep bumps
|
|
4609
|
+
- Standalone console spec -- `worktrain console` as independent file-reading binary, zero coupling to daemon or MCP server
|
|
4561
4610
|
|
|
4562
4611
|
---
|
|
4563
4612
|
|
|
@@ -5309,19 +5358,19 @@ Long-term (when mobile exists):
|
|
|
5309
5358
|
|
|
5310
5359
|
### What works at this commit
|
|
5311
5360
|
|
|
5312
|
-
-
|
|
5313
|
-
-
|
|
5314
|
-
-
|
|
5315
|
-
-
|
|
5316
|
-
-
|
|
5317
|
-
-
|
|
5318
|
-
-
|
|
5319
|
-
-
|
|
5320
|
-
-
|
|
5321
|
-
-
|
|
5322
|
-
-
|
|
5323
|
-
-
|
|
5324
|
-
-
|
|
5361
|
+
- Daemon accepts webhooks, starts sessions, runs workflows end-to-end
|
|
5362
|
+
- Sessions advance through all workflow phases autonomously
|
|
5363
|
+
- `mr-review-workflow-agentic` v2.6 runs fully -- context gathering, review phases, synthesis loop, validation, handoff
|
|
5364
|
+
- `wr.discovery` v3.2.0 runs fully -- with new phase-0-reframe (goal reframing before research)
|
|
5365
|
+
- Console shows live sessions via event log (no daemon connection required)
|
|
5366
|
+
- MCP server is stable (bridge removed, EPIPE fixed, v3.34.1 published)
|
|
5367
|
+
- GitHub + GitLab polling triggers (no webhooks needed)
|
|
5368
|
+
- `worktrain init`, `tell`, `inbox`, `spawn`, `await` CLI commands
|
|
5369
|
+
- Stuck detection + visibility (`worktrain status`, `worktrain logs --follow`)
|
|
5370
|
+
- `complete_step` tool -- daemon manages continueToken, LLM never handles it
|
|
5371
|
+
- Assessment gate circuit breaker (stops at 3 blocked attempts, shows artifact format)
|
|
5372
|
+
- `worktrain daemon --install` creates launchd service (daemon survives MCP reconnects)
|
|
5373
|
+
- Self-configuration (`triggers.yml`, `daemon-soul.md`, `AGENTS.md` for workrail repo)
|
|
5325
5374
|
|
|
5326
5375
|
### Current limitations at this commit
|
|
5327
5376
|
|
|
@@ -5508,10 +5557,10 @@ Artifact: design-candidates-stdio-simplification-2026-04-18.md
|
|
|
5508
5557
|
|
|
5509
5558
|
### What additionally shipped since the milestone (commit 473f4bd0)
|
|
5510
5559
|
|
|
5511
|
-
-
|
|
5512
|
-
-
|
|
5513
|
-
-
|
|
5514
|
-
-
|
|
5560
|
+
- **`complete_step` tool** (#569) -- daemon manages continueToken internally, LLM never handles it. Notes required (min 50 chars). `continue_workflow` deprecated.
|
|
5561
|
+
- **`spawn_agent` tool** (#573) -- native in-process child session spawning. parentSessionId in session_created event. Depth enforcement. Semaphore bypass. All 4 WorkflowRunResult variants handled.
|
|
5562
|
+
- **`complete_step` description fix** (#575) -- removed token-seeking language from deprecated continue_workflow description that would have triggered the LLM to seek a token.
|
|
5563
|
+
- **Discovery ran before both implementations** -- wr.discovery validated complete_step approach (found 1 merge blocker fixed), designed spawn_agent architecture (found semaphore deadlock risk avoided).
|
|
5515
5564
|
|
|
5516
5565
|
### Updated limitations
|
|
5517
5566
|
|
|
@@ -6051,24 +6100,24 @@ Also consolidated from three workflow variants to one canonical file.
|
|
|
6051
6100
|
|
|
6052
6101
|
### What shipped since v3.36.0 (Apr 18 -- Apr 19)
|
|
6053
6102
|
|
|
6054
|
-
-
|
|
6055
|
-
-
|
|
6056
|
-
-
|
|
6057
|
-
-
|
|
6058
|
-
-
|
|
6059
|
-
-
|
|
6060
|
-
-
|
|
6061
|
-
-
|
|
6062
|
-
-
|
|
6063
|
-
-
|
|
6064
|
-
-
|
|
6065
|
-
-
|
|
6066
|
-
-
|
|
6067
|
-
-
|
|
6068
|
-
-
|
|
6069
|
-
-
|
|
6070
|
-
-
|
|
6071
|
-
-
|
|
6103
|
+
- **`wr.shaping`** -- faithful Shape Up shaping workflow (9 steps, two human gates with autonomous fallback)
|
|
6104
|
+
- **`coding-task-workflow-agentic` Phase 0.5** -- upstream context detection; skips design phases when solution is pre-specified. Three-workflow pipeline: shaping → discovery → coding.
|
|
6105
|
+
- **Coding workflow consolidated** -- from three variants (lean, full, lean.v2) to one canonical file.
|
|
6106
|
+
- **HttpServer removed from MCP server** (#601) -- pure stdio. MCP server can no longer accidentally start an HTTP server.
|
|
6107
|
+
- **Late-bound goals** (#604) -- `goalTemplate: "{{$.goal}}"` defaults for webhook-driven sessions. Goals can come from the payload, not just the static trigger definition.
|
|
6108
|
+
- **Coordinator message queue drain** (#606) -- `pr-review` coordinator reads `~/.workrail/message-queue.jsonl` before each spawn cycle. `worktrain tell stop`, `skip-pr <n>`, `add-pr <n>` work.
|
|
6109
|
+
- **Notifications shipped** -- `NotificationService` implemented, wired into `TriggerRouter` via `trigger-listener.ts`. `WORKTRAIN_NOTIFY_MACOS=true` and `WORKTRAIN_NOTIFY_WEBHOOK=<url>` in `~/.workrail/config.json`.
|
|
6110
|
+
- **`worktrain run pr-review`** -- fully wired coordinator command. `spawnSession` → `awaitSessions` → `getAgentResult` (session-wide artifact aggregation) → `parseFindingsFromNotes` → route by severity.
|
|
6111
|
+
- **`wr.review_verdict` artifact path** -- end-to-end wired: `mr-review-workflow.agentic.v2.json` phase-6 emits it, `artifact-contract-validator.ts` validates it at `continue_workflow` time, coordinator reads it with keyword-scan fallback.
|
|
6112
|
+
- **`worktrain logs` / `worktrain health`** -- structured daemon log tailing and per-session health summary. `worktrain status <id>` deprecated in favor of `worktrain health <id>`.
|
|
6113
|
+
- **`signal_coordinator` tool** -- agent can emit structured mid-session signals (`progress`, `finding`, `data_needed`, `approval_needed`, `blocked`) without advancing the step.
|
|
6114
|
+
- **`ChildWorkflowRunResult` + `assertNever`** -- spawn_agent delivery_failed bug fixed. `delivery_failed` impossible state is compile-time excluded.
|
|
6115
|
+
- **`lastStepArtifacts` on `WorkflowRunSuccess`** -- `onComplete` callback forwards artifacts alongside notes. Coordinator can read typed artifacts from result without a separate HTTP call.
|
|
6116
|
+
- **`steerRegistry` + POST `/sessions/:id/steer`** -- coordinator injection endpoint wired in daemon console. Running sessions register a steer callback; coordinators can inject mid-session messages via HTTP.
|
|
6117
|
+
- **GitHub polling adapters** -- `github_issues_poll` and `github_prs_poll` providers fully implemented alongside existing `gitlab_poll`.
|
|
6118
|
+
- **Knowledge graph spike** -- `src/knowledge-graph/` module: DuckDB in-memory + ts-morph indexer + two validation queries. NOT yet wired to an MCP tool (ts-morph in devDependencies).
|
|
6119
|
+
- **`worktrain daemon --install`** -- launchd plist creation, load, verify. Daemon survives MCP server reconnects.
|
|
6120
|
+
- **Performance sweep** -- April 2026 sweep identified 10 highest-leverage fixes, filed as issues #248-257. Not yet merged.
|
|
6072
6121
|
|
|
6073
6122
|
### Accurate limitations (as of v3.40.0)
|
|
6074
6123
|
|
|
@@ -6406,27 +6455,27 @@ Design this as part of the adaptive coordinator (#3). The `touchesUI` flag belon
|
|
|
6406
6455
|
|
|
6407
6456
|
All five top-priority autonomous pipeline items shipped:
|
|
6408
6457
|
|
|
6409
|
-
-
|
|
6458
|
+
- **#1 -- Worktree isolation + auto-commit** (PR #630) -- Each WorkTrain coding session now runs in an isolated git worktree (`~/.workrail/worktrees/<sessionId>`). `trigger.workspacePath` is never mutated; all tool factories receive `sessionWorkspacePath`. Crash recovery sidecar persists `worktreePath` for orphan cleanup. `delivery-action.ts` asserts HEAD branch before push. `test-task` trigger: `branchStrategy: worktree`, `autoCommit: true`, `autoOpenPR: true`.
|
|
6410
6459
|
|
|
6411
|
-
-
|
|
6460
|
+
- **#2 -- Stuck detection escalation** (PR #636) -- New `WorkflowRunResult._tag: 'stuck'` discriminant. When `repeated_tool_call` heuristic fires and `stuckAbortPolicy !== 'notify_only'` (default: `'abort'`), daemon aborts the session immediately instead of burning the 30-min wall clock. Writes structured entry to `~/.workrail/outbox.jsonl`. `stuckAbortPolicy` and `noProgressAbortEnabled` configurable per trigger in `agentConfig`. `ChildWorkflowRunResult` updated atomically.
|
|
6412
6461
|
|
|
6413
|
-
-
|
|
6462
|
+
- **#3 -- Adaptive pipeline coordinator** (PR #639) -- `worktrain run pipeline --issue N --workspace path` routes tasks to the right pipeline via pure static routing:
|
|
6414
6463
|
- dep-bump + PR number → QUICK_REVIEW (delegates to `runPrReviewCoordinator`)
|
|
6415
6464
|
- PR/MR number → REVIEW_ONLY
|
|
6416
6465
|
- `current-pitch.md` exists → IMPLEMENT (coding + PR + review + merge)
|
|
6417
6466
|
- Default → FULL (discovery → shaping → coding → PR → review → merge)
|
|
6418
6467
|
- Fix loop cap: 2 iterations max. Escalating audit chain for Critical findings. UX gate for UI-touching tasks. 6 hardcoded timeout constants. Pitch archived after IMPLEMENT/FULL completes.
|
|
6419
6468
|
|
|
6420
|
-
-
|
|
6469
|
+
- **#4 -- GitHub issue queue poll trigger** (PR #637) -- New `github_queue_poll` trigger provider. Polls GitHub issues matching `GitHubQueueConfig` (assignee-based MVP, `label`/`mention`/`query` typed but `not_implemented`). Maturity inference from 3 deterministic heuristics. Idempotency check (conservative: parse errors = active). JSONL decision log at `~/.workrail/queue-poll.jsonl`. `maxTotalConcurrentSessions` cap. Bot identity config (`botName`, `botEmail`).
|
|
6421
6470
|
|
|
6422
|
-
-
|
|
6471
|
+
- **#5 -- Context assembly layer** (PR #624, shipped earlier) -- `ContextAssembler` injects git diff summary + prior session notes before turn 1. Feeds into coordinator pre-dispatch.
|
|
6423
6472
|
|
|
6424
|
-
-
|
|
6425
|
-
-
|
|
6426
|
-
-
|
|
6427
|
-
-
|
|
6428
|
-
-
|
|
6429
|
-
-
|
|
6473
|
+
- **Performance sweep** (all 10 issues #248-257 -- already confirmed complete)
|
|
6474
|
+
- **Console session tree** (PR #607 -- parentSessionId rendered in UI)
|
|
6475
|
+
- **Daemon file-nav tools** (PR #619) -- Glob, Grep, Edit + upgraded Read/Write with staleness guard
|
|
6476
|
+
- **`spawn_agent` artifacts** (PR #613) -- `lastStepArtifacts` surfaced through spawn_agent return
|
|
6477
|
+
- **`wr.shaping` workflow** (PR #610) -- faithful Shape Up shaping, 9 steps
|
|
6478
|
+
- **Coding workflow Phase 0.5** (PR #610) -- upstream context detection, three-workflow pipeline
|
|
6430
6479
|
|
|
6431
6480
|
### WorkTrain current capabilities (v3.45.0)
|
|
6432
6481
|
|
|
@@ -7497,22 +7546,22 @@ Medium for the cleanup command (quality of life, stops log noise). High for star
|
|
|
7497
7546
|
|
|
7498
7547
|
**All five autonomous pipeline items (previously recorded) plus:**
|
|
7499
7548
|
|
|
7500
|
-
-
|
|
7501
|
-
-
|
|
7502
|
-
-
|
|
7503
|
-
-
|
|
7504
|
-
-
|
|
7505
|
-
-
|
|
7506
|
-
-
|
|
7507
|
-
-
|
|
7508
|
-
-
|
|
7509
|
-
-
|
|
7510
|
-
-
|
|
7511
|
-
-
|
|
7512
|
-
-
|
|
7513
|
-
-
|
|
7514
|
-
-
|
|
7515
|
-
-
|
|
7549
|
+
- **Discovery loop fix** (#748) -- three coupled fixes: thread `maxSessionMinutes` through `spawnSession` (sessions now get 55/35/65 min instead of 30 min default), inspect `PipelineOutcome` in polling-scheduler and apply `worktrain:in-progress` label on escalation, write issue-ownership sidecar for cross-restart idempotency
|
|
7550
|
+
- **In-process `awaitSessions` and `getAgentResult`** (#741) -- replaced HTTP calls to the daemon's own console with direct `ConsoleService` access
|
|
7551
|
+
- **Try/catch on all coordinator I/O** (#740) -- `getAgentResult`, `pollForPR`, `postToOutbox` all wrapped; coordinator no longer crashes on I/O failure
|
|
7552
|
+
- **Dispatch dedup prealloc bypass** (#744) -- `dispatch()` now bypasses dedup for pre-allocated sessions, fixing the zombie session bug that prevented discovery from starting
|
|
7553
|
+
- **Promise.race crash fix** (#733) -- worktrees scan timeout no longer crashes the daemon via unhandled rejection
|
|
7554
|
+
- **Trigger validator** (#690) -- `worktrain trigger validate` command, `validateTriggerStrict()` pure function
|
|
7555
|
+
- **`worktrain trigger poll`** (#697) -- force immediate poll cycle on any queue trigger
|
|
7556
|
+
- **`worktrain trigger test`** (#656) -- dry-run showing what would dispatch
|
|
7557
|
+
- **Auto-load ~/.workrail/.env** (#673) -- daemon reads secrets from .env automatically
|
|
7558
|
+
- **Daemon lifecycle events** (#674) -- `session_aborted` on SIGTERM, `daemon_heartbeat` every 30s
|
|
7559
|
+
- **Attribution signals** (#658) -- `[WT]` PR title prefix, `Co-authored-by: WorkTrain` commit trailers, `worktrain:generated` label
|
|
7560
|
+
- **Secret scan before push** (#660) -- pattern-based scan blocks commits with leaked credentials
|
|
7561
|
+
- **Unified logs stream** (#680) -- `worktrain logs` now merges daemon events, queue-poll.jsonl, and filtered stderr
|
|
7562
|
+
- **Stale lock file handling** (#705) -- validates lock file PID before trusting port discovery
|
|
7563
|
+
- **5 architectural audits** (docs/design/) -- coordinator access, error handling, testability, type bloat, memory management
|
|
7564
|
+
- **Stale user workflow cleanup** -- removed old copies from `~/.workrail/workflows/` that were causing ValidationError noise
|
|
7516
7565
|
|
|
7517
7566
|
### Current pipeline state (live)
|
|
7518
7567
|
|
|
@@ -7591,30 +7640,30 @@ Discovery session `ecf359d7` running: 77 turns, 11 step advances (active, making
|
|
|
7591
7640
|
This was a major session covering daemon/console separation, metrics infrastructure, and workflow stability fixes.
|
|
7592
7641
|
|
|
7593
7642
|
**Architecture -- daemon/console/MCP separation:**
|
|
7594
|
-
-
|
|
7595
|
-
-
|
|
7596
|
-
-
|
|
7643
|
+
- **Delete daemon-console.ts** (#753) -- daemon no longer bundles an embedded console; `worktrain console` is now the sole console entry point
|
|
7644
|
+
- **Remove dead steer/poll endpoints** (#755) -- deleted `worktrain trigger poll` CLI and the steer/poll HTTP endpoints that were only used by the deleted daemon-console
|
|
7645
|
+
- **Wire workflow catalog into standalone console** (#783, open) -- `worktrain console` Workflows tab now works without the MCP server running; `EnhancedMultiSourceWorkflowStorage` constructed directly in `standalone-console.ts`
|
|
7597
7646
|
|
|
7598
7647
|
**Metrics infrastructure (6-step sequence, all merged):**
|
|
7599
|
-
-
|
|
7600
|
-
-
|
|
7601
|
-
-
|
|
7602
|
-
-
|
|
7603
|
-
-
|
|
7604
|
-
-
|
|
7648
|
+
- **timestampMs on events** (#768, #772) -- `DomainEventEnvelopeV1Schema` now has required `timestampMs`; backfill script at `scripts/backfill-timestamps.ts`
|
|
7649
|
+
- **`run_completed` event** (#773) -- emitted on successful session completion with `startGitSha`, `endGitSha`, `agentCommitShas`, `captureConfidence`, `durationMs`
|
|
7650
|
+
- **Authoring docs: metrics_* keys** (#767) -- `metricsProfile` field and SHA accumulation convention documented in `docs/authoring-v2.md`
|
|
7651
|
+
- **`projectSessionMetricsV2` projection** (#771) -- pure projection reading `run_completed` + `context_set metrics_*` keys, wired into `ConsoleSessionSummary`
|
|
7652
|
+
- **Console metrics display** (#777) -- `SessionMetricsSection` in session detail view; `GET /api/v2/sessions/:id/diff-summary` endpoint
|
|
7653
|
+
- **`stats-summary.json` writer** (#769) -- `~/.workrail/data/stats-summary.json` aggregated from `execution-stats.jsonl`, written post-session and every 30s heartbeat
|
|
7605
7654
|
|
|
7606
7655
|
**Engine improvements:**
|
|
7607
|
-
-
|
|
7608
|
-
-
|
|
7609
|
-
-
|
|
7610
|
-
-
|
|
7611
|
-
-
|
|
7612
|
-
-
|
|
7613
|
-
-
|
|
7614
|
-
-
|
|
7656
|
+
- **Execution time tracking** (#756) -- `execution-stats.jsonl` per session in finally block
|
|
7657
|
+
- **Worktree orphan leak fix** (#756) -- sidecar deletion deferred to `maybeRunDelivery()` for worktree sessions
|
|
7658
|
+
- **assertNever for ReviewSeverity** (#756)
|
|
7659
|
+
- **Crash recovery phase A** (#759) -- `clearQueueIssueSidecars()` fixes 56-min re-dispatch block; sidecar preservation for sessions with progress
|
|
7660
|
+
- **Conversation history persistence** (#762) -- `<sessionId>-conversation.jsonl` per daemon session, append-only delta flush at each turn
|
|
7661
|
+
- **queue-poll.jsonl rotation** (#761) -- 10 MB size cap with `.1` backup
|
|
7662
|
+
- **Remove WorkTrain-owned label writes** (#765) -- `worktrain:in-progress`, `worktrain:generated` labels removed; deduplication now purely internal (sidecar + dispatchingIssues + session scan)
|
|
7663
|
+
- **metricsProfile footer injection** (#779) -- engine injects `metrics_*` accumulation footers based on `metricsProfile` workflow field; all 35 bundled workflows assigned profiles
|
|
7615
7664
|
|
|
7616
7665
|
**Workflow namespace:**
|
|
7617
|
-
-
|
|
7666
|
+
- **Rename all bundled workflows to `wr.*`** (#782, open) -- `coding-task-workflow-agentic` → `wr.coding-task`, `mr-review-workflow-agentic` → `wr.mr-review`, etc. Prevents local project source from shadowing bundled workflows on version mismatch.
|
|
7618
7667
|
|
|
7619
7668
|
---
|
|
7620
7669
|
|
|
@@ -7648,22 +7697,43 @@ This was a major session covering daemon/console separation, metrics infrastruct
|
|
|
7648
7697
|
|
|
7649
7698
|
---
|
|
7650
7699
|
|
|
7651
|
-
### Current system state (
|
|
7700
|
+
### Current system state (Apr 23, 2026 -- end of session)
|
|
7701
|
+
|
|
7702
|
+
**npm version: v3.68.1** | Daemon: stopped | MCP: connected on 3.68.1
|
|
7703
|
+
|
|
7704
|
+
**What shipped this session (Apr 23):**
|
|
7705
|
+
- **`wr.*` workflow namespace rename** (#782) -- all 31 bundled workflows renamed; `legacy_project` source can no longer shadow bundled ones
|
|
7706
|
+
- **`triggers.yml` updated** (#785) -- `wr.coding-task`, `wr.mr-review`
|
|
7707
|
+
- **Standalone console Workflows tab** (#783) -- works without MCP server
|
|
7708
|
+
- **Validation regression test** (#784) -- `additionalProperties: false` confirmed enforced
|
|
7709
|
+
- **Session metrics refactor** (#786) -- defensive cast removed, types clean
|
|
7710
|
+
- **Validation warnings in `list_workflows`** (#787) -- users now see why their workflow disappeared
|
|
7711
|
+
- **`loadSessionNotes` export fix** (#790) -- 14 pre-existing test failures now pass
|
|
7712
|
+
- **`metrics_outcome` validation** (#793) -- agents get `VALIDATION_ERROR` immediately if they pass invalid values; tested and confirmed working
|
|
7652
7713
|
|
|
7653
|
-
**
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
**Local build:** Built from main at 3.66.0 (`npm run build` done)
|
|
7658
|
-
**triggers.yml:** Must update `workflowId` values to new `wr.*` IDs after #782 merges (e.g. `coding-task-workflow-agentic` → `wr.coding-task`)
|
|
7714
|
+
**Active bugs / gaps:**
|
|
7715
|
+
- GitHub admin bypass removed from ruleset -- `gh pr merge --admin` will fail
|
|
7716
|
+
- `metrics_pr_numbers` still 0% (review workflows not picking up footer) -- expected, no sessions have completed `wr.mr-review` with new IDs yet
|
|
7717
|
+
- Only 20% of sessions have `run_completed` -- most daemon sessions don't complete due to crashes/timeouts; normal
|
|
7659
7718
|
|
|
7660
|
-
**
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7719
|
+
**Known gaps (not yet started):**
|
|
7720
|
+
- **Phase B crash recovery** -- actual agent loop restart after crash
|
|
7721
|
+
- **`workrail cleanup` command** -- dead managed sources, old sessions
|
|
7722
|
+
- **Versioned workflow schema validation** -- see backlog entry above
|
|
7723
|
+
- **console-routes.ts dispatch coupling** -- `POST /api/v2/auto/dispatch` imports from `src/daemon/`
|
|
7724
|
+
- **Daemon agent loop stall detection** -- 120s liveness check for frozen loops
|
|
7725
|
+
|
|
7726
|
+
**System state:**
|
|
7727
|
+
- **WorkRail MCP server:** Connected at 3.68.1 (global npm `npx -y @exaudeus/workrail`). All `wr.*` IDs working.
|
|
7728
|
+
- **WorkTrain daemon:** Stopped. Start: `launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/io.worktrain.daemon.plist`. Points at local dist (`/Users/etienneb/git/personal/workrail/dist/cli-worktrain.js`).
|
|
7729
|
+
- **WorkRail console:** Not running. Start: `worktrain console`. Reads session files directly, no daemon required.
|
|
7730
|
+
- **Global npm:** 3.68.1 (`npm update -g @exaudeus/workrail` done)
|
|
7731
|
+
- **Local build:** Built from main at 3.68.1 (`npm run build` done)
|
|
7732
|
+
|
|
7733
|
+
**Next up:**
|
|
7734
|
+
1. Restart daemon and watch first pipeline run with `wr.*` IDs
|
|
7735
|
+
2. Versioned schema validation (design ready in backlog, audit confirmed v1 = current schema)
|
|
7736
|
+
3. Daemon agent loop stall detection (medium priority)
|
|
7667
7737
|
|
|
7668
7738
|
---
|
|
7669
7739
|
|
|
@@ -7804,3 +7874,49 @@ Convention drift is a recurring tax. Migration is a one-time cost. In a codebase
|
|
|
7804
7874
|
This is not urgent -- the current codebase is working well. But if autonomous agent usage grows and human review per-PR decreases further, the compiler enforcement gap becomes more important, not less.
|
|
7805
7875
|
|
|
7806
7876
|
**Priority:** Low / long-term. Worth revisiting when the agent is writing the majority of new code. Requires a concrete spike: rewrite one module (e.g. `src/v2/durable-core/domain/`) in Kotlin and measure the real friction before committing to a full migration.
|
|
7877
|
+
|
|
7878
|
+
---
|
|
7879
|
+
|
|
7880
|
+
## Task re-dispatch loop protection (Apr 23, 2026) -- HIGH PRIORITY
|
|
7881
|
+
|
|
7882
|
+
**The problem:** When a pipeline session fails (stuck, crash, timeout), the idempotency sidecar (`queue-issue-<N>.json`) expires after its TTL and the queue re-selects the same issue on the next poll cycle. There is no memory of how many times an issue has been attempted. A task that consistently fails (bad workflow, broken code, unsolvable problem) gets retried indefinitely, burning API credits and producing no forward progress.
|
|
7883
|
+
|
|
7884
|
+
**Concrete incident:** Issue #393 ("test(daemon): add coverage for loadSessionNotes failure paths") was dispatched in a loop -- discovery + shaping + coding sessions repeatedly started, failed stuck, and were re-dispatched. The issue had already been resolved by human intervention but the daemon didn't know.
|
|
7885
|
+
|
|
7886
|
+
**What we need:** Per-issue attempt tracking with a max-attempts cap and escalation on exhaustion.
|
|
7887
|
+
|
|
7888
|
+
**Design sketch:**
|
|
7889
|
+
|
|
7890
|
+
1. **Attempt counter in the sidecar:** Extend `queue-issue-<N>.json` to include `attemptCount: number`. On each new dispatch for the same issue, increment the counter. When `attemptCount >= maxAttempts` (default 3), do not dispatch -- instead emit an outbox notification and apply a `worktrain:needs-human` label (or equivalent internal signal) so the issue is skipped until a human resets it.
|
|
7891
|
+
|
|
7892
|
+
2. **Sidecar persistence across TTL expiry:** Today the sidecar is deleted when the TTL expires. To count attempts across expiry, either: (a) use a longer-lived separate tracking file per issue, or (b) check the daemon event log for previous `session_started` events with the same `issueNumber` goal within a lookback window (e.g. last 24h).
|
|
7893
|
+
|
|
7894
|
+
3. **Human reset mechanism:** A human should be able to say "try again" by closing and reopening the issue, or by removing a `worktrain:stuck` label, or via a `worktrain retry <issueNumber>` CLI command.
|
|
7895
|
+
|
|
7896
|
+
4. **Escalation signal:** When max attempts is hit, post a comment on the GitHub issue: "WorkTrain attempted this task 3 times and was unable to complete it. Manual intervention required." This closes the invisible failure loop.
|
|
7897
|
+
|
|
7898
|
+
**Files to change:**
|
|
7899
|
+
- `src/trigger/adapters/github-queue-poller.ts` -- track attempt count when writing sidecar
|
|
7900
|
+
- `src/trigger/polling-scheduler.ts` -- check attempt count before dispatch
|
|
7901
|
+
- `~/.workrail/daemon-sessions/queue-issue-<N>.json` schema -- add `attemptCount`
|
|
7902
|
+
|
|
7903
|
+
**Priority:** High. This is a production correctness issue -- the daemon will burn unlimited credits on a broken task without this.
|
|
7904
|
+
|
|
7905
|
+
---
|
|
7906
|
+
|
|
7907
|
+
## Auto-start mechanism inventory (Apr 23, 2026)
|
|
7908
|
+
|
|
7909
|
+
**Current auto-start mechanisms for WorkTrain daemon:**
|
|
7910
|
+
|
|
7911
|
+
1. **launchd plist** (`~/Library/LaunchAgents/io.worktrain.daemon.plist`) with `KeepAlive: true` -- daemon restarts automatically on crash or manual kill. Only `launchctl bootout` stops it permanently.
|
|
7912
|
+
|
|
7913
|
+
No other auto-start mechanisms exist (no login items, no cron, no systemd).
|
|
7914
|
+
|
|
7915
|
+
**Operational notes:**
|
|
7916
|
+
- To stop temporarily: `launchctl stop io.worktrain.daemon` -- daemon stops but restarts on next launchd check
|
|
7917
|
+
- To stop permanently: `launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/io.worktrain.daemon.plist`
|
|
7918
|
+
- To restart after bootout: `launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/io.worktrain.daemon.plist`
|
|
7919
|
+
|
|
7920
|
+
**Known risk:** When working on daemon code, always `bootout` first. A `stop` will just respawn the old binary. This has caused confusion multiple times in this session.
|
|
7921
|
+
|
|
7922
|
+
**Improvement idea:** Add a `worktrain daemon stop --permanent` command that does the bootout automatically, and `worktrain daemon start` that does the bootstrap. Makes the distinction between temporary stop and permanent stop explicit without requiring operators to know launchd internals.
|