|
| 1 | +# Sample-App Plan |
| 2 | + |
| 3 | +This document is the formal phase plan for the `sample-app` Laravel |
| 4 | +project that ships under the Durable Workflow umbrella. It explains why |
| 5 | +the sample app exists, how it relates to the engine, and what each phase |
| 6 | +of investment is meant to deliver. |
| 7 | + |
| 8 | +The clarity rule for this plan is the same as the rest of the v2 |
| 9 | +documentation: every claim about the sample app must point at an |
| 10 | +inspectable artifact in the `sample-app` repository. If a phase of this |
| 11 | +plan claims something is in place, the linked file or directory must |
| 12 | +prove it. |
| 13 | + |
| 14 | +## Why a Sample-App Plan Lives Here |
| 15 | + |
| 16 | +The workflow package owns the durable kernel. The sample app is the |
| 17 | +first place new features are demonstrated end-to-end and the first place |
| 18 | +bugs are reproduced against a realistic Laravel host. Because every |
| 19 | +release of the workflow package is meant to be exercised against the |
| 20 | +sample app within one cycle, the sample-app plan is published next to |
| 21 | +the workflow plan: a workflow-package contributor needs to know which |
| 22 | +samples a new feature must land in, and a sample-app contributor needs |
| 23 | +to know which engine surface a sample is meant to exercise. |
| 24 | + |
| 25 | +The sample-app source of truth lives in the |
| 26 | +[`sample-app` repository](https://github.com/durable-workflow/sample-app); |
| 27 | +this document only describes the contract and phase plan. |
| 28 | + |
| 29 | +## Scope |
| 30 | + |
| 31 | +This plan covers: |
| 32 | + |
| 33 | +- the four phases of sample-app evolution, from "small Laravel demo" |
| 34 | + to "first-class upstream feedback loop"; |
| 35 | +- the deliverables and exit criteria for each phase; |
| 36 | +- how the sample app stays in sync with workflow-package releases; |
| 37 | +- how upstream features get sample coverage and how missing coverage is |
| 38 | + surfaced. |
| 39 | + |
| 40 | +It does not cover: |
| 41 | + |
| 42 | +- engine architecture or durable-kernel contracts (see |
| 43 | + [`docs/workflow/plan.md`](../workflow/plan.md) and the architecture |
| 44 | + documents next to it); |
| 45 | +- managed-cloud readiness (see the readiness section of |
| 46 | + [`docs/workflow/plan.md`](../workflow/plan.md)); |
| 47 | +- the standalone server's polyglot worker examples, which live with the |
| 48 | + server documentation. |
| 49 | + |
| 50 | +## Status |
| 51 | + |
| 52 | +The sample app currently runs on Laravel 13 with the Durable Workflow |
| 53 | +2.0-alpha series. The Laravel 12 / Durable Workflow 1.x snapshot is |
| 54 | +preserved on the |
| 55 | +[`Laravel-12` branch](https://github.com/durable-workflow/sample-app/tree/Laravel-12) |
| 56 | +of the sample-app repository. |
| 57 | + |
| 58 | +| Phase | Title | State | |
| 59 | +|------|------|-------| |
| 60 | +| 1 | Foundational samples | done | |
| 61 | +| 2 | Multi-pattern coverage and codespace flow | done | |
| 62 | +| 3 | Operator surfaces and MCP | done | |
| 63 | +| 4 | Upstream feedback loop | done | |
| 64 | + |
| 65 | +## Phase 1 — Foundational samples |
| 66 | + |
| 67 | +**Goal.** Prove that a Laravel application can run a v2 workflow |
| 68 | +end-to-end with the published package. |
| 69 | + |
| 70 | +**Deliverables.** |
| 71 | + |
| 72 | +- a runnable codespace and `docker compose` flow; |
| 73 | +- `App\Workflows\Simple\SimpleWorkflow` plus an artisan command that |
| 74 | + starts it; |
| 75 | +- a `composer run dev` entry point that boots the queue worker and |
| 76 | + Waterline together. |
| 77 | + |
| 78 | +**Exit criteria.** |
| 79 | + |
| 80 | +- a new contributor can clone the repository, run one command, and see a |
| 81 | + workflow complete inside Waterline. |
| 82 | + |
| 83 | +## Phase 2 — Multi-pattern coverage and codespace flow |
| 84 | + |
| 85 | +**Goal.** Demonstrate the patterns a real Laravel application is most |
| 86 | +likely to need. |
| 87 | + |
| 88 | +**Deliverables.** |
| 89 | + |
| 90 | +- samples for elapsed-time measurement, multi-service coordination, |
| 91 | + webhook-started workflows, browser automation, AI activity loops, and |
| 92 | + durable inbox/outbox message streams; |
| 93 | +- a sample index in the repository README that names the goal, the |
| 94 | + workflow class, the artisan command, and the MCP key for each entry. |
| 95 | + |
| 96 | +**Exit criteria.** |
| 97 | + |
| 98 | +- every sample listed in the README is registered in |
| 99 | + `config/workflow_mcp.php` and exercised by `php artisan test`. |
| 100 | + |
| 101 | +## Phase 3 — Operator surfaces and MCP |
| 102 | + |
| 103 | +**Goal.** Make the sample app double as a teaching surface for the |
| 104 | +operator-facing parts of the engine. |
| 105 | + |
| 106 | +**Deliverables.** |
| 107 | + |
| 108 | +- Waterline available out of the box, with explicit guidance on how to |
| 109 | + read durable history versus runtime worker logs; |
| 110 | +- an MCP server that exposes the registered samples to AI clients with |
| 111 | + safe discovery metadata; |
| 112 | +- replay-safety teaching notes in the README that contrast `now()` with |
| 113 | + `sideEffect()` and link the relevant samples. |
| 114 | + |
| 115 | +**Exit criteria.** |
| 116 | + |
| 117 | +- an operator who runs the sample app can answer "what did the run do?" |
| 118 | + from Waterline alone, and an AI client can start, observe, and |
| 119 | + diagnose a sample run through MCP. |
| 120 | + |
| 121 | +## Phase 4 — Upstream feedback loop |
| 122 | + |
| 123 | +**Goal.** Make the sample app the first place new features land and the |
| 124 | +first place bugs get reproduced, and make missing coverage visible |
| 125 | +instead of implicit. |
| 126 | + |
| 127 | +**Deliverables.** |
| 128 | + |
| 129 | +- a structured **sample-request flow**: when a feature ships upstream, |
| 130 | + an issue can be opened against the sample-app repo with the |
| 131 | + `sample-request` template, and it closes when a workflow class lands |
| 132 | + under `app/Workflows/` that exercises the pattern end-to-end and is |
| 133 | + wired into both the artisan command list and `config/workflow_mcp.php`; |
| 134 | +- a structured **bug-reproducer flow**: bugs file with the `bug-report` |
| 135 | + template and land as workflows under `app/Workflows/Bug/`, where they |
| 136 | + stay covered by CI after the fix; |
| 137 | +- a **release-cycle upgrade cadence**: the sample app's pinned |
| 138 | + `durable-workflow/workflow` version moves within one release cycle of |
| 139 | + every upstream tag, and drift past one cycle is treated as tech debt; |
| 140 | +- a **lightweight upstream-coverage tracker**: a manifest in the |
| 141 | + sample-app repository names the upstream feature surfaces the sample |
| 142 | + app is expected to demonstrate, marks each one `covered` or `gap`, and |
| 143 | + is linted on every push so a feature that ships upstream without a |
| 144 | + sample becomes visible in CI rather than in tribal memory. |
| 145 | + |
| 146 | +**Exit criteria.** |
| 147 | + |
| 148 | +- a feature shipping upstream without a sample is visible in the |
| 149 | + coverage tracker before the next release, and the missing entry blocks |
| 150 | + CI on the sample-app repository; |
| 151 | +- bug reports routinely land with a sample-app reproducer, and the |
| 152 | + reproducer stays runnable after the bug is fixed because it is |
| 153 | + registered as a workflow under `app/Workflows/Bug/` and exercised by |
| 154 | + `php artisan test`. |
| 155 | + |
| 156 | +**Anchors in the sample-app repository.** |
| 157 | + |
| 158 | +- `.github/ISSUE_TEMPLATE/sample_request.yml` — sample-request flow. |
| 159 | +- `.github/ISSUE_TEMPLATE/bug_report.yml` — reproducer flow. |
| 160 | +- `.github/ISSUE_TEMPLATE/config.yml` — issue chooser that routes engine |
| 161 | + bugs and standalone-server bugs to their own repositories so they do |
| 162 | + not pollute the sample-app reproducer queue. |
| 163 | +- `docs/upstream-coverage.md` and `docs/upstream-coverage.yaml` — the |
| 164 | + human-readable tracker and machine-readable manifest of upstream |
| 165 | + feature surfaces and their sample-coverage status. |
| 166 | +- `scripts/check-upstream-coverage.php` and the CI job that runs it — |
| 167 | + the lint that proves the manifest stays consistent with the registered |
| 168 | + samples and that no listed feature surface has slipped to `gap` without |
| 169 | + an open `sample-request` issue. |
| 170 | +- README "Reporting Bugs and Requesting Samples" section — operator- |
| 171 | + visible entry point that explains both flows in one place. |
| 172 | + |
| 173 | +## Cadence Contract |
| 174 | + |
| 175 | +The sample-app pinned `durable-workflow/workflow` version moves within |
| 176 | +one release cycle of every upstream tag. A release cycle is defined by |
| 177 | +the workflow package's tag schedule, not by sample-app activity: |
| 178 | + |
| 179 | +- when an upstream tag ships, the sample-app coverage manifest's |
| 180 | + `tracked_workflow_version` is updated to that tag in the same |
| 181 | + release cycle; |
| 182 | +- if `tracked_workflow_version` is older than the latest upstream tag |
| 183 | + for more than one release cycle, the lint job fails so the gap is |
| 184 | + visible in CI; |
| 185 | +- security-driven upstream patches are treated as in-cycle and do not |
| 186 | + reset the cadence window. |
| 187 | + |
| 188 | +This contract gives external readers a predictable answer to "is this |
| 189 | +sample app in sync with the engine right now?" — they read the manifest |
| 190 | +header and compare it to the upstream tag list. |
| 191 | + |
| 192 | +## Coverage Manifest Shape |
| 193 | + |
| 194 | +The coverage manifest is the load-bearing artifact of Phase 4. It must: |
| 195 | + |
| 196 | +- enumerate every upstream feature surface the sample app is expected |
| 197 | + to demonstrate, with a stable `id` so links from issues, blog posts, |
| 198 | + or external docs do not rot; |
| 199 | +- mark each entry `covered` (with a workflow class and an artisan |
| 200 | + command that exercises it) or `gap` (with a link to an open |
| 201 | + `sample-request` issue, so a missing sample is always paired with a |
| 202 | + ticket that can absorb the work); |
| 203 | +- name the upstream documentation page that defines the surface, so a |
| 204 | + reader can see what the sample is supposed to teach without leaving |
| 205 | + the manifest; |
| 206 | +- record the `tracked_workflow_version` so the cadence contract is |
| 207 | + machine-readable. |
| 208 | + |
| 209 | +The manifest is rendered to a human-readable table in |
| 210 | +`docs/upstream-coverage.md` for casual reading, but the YAML file is |
| 211 | +the source of truth that the lint script checks. |
| 212 | + |
| 213 | +## Changing This Plan |
| 214 | + |
| 215 | +Adding a phase, marking a phase as done, changing the deliverables of a |
| 216 | +phase, or relaxing the cadence contract requires updating this document |
| 217 | +and the corresponding artifacts in the sample-app repository in the same |
| 218 | +change. In particular, marking Phase 4 deliverables as done requires the |
| 219 | +linked anchors above to exist on `main` of the sample-app repository. |
| 220 | + |
| 221 | +Removing a sample from the sample app or replacing it with a different |
| 222 | +demonstration of the same feature surface is a manifest update, not a |
| 223 | +plan change: edit `docs/upstream-coverage.yaml` and run the lint script, |
| 224 | +and leave this document alone. |
| 225 | + |
| 226 | +## See Also |
| 227 | + |
| 228 | +- [`docs/workflow/plan.md`](../workflow/plan.md) — workflow package |
| 229 | + plan, durable kernel feature mapping, and managed-cloud readiness. |
| 230 | +- [`docs/api-stability.md`](../api-stability.md) — stable API and |
| 231 | + history-event surface that the sample app is allowed to depend on. |
0 commit comments