How We Work
A streamlined process for outcome-driven delivery, mapping strategic problems straight through to test-driven execution.
How We Work
This section describes how we move from an observed problem to shipped customer value. The process is lean by design, enforcing that technical execution is strictly bound to clear intent and verified by automated tests from the very beginning. It answers the fundamental question: How do you move fast without skipping the discovery that stops you building the wrong thing?
Work flows through four stages, each more concrete than the last:
Inside each stage
1. Problem Statement
Most wasted work is caused by excellent execution of the wrong thing. Skipping from idea to solution — without pausing to understand the problem — leads to building with false confidence.
A Problem Statement captures observed pain — real, evidenced, specific — alongside an appetite: a judgment about how much time this problem is worth solving.
- Appetite is not an estimate of how long a solution will take. It is an opportunity cost judgment made before the solution is defined. You are betting that the problem is worth that much time.
- Problem statements do not accumulate indefinitely. They are a curated list, updated as understanding evolves and retired when no longer relevant.
- Platform and infrastructure problems are valid problem statements. The "who experiences it" can be internal — the engineering team, the system's reliability, the business's compliance posture. Feature bets routinely surface infrastructure gaps (e.g., a missing event backplane, no deletion cascade). The right response is to extract the gap as its own problem statement — not to expand the feature bet. The feature bet declares the constraint explicitly; the platform bet solves it.
Reviewing a Problem Statement
| Check | What to verify |
|---|---|
| Pain is real | Describes observed friction with evidence (user feedback, metrics, incidents), not a hypothetical. |
| No solution leaking | The problem section describes pain, not a technical gap. "We need a WebSocket endpoint" is a solution. "Users can't see updates until they refresh" is a problem. |
| Appetite is a judgment | Explains the reasoning behind the time budget, not just a number. Reads as an opportunity cost decision. |
| Why-now is compelling | Something concrete has changed — not "it would be nice" but a real trigger. |
| Scope is bounded | Specific enough to shape into a pitch. Vague problems ("improve the user experience") can't be pitched. |
Common pitfalls:
- Solution masquerading as a problem: "We need to add real-time transcription" is a solution. The problem is "Users cannot follow meeting discussions in real-time because transcripts are only available after the meeting ends."
- Missing evidence: "Users probably want X" is not evidence. Reference specific feedback, usage data, incidents, or engineering friction.
- Appetite without reasoning: "4 weeks" is not an appetite judgment. "This affects ~60% of meetings. Four weeks is worth it to eliminate the manual workaround that takes 10 minutes per meeting" is.
2. Pitch
Unformed ideas become backlogs. Backlogs create the illusion that everything is captured and considered, when really they are lists of things nobody explicitly said no to.
Before a problem reaches the build phase, it is shaped into a Pitch. A pitch links a validated problem to a rough solution proposal. It is concrete enough to execute against but stays away from micro-detail.
A pitch must contain:
- The problem — what was observed, who experiences it, why it matters now.
- The appetite — how much time to spend.
- A rough solution sketch — the general approach to the solution.
- Rabbit holes — approaches already considered and ruled out. Include plausible-looking approaches that would blow the appetite or the scope, and infrastructure assumptions the bet makes (e.g., "we assume sticky sessions, not a backplane").
- Explicit no-gos — what is completely out of scope. Include both obvious exclusions and natural extensions that users would reasonably expect but that don't belong in this version (e.g., pause/resume, mobile support, export/download). Vague no-gos invite scope creep — be specific about what's excluded and why.
A funded pitch becomes a Bet — a commitment bounded by the appetite.
Reviewing a Pitch
| Check | What to verify |
|---|---|
| Problem traces to a statement | The pitch's problem section restates the validated problem statement, not a different problem. |
| Solution stays fat-marker | The proposed solution describes direction, not implementation. No endpoint paths, field names, or service-internal details. |
| Rabbit holes are genuine | Each ruled-out approach is plausible and the rejection reason names a real cost (appetite, complexity, maintenance burden). |
| No-gos include natural extensions | The list names capabilities users would reasonably expect but that are excluded — not just obvious unrelated features. |
| No-gos are specific | Each exclusion explains what and why. "We won't do everything" is not a no-go. "Pause/resume recording is out because it requires server-side state management that exceeds the appetite" is. |
| Appetite is preserved | The proposed solution fits within the appetite. If it doesn't, either reshape the solution or increase the appetite with justification. |
Common pitfalls:
- Over-designed solution: If the pitch includes database schemas, API paths, or component hierarchies, it has gone too far. Those belong in the TDD.
- Missing rabbit holes: Every problem has at least one plausible approach that should be avoided. An empty section suggests insufficient exploration.
- Weak no-gos: No-gos that only list obviously unrelated features. The valuable no-gos are the natural extensions users expect — "download/export of recordings is out of v1 because it requires a transcoding pipeline."
- Problem drift: The pitch describes a different or broader problem than the problem statement. The pitch should refine the same problem, not expand it.
3. TDD: Foundations
Technical Design bridges the intent of the pitch to parallel execution. We start by laying the technical foundation so that progress isn't blocked later by misaligned interfaces.
UI Design
The UI Design doc translates the pitch's rough solution sketch into concrete, screen-level detail. It answers: what exactly will the user see and do?
Organise it by screen — not by feature, not by user story. Each screen the bet touches gets its own section with:
- A wireframe — even a rough sketch. This is the anchor; the text describes it.
- Layout — the regions on screen and what content lives in each one.
- States — what the user sees during loading, active use, empty states, errors, and degraded conditions.
- Key interactions — what the user can do and what happens in response.
After the screens, map the user journeys between them (how the user moves from entry point to final outcome), and list edge cases (anything unusual the system needs to handle visibly).
Be specific about data objects. If a screen shows tasks, define what a task is: which fields it has, which are required, whether they nest, what states they can be in. If a screen has a text editor, say whether it's rich text or plain, whether it auto-saves or has a save button. These details directly determine the API contracts and database schema that come next.
Stay at the user level. If you're specifying which service owns the logic, how the frontend integrates, or where data persists — you've gone too far. The UI Design doc describes what the user experiences, not how the system delivers it. System concerns belong in the Data Flow doc.
The output feeds directly into: Data Flow diagrams (which service calls which), API contracts (what fields and endpoints exist), and database schemas (what gets stored). If someone can't design those artefacts from the UI Design doc alone, the doc isn't detailed enough.
Reviewing a UI Design
| Check | What to verify |
|---|---|
| Every screen traces to the pitch | No screen appears that wasn't implied by the pitch's proposed solution. |
| States are complete | Every screen has loading, active, empty, and error states at minimum. Features with live connections have per-failure-mode states (Connecting, Degraded, Connectivity Lost, Reconnected). |
| Data objects are specified | Fields, required status, nesting, states, and editing behaviour are defined for every data type shown on screen. |
| Interactions stay user-level | No service names, endpoint paths, or persistence details. "The task appears in the list" not "Core returns 201." |
| User journeys cover branches | Happy path AND error/recovery branches are mapped. |
| Downstream derivability | A data flow designer can derive every service boundary from this document alone. |
Common pitfalls:
- Feature-oriented organisation: Grouping by feature ("Recording feature") instead of by screen. Screens are the unit of user experience; features span screens.
- Missing empty and error states: Only the happy path is described.
- Vague data objects: "The screen shows tasks" without defining fields, states, or editing behaviour. This ambiguity cascades into vague contracts and schemas.
- Implementation leaking in: "Core sends a WebSocket event" or "The SWR cache is invalidated." UI Design describes what the user sees, not how the system delivers it.
Data Flows
The Data Flow doc maps every user interaction from the UI Design through service boundaries. It answers: what calls what, what data crosses each boundary, and what happens when something fails. It is the primary input for API contracts and database schemas — if someone can't design those artefacts from this doc alone, the doc isn't complete.
Start with a system context graph. Before drawing any sequences, draw the topology: which services exist, which protocols connect them, which data stores each service owns. This is a static map — it orients readers and makes the scope of the bet explicit.
Name flows after what triggers them. Group related flows into logical Parts (e.g., "Session Lifecycle", "Streaming Processing", "Failure Modes"). A flow name describes what the user does or what system condition fires — not the implementation.
Use descriptive operation labels — never endpoint paths. Diagram labels should read like Create task (idempotent, echo-suppressed) not POST /meetings/{id}/tasks. Header names, field names, and HTTP methods all belong in the Contracts doc. Each arrow in a flow is a contract boundary (what shape the data takes) and a sequencing constraint (downstream cannot build until upstream is agreed). Naming the operation is enough — the Contracts doc defines the shape precisely.
Failure modes are required, not optional. For every significant service boundary in the bet, there must be at least one flow describing what happens when that boundary fails. If the UI Design doc models a "Degraded" or "Connectivity Lost" state, the Data Flow doc must show the recovery sequence. Resilience is a first-class design concern — not an afterthought.
Close with two required sections:
- Design Decisions — tradeoffs made, alternatives ruled out, constraints that drove choices. Captures reasoning that isn't visible in the diagrams.
- Boundary Inventory — a table of every service-to-service boundary in the doc. Five columns: Boundary | Flows | From → To | Protocol | Data shape. Each row here becomes a contract entry in the Contracts doc.
Reviewing a Data Flow
| Check | What to verify |
|---|---|
| System context matches scope | Every node in the topology appears in at least one flow. No phantom services. |
| Every flow traces to a UI interaction | No flow exists without a triggering user action or system event from the UI Design. |
| Labels are descriptive, not implementation | No endpoint paths, HTTP methods, header names, or field names in diagram labels. |
| Failure modes are present | Every significant service boundary has at least one failure flow. UI "Degraded" states have matching recovery flows here. |
| Design decisions explain tradeoffs | Each decision names what was considered and why the chosen option won — not just "we chose X." |
| Boundary inventory is complete | Every service-to-service call in every flow appears in the boundary inventory. |
Common pitfalls:
- Implementation in diagram labels:
POST /meetings/{id}/tasksorAuthorization: Bearerappearing in sequence diagrams. Use descriptive labels; push implementation to Contracts. - Missing failure modes: Only happy-path flows are drawn. This is the most common defect.
- Incomplete boundary inventory: Flows show 8 service calls but the inventory lists 5. The gap means 3 contract boundaries are invisible.
- Design decisions without alternatives: "We chose WebSocket" without explaining what was considered (HTTP polling, SSE, HTTP streaming) and why WebSocket won.
Contracts & Schemas
The agreed API contracts (REST, WebSocket, Pub/Sub) and database schemas (PostgreSQL, object storage). Downstream UI can mock against the contract; upstream Core can build against it.
Choose the protocol by the interaction pattern:
| Protocol | Use when |
|---|---|
| REST | Caller needs a clear success/failure response and the receiver owns resulting state. |
| WebSocket | Interaction is bidirectional, low-latency, or session-oriented. |
| Pub/Sub | Fire-and-forget event notification. Producer doesn't wait for consumer. |
All Wordloop contracts share these semantics:
| Concern | Contract |
|---|---|
| Auth | bearerAuth for user-facing; service auth / mTLS for service-to-service |
| Trace context | Forward traceparent / tracestate |
| Idempotency | All creating or side-effecting retryable POST operations require Idempotency-Key |
| Echo suppression | User mutations accept Client-Session-Id when WebSocket echoes exist |
| Errors | RFC 9457 application/problem+json |
Schema design conventions:
- TEXT + CHECK over PG enums — allows adding/removing values without a migration.
- FK indexes are mandatory — PostgreSQL does not auto-index foreign key columns. Every FK carries an index.
- JSONB for write-once-read-few — genuinely dynamic structure only. If individual keys are queried, filtered, or joined on, normalize into columns.
- Append-only audit tables — status transitions tracked in a separate history table with
(record_id, created_at)index.
Reviewing Contracts
| Check | What to verify |
|---|---|
| Every contract traces to the boundary inventory | No contract without a matching row. No boundary inventory row without a contract. |
| Shared semantics are applied | Auth, trace context, idempotency, echo suppression, and error format specified per operation. |
| Idempotency is explicit | Every side-effecting operation states its deduplication key. |
| Error responses use RFC 9457 | REST errors return application/problem+json with type, title, status, detail. |
| WebSocket reconnection is specified | Replay cursor, reconnect strategy, duplicate handling documented. |
| Example payloads are realistic | Field values are realistic, not placeholders like "string" or "example." |
Reviewing Schemas
| Check | What to verify |
|---|---|
| Every table traces to a data flow | No table without a justifying persistent store in the data flow. |
| State machines are diagrammed | Tables with lifecycle states have a state diagram showing transitions and terminal states. |
| Every FK has an index | Foreign key columns have corresponding indexes. |
| JSONB is justified | Every JSONB column explains why normalisation was rejected. |
| Index rationale is documented | The index design table explains which query each index serves. |
| Naming is consistent | Table and column names match the terminology in contracts and data flow. |
4. TDD: Execution
Once the technical foundation is set, the bet is decomposed into deliverable units.
- Integration Milestones: Points of user-visible value. This is the integration of multiple pieces that results in a cohesive feature or state change for the user.
- Domain Slices: The smallest independently buildable and testable units of work. We never slice horizontally (e.g. building all databases, then all APIs, then all UI). We always slice vertically. A vertical slice could be a full feature connecting App -> Core -> ML, or a complete vertical slice completely within a single domain (e.g., being able to do CRUD on a Meeting in Core via the API). Slices must be independently deployable and verifiable.
Designing milestones
Order milestones by integration value. The first milestone delivers the simplest end-to-end flow that proves the architecture works; later milestones add richness. Each milestone must be independently shippable — users get value from milestone 1 even if milestone 2 never ships. If milestone 1 only produces database tables and milestone 3 adds the UI, that is horizontal slicing disguised as milestones.
Dependencies flow forward. Milestone 2 may depend on milestone 1, but never the reverse.
Reviewing a Milestone
| Check | What to verify |
|---|---|
| Goal describes user-visible value | Reads as an observable outcome, not a list of technical tasks. |
| Ordering has a rationale | "Why This Comes Now" explains dependencies and what this milestone unblocks. |
| Scope is precise | A reader can tell whether a piece of work belongs in this milestone or another. |
| Not Included names natural extensions | Exclusions include capabilities a reader would expect here but that belong later. |
| Slices are ordered by dependency | Prerequisites are explicit. Slice 1 must be mergeable before Slice 2 starts (unless independent). |
| Acceptance criteria are observable | Each criterion can be verified by running the system — no source code reading. |
Anatomy of a well-written slice
A slice that guides an AI agent or engineer to build the right thing has six parts:
- Owner / Domain / Complexity / Prerequisite callout — one line each. Complexity (S / M / L) signals the build window. Prerequisite names the exact prior merge gate — "Slice 1 merged +
./dev gen all" is specific enough to act on; "after Core" is not. - One-paragraph intro — what does this vertical capability achieve, and why is it the right unit of work? Links to the milestone.
- Required Capabilities — an unchecked task list, grouped by logical area when the domain has distinct concerns (e.g. Schema / API / Events for a Core slice). These become the implementation checklist. Each item is a falsifiable statement of behaviour, not a vague description.
- Dependencies — concrete merge or configuration gates. If a generated client must be up to date, say "
./dev gen allrun after Slice 1 merged". - Domain-specific section — one of:
- Core: Schema Notes table (new/modified tables, key columns, index rationale)
- ML: Pipeline Sequencing diagram (stage order, transition triggers, failure handling)
- App: UI States table (state name, trigger condition, what the user sees)
- Test Cases — a table with
Test | Location | Assertioncolumns.Locationis one oftest_core,test_ml,test_app,test_system. Assertions are specific and falsifiable ("returns 201 with Location header", not "works correctly"). These rows map directly to the generated test stub intests/bets/<slug>/test_slice_<domain>_<slice>.py.
What a slice is not: A slice is not a summary of the contracts doc, not a user story, not a list of files to change. It is a vertical capability specification that tells an agent exactly what to build, in what order, and how to verify it is done.
The vertical slicing test: Can this slice be deployed to production and verified without any future slice existing? If yes, it is vertical. If it requires a downstream slice to be useful, it is either too thin or horizontally sliced.
- Vertical (correct): "Upload audio file" slice — includes storage schema, upload endpoint, GCS integration, and API response. Deployable and verifiable on its own.
- Horizontal (wrong): "Database schema" slice → "API endpoints" slice → "Frontend upload" slice. Nothing works until the last slice ships.
Falsifiable capabilities: Each item in Required Capabilities must be testable as true or false.
- Good: "
POST /meetings/{id}/audioreturns 202 with a Location header pointing to the recording resource." - Bad: "Audio handling is implemented."
Specific test assertions: Each row in the Test Cases table must name the exact expected outcome.
- Good: "Returns RFC 9457 problem+json with status 409 for duplicate Idempotency-Key."
- Bad: "Handles duplicates."
Reviewing a Slice
| Check | What to verify |
|---|---|
| Header is complete | Owner, domain, complexity, and prerequisite specified. Prerequisite is an exact merge gate. |
| Intro describes target state | What the system does when complete — not the changes from current state. |
| Capabilities are falsifiable | Each item can be verified as true or false. No vague descriptions. |
| Capabilities trace to contracts | Every API-facing capability references a contract endpoint. Every schema capability references a schema definition. |
| Dependencies are concrete | Merge gates name the exact slice and post-merge steps (e.g., ./dev gen all). |
| Domain section matches domain | Core has Schema Notes, ML has Pipeline Sequencing, App has UI States. |
| Test cases have specific assertions | Every row has a falsifiable assertion. |
| Slice is vertical | Deployable and verifiable independently. Does not require a downstream slice. |
Bet Test Suite
Every milestone and slice has a corresponding test in the bet progress suite — a set of system-level tests that prove delivered capability. These tests are the single source of truth for bet progress. Red means work to do; green means proven.
How the bet test suite works:
- When a milestone or slice is scaffolded via
./dev new milestoneor./dev new slice, empty test stubs are generated intests/bets/<slug>/. - Test stubs are filled in as part of slice execution, verifying observable end-to-end outcomes.
- Run the full suite on demand with
./dev test bet <slug>to see an at-a-glance progress report: which milestones are complete, which slices within the current milestone are done, and which are still red. - These tests are system-level only — they exercise the running system end-to-end, not individual units. They are manually triggered because they are slow (they start services, hit real databases, call real APIs).
- Because they test integration outcomes, they can be written before the production code exists. The test describes the target behaviour; the implementation makes it green.
Lifecycle:
- During the bet — the suite tracks progress. A passing suite means the milestone or slice is provably done.
- After a slice is complete — full test coverage is implemented according to the project's testing strategy: service perimeter tests, unit tests for complex logic, and system tests as appropriate. These permanent tests live in the service repos, not the bet suite.
- After the bet is delivered — the bet test suite is archived via
./dev archive bet <slug>. It moves totests/bets/_archive/<slug>/. These tests are not maintained going forward — the features are absorbed into the system and covered by permanent service tests.
Two layers of testing:
| Bet progress suite | Service and system tests | |
|---|---|---|
| Location | tests/bets/<slug>/ | Service repo or tests/system/ |
| Lifecycle | Temporary — archived with bet | Permanent — stays in codebase |
| Scope | End-to-end integration outcomes | Perimeter, unit, contract, system |
| Happy path | Yes | Yes |
| Error handling | Minimal | Thorough |
| Edge cases | Rarely | Yes |
| Observability | No | Yes (trace validation) |
| Contract compliance | No | Yes (consumer-driven) |
Test design principles:
- Test the target state. Tests describe what the system does when the bet is done. Write the test as if the feature already exists.
- System-level only. Bet tests make HTTP requests and verify end-to-end flows. They do not import application code or mock dependencies.
- Specific and falsifiable. Every assertion maps to a row in the slice's Test Cases table.
- Written before the code exists. The test describes target behaviour; the implementation makes it green.
Completing a Slice
A slice is not done when the code works. A merged slice means the capability is shipped, tested, reviewed, and documented. The following checklist applies to every completed slice:
- Code merged and deployed — the slice is running in the system, not sitting in a branch.
- Bet test green — the corresponding bet progress tests pass via
./dev test bet <slug>. - Permanent tests implemented — full service-level test coverage per the testing strategy. Service perimeter tests (default), unit tests (complex logic), system tests (cross-service paths).
- Code review — peer review of implementation quality, adherence to architectural principles, and consistency with the slice spec.
- API review — any new or modified API surfaces reviewed for consistency with contracts, error handling, and naming conventions.
- Testing review — test coverage reviewed for completeness: happy paths, error paths, edge cases, and observability assertions.
- Documentation updated — system documentation that is affected by this slice is brought up to date:
- Architecture and service descriptions (if the slice changes system topology or responsibilities)
- Data flow documentation (if new boundaries or protocols are introduced)
- API reference (auto-generated from specs where possible, manually updated where not)
- Database reference (if schema changes are included)
- Runbooks and operational guides (if new failure modes or operational concerns are introduced)
Writing Guidelines
Bet documentation is read by engineers and AI agents under time pressure. Every sentence should earn its place.
Describe the Target State
All bet documentation — pitches, TDD docs, milestones, slices — describes the target state of the system. There are no diffs, no gap analyses, no references to what already exists or what needs to change. Just a clear description of how the system works when the work is done.
This simplifies consumption. A reader should be able to pick up any document and understand the end goal without needing to know what the system looks like today. When designing the target state, build on top of what already exists to avoid excessive drift, but the documentation itself does not express the current state, the target state, and the delta between them. That analysis happens during slice execution as part of the implementation plan — it does not live in these docs.
Do:
- "The meeting detail page shows a live transcript panel that updates as segments arrive."
- "
POST /meetings/{id}/audiostores the file to GCS and publishes a transcription.requested event."
Don't:
- "Currently, meetings don't support audio upload. We need to add a new endpoint..."
- "The existing meeting list page will be extended to include..."
- "Unlike the current implementation, the new version will..."
Tone and Style
- Direct and declarative. State what the system does, not what it should or could do. "The upload endpoint returns 202" not "The upload endpoint should return 202."
- Concrete over abstract. Name the endpoint, the field, the state, the event. Specificity prevents ambiguity.
- Short sentences. One idea per sentence. Break complex statements into separate bullets or rows.
- No filler. Cut words like "basically", "essentially", "in order to", "it is important to note that". If a sentence works without the word, remove it.
- Active voice. "The service publishes an event" not "An event is published by the service."
- Consistent terminology. Use the same term for the same concept everywhere. If it's a "segment" in the contract, it's a "segment" in the slice, the milestone, and the test case. Don't alternate between "segment", "chunk", and "piece".
Structure for Progressive Exposure
Documents should reward scanning. A reader should get the key message in 10 seconds, the full picture in 2 minutes, and the details on demand.
- Frontmatter — title, description, status, and ownership. Enough to decide whether to read further.
- Opening line or paragraph — the goal or purpose in one or two sentences. No preamble.
- Primary sections — the main content, ordered by importance. The most critical information comes first.
- Detail sections — tables, test cases, schema notes, domain-specific content. Readers arrive here when they need to implement or verify.
Use tables for structured, repeating information (test cases, schema columns, states). Use bullet lists for sequential or grouped items. Use prose only when relationships between ideas matter more than the individual items.
Document Chain Integrity
Each document in the bet lifecycle consumes its upstream and produces for its downstream. When this chain breaks — a data flow that invents boundaries not in the UI design, or a slice with test cases that don't trace to milestone acceptance criteria — the bet has a structural defect. Review is the practice of verifying the chain holds.
| Document | Upstream check | Downstream check |
|---|---|---|
| Problem Statement | Is the pain real, evidenced, specific? | Does the pitch restate this problem (not a different one)? |
| Pitch | Does it solve the stated problem within the appetite? | Do TDD success criteria map to the pitch's solution? |
| UI Design | Does every screen trace to a capability in the pitch? | Can the data flow be derived from these screens alone? |
| Data Flow | Does every flow trace to a UI interaction? | Does the boundary inventory account for every service call? |
| Contracts | Does every contract trace to the boundary inventory? | Do slice capabilities reference these contracts? |
| Schemas | Does every table trace to a persistent store in the data flow? | Do slice schema notes reference these tables? |
| Milestones | Do acceptance criteria trace to TDD success criteria? | Does every slice belong to exactly one milestone? |
| Slices | Do capabilities trace to contracts and schemas? | Do test cases trace to milestone acceptance criteria? |
Bet Operations
By utilizing the Golden Path CLI tools, documentation is kept exactly in sync with the integration testing layout.
Start a new bet
./dev new bet <slug>Promotes a pitch into an active bet at work/<slug>/ and creates the baseline test boundary suite in tests/bets/<slug>/. The slug must be lowercase kebab-case (e.g. speaker-navigation). A pitch must exist first — run ./dev new pitch <slug>.
Scaffolding Architecture (TDD)
# Scaffolds architectural boundaries
./dev new contract <bet-slug> <service> <protocol>
./dev new schema <bet-slug> <service> <database-tech>
# Scaffolds milestones and domains
./dev new milestone <bet-slug> <milestone-slug>
./dev new slice <bet-slug> <milestone-slug> <domain> <slice-slug>Generating a slice or a milestone will drop corresponding placeholder testing boundaries in tests/bets/.
Run bet progress tests
./dev test bet <slug>Runs the bet progress suite on demand. Watch the test output to verify that your delivery is progressing as intended.
Archive a delivered bet
./dev archive bet <slug>Moves the bet directory to _archive/ and the associated test suite to tests/bets/_archive/<slug>/. URL routing is preserved.