What Nebula Swarm Produces Before a Line of Code

One paragraph from a founder goes in. Before any agent writes code, Nebula Swarm turns it into a PRD, architecture and UX constraints, a list of decisions only you can make, and a ticket plan in dependency order. This is that output for one realistic feature, trimmed to fit a page.

Sample The company, the feature and every number on this page are made up to show the format. This is not a customer's document.

Feature
Bulk CSV Order Import
Company
Northwind Freight (fictional B2B SaaS)
Prepared by
Sidera Labs with Nebula Swarm

The Request, Exactly as the Founder Sent It

"Our bigger customers keep emailing us spreadsheets of orders and support types them in by hand. Let them upload a CSV instead, up to about 2,000 orders. They should see a preview first, with anything wrong clearly flagged, and only the rows they approve should turn into orders. And please make sure we don't end up with duplicate order numbers. That's the thing support complains about most."

Founder and CEO, Northwind Freight (fictional) · sent as a Slack message

That's the whole input. Everything below was produced from it, plus answers to the questions in Open Decisions, below.

Step 1. You Click Through the Screens Before Anyone Plans the Build

Nebula Swarm makes clickable mockups and a small design system first, so you approve what the customer sees before the PRD is written. On the real download these are live screens.

Upload and preview

Screen 1 of 2[clickable mockup goes here]

Drop zone, template download, parse progress, then the first rows with a flagged count.

Review flagged rows and approve

Screen 2 of 2[clickable mockup goes here]

Filter to flagged rows, reasons in plain words, a duplicate badge, one approve action and a downloadable error file.

Step 2. The PRD: What We're Building and How We'll Know It Worked

Written by the product-manager agent in the harness's fixed section order, then merged from several drafts written from different angles (pragmatic, user-first, ambitious) into one gold version.

nebula · reduce/backlog_gold_v2.md
<!-- { "artifact_type": "prd", "stage": "requirements", "agent_type": "ProductManager",
      "run_id": "2026.10.09-10.14.02-prd", "status": "complete", "lens": "gold" } -->

Problem statement

Customers with more than about 50 orders a day send spreadsheets to support, who type each order in by hand. It takes about 45 minutes per 500 orders, causes typos in addresses, and creates duplicate orders when the same sheet is sent twice. The biggest accounts are the ones feeling it most.

Users and personas

  • Dana, operations lead at a 40-person merchant. Exports orders from her ERP each morning. Wants them in Northwind before the 10 a.m. carrier pickup, and to know which ones didn't make it.
  • Marcus, Northwind support agent. Currently re-keys those sheets. Wants to stop, and to be able to see what a customer imported when they call.

Goals and success metrics

< 5 min

To load 500 orders, from upload to committed. Today it's about 45 minutes of support time.

import_started → batch_committed, p75
0

Duplicate orders created through import in the first 90 days.

orders with same tenant + order_no
≥ 90%

Of import batches committed without a support ticket about that batch.

batches vs. tickets tagged "import"

User journey (primary, MVP)

  1. Open Orders → Import CSV. Download the template if needed.
  2. Upload a file. Fails if: not a CSV, over 5 MB or over 2,000 rows. The message says which and how to fix it; nothing is stored.
  3. Wait for the preview. Progress shows rows checked so far.
  4. Review. Every row is Ready, Error (with the field and reason) or Duplicate. Filter to flagged rows only.
  5. Approve. Ready rows are selected by default; the customer can deselect any. Error and duplicate rows can't be approved.
  6. Import. Only approved rows become orders. If interrupted: the import resumes and never creates an order twice.
  7. See the result. Counts for created and skipped, a link to the new orders, and an error CSV to fix and re-upload.

Functional requirements and acceptance criteria

  • R1

    Upload a CSV of up to 2,000 orders MVP

    • Given a UTF-8 CSV with 2,000 data rows and ≤ 5 MB when uploaded then a preview is created.
    • 2,001 rows, > 5 MB, or a non-CSV file is rejected before parsing, with a message naming the limit.
  • R2

    Download a template MVP

    • The template has the required headers, one example row and a notes row explaining each field.
  • R3

    Validate every row MVP

    • Checks required fields, ZIP/postcode format, weight > 0 and known service codes, using the same rules as manual order entry.
    • Each error names the row, the column and the fix ("ZIP is required").
  • R4

    Preview with bad rows flagged MVP

    • Every row shows Ready, Error or Duplicate with an icon and text, not color alone.
    • A "Flagged only" filter shows just Error and Duplicate rows; the count matches the summary.
  • R5

    Detect duplicate order numbers MVP

    • Given an order number that already exists for this customer then the row is flagged Duplicate and links to the existing order.
    • Given the same order number twice in one file then the first is Ready and later ones are Duplicate.
  • R6

    Approve rows; only approved rows become orders MVP

    • Ready rows are pre-selected; any can be deselected. Error and Duplicate rows can't be selected.
    • The orders created equal the approved rows exactly, by count and order number.
  • R7

    Commit safely, even when interrupted MVP

    • Pressing Import twice, or a worker restart mid-import, never creates an order twice.
    • An order created by someone else after preview is caught at commit time and skipped as Duplicate.
  • R8

    Result summary and error file MVP

    • Shows created and skipped counts; the error CSV contains only skipped rows, plus a "reason" column, and re-uploads cleanly once fixed.
  • R9

    Import history for support MVP

    • Support can see each batch: who uploaded it, when, the counts, and the orders it created.
  • R10

    Map custom column names Later

    • Deferred: let customers map their own headers. MVP accepts the template headers plus a short list of common aliases.

Non-functional requirements

AreaTarget
PerformancePreview of 2,000 rows ready in under 10 s (p95). Commit of 2,000 rows in under 60 s.
ReliabilityCommit is idempotent and resumable. No half-created orders.
PrivacyFiles hold customer addresses: tenant-isolated storage, raw file deleted after 7 days, no addresses in logs.
SecurityFile type checked by content, not just extension. Error CSV is escaped against spreadsheet formula injection.
AccessibilityWCAG 2.2 AA. The preview table can be used with the keyboard and a screen reader.
CostNo new paid services. Background work runs on the existing job queue.

Analytics and telemetry

import_started · preview_ready (rows, flagged, ms) · rows_deselected · batch_committed (created, skipped, ms) · error_csv_downloaded

Non-goals (out of scope)

  • Excel (.xlsx) files, SFTP or scheduled imports.
  • Updating existing orders from a file. Import only creates new orders.
  • Editing rows inside the preview. Customers fix the file and re-upload.
  • Files over 2,000 rows. Those customers use the API.

Harness artifact: reduce/backlog_gold_v2.md · traceability matrix maps every sentence of the request to R1–R10

The Rules Every Ticket Has to Follow

The architect and UX agents write these, and they're attached to the backlog before it's split into tickets. Shortened here.

Architecture

  • Clear ownership. The import module owns batches and rows. It creates orders only through the orders module's existing create function, never by writing to the orders table.
  • Async by default. Parsing and commit run as background jobs; the browser polls for progress.
  • Idempotency key per row: customer + batch + row number. A unique index on customer + order number is the final guard.
  • Failure modes named. Worker crash resumes from the last committed row; a malformed file fails the whole preview with one clear reason.
  • Limits enforced on the server, not only in the browser.

reduce/architecture_gold.md

UX

  • Every state is designed: empty, uploading, checking, preview, partly flagged, all flagged, importing, done, failed.
  • Error copy names the problem and the fix, in the customer's words, not field IDs.
  • Status uses icon plus text, never color alone.
  • The 2,000-row table stays fast: virtualized rows and keyboard navigation between flagged rows.
  • Built from the approved design system and its tokens; no one-off styles.

reduce/ux_spec_gold.md

Step 3. Six Decisions Only You Can Make

Agents shouldn't guess at product calls. Nebula Swarm challenges the plan, lists what's still open, and gives each question options and a recommendation. Nothing gets built until you answer. Most take a minute.

  1. D1 When a row's order number already exists, what happens?

    The founder's top worry. It affects R5, R7 and the support load.

    • AFlag as Duplicate and skip; link to the existing order. Recommended
    • BOverwrite the existing order with the file's values.
    • CImport it anyway with a suffix (NW-10007-2).

    Why A: it can't damage live orders, and updating orders is a separate feature.

  2. D2 If some rows have errors, can the rest still be imported?

    Sets the shape of the approve step.

    • AYes. Import approved, valid rows; skip the rest with an error file. Recommended
    • BNo. The whole file must be clean before anything is imported.

    Why A: it matches the request ("only the rows they approve") and avoids a 2,000-row file being blocked by one typo.

  3. D3 Should the import run while the customer waits, or in the background?

    Sets the architecture and the "importing" screen.

    • AIn the request; the page waits until it's done.
    • BBackground job with a progress bar; safe to close the tab. Recommended

    Why B: 2,000 rows can outlast a web request timeout, and a job can resume after a crash.

  4. D4 Is 2,000 rows a hard limit for everyone?

    The request said "about 2,000".

    • AHard 2,000 rows and 5 MB for all plans at launch. Recommended
    • BLimit by plan (e.g. 500 / 2,000 / 10,000).
    • CNo limit; split large files into several jobs.

    Why A: one number to test and to explain. Revisit with usage data after 30 days.

  5. D5 Do customers have to use our column names?

    Decides whether R10 is in this release.

    • AOur template, plus common aliases ("Zip", "Postal Code"). Recommended
    • BA column-mapping screen in this release.

    Why A: saves two tickets now. Mapping becomes R10 if error files show header mismatches.

  6. D6 How long do we keep the uploaded file?

    The file contains customer addresses.

    • ADelete it as soon as the import finishes.
    • BKeep it 7 days for support, then delete; keep the row-level history. Recommended
    • CKeep it as long as the account exists.

    Why B: support can still help with "what did I upload?" without keeping addresses longer than needed.

Your answers are written back into the PRD and the ticket specs, with the date, so the agents read the decision, not a guess. Harness artifact: Open Decisions (not decided here, recommendation given, you decide) in each task spec.

Step 4. Ten Tickets, in the Order They Can Be Built

The dev-manager agent splits the PRD into small tickets, each with its own acceptance criteria and dependencies, and orders them so as many as possible run at once. The shared contract comes first, so the API, backend and screens can be built in parallel against it.

  • 10Tickets, sized XS to M.
  • 4Built in parallel in wave 1.
  • 6Waves from start to rollout.
  • 6Tickets on the critical path.

Scroll sideways to see the whole plan →

Ticket dependency diagram T001 comes first. Then T002, T003, T005 and T008 run in parallel. T004 needs T002. T007 needs T003 and T005. T006 needs T003 and T004. T009 needs T006, T007 and T008. T010 needs T009. Critical path: T001, T002, T004, T006, T009, T010. Backend API UI Ops Wave 0 Wave 1 Wave 2 Wave 3 Wave 4 Wave 5 T001 · SImport contract T002 · MParse + validate T003 · MUpload + preview T005 · MUpload screen T008 · SHistory + events T004 · SDuplicate check T007 · MReview + approve T006 · MCommit job T009 · S2,000-row E2E T010 · XSFlag + rollout
  • Critical path
  • Depends on
  • Shared (contract or integration)
Each row is a parallel lane; each column is a wave that can start once the waves before it are done. Dashed boxes are shared across lanes. Scroll sideways on a small screen.

Scroll the table sideways →

IDTicketSizeDepends onLane · waveCovers
T001 (critical path)Import contract and data modelBatch and row tables, API shapes, fixtures for the UI to build againstSNoneShared · 0R1–R9
T002 (critical path)CSV parser and row validatorStreaming parse, template headers and aliases, manual-entry rules reusedMT001Backend · 1R1 R3
T003Upload and preview APISize, row and type limits on the server; progress pollingMT001API · 1R1 R2 R4
T005Upload and preview screenDrop zone, template link, progress, first rows; built against T001 fixturesMT001UI · 1R1 R2 R4
T008Import history and telemetrySupport view of batches; the five events in the PRDST001Ops · 1R9
T004 (critical path)Duplicate order-number detectionAgainst existing orders and within the file (D1)ST002Backend · 2R5
T007Flagged-row review and approveFilter, reasons, selection rules, virtualized table, keyboard pathMT003 T005UI · 2R4 R6
T006 (critical path)Commit jobIdempotent, resumable, re-checks duplicates at commit; result and error CSVMT003 T004Backend · 3R6 R7 R8
T009 (critical path)End-to-end test with a 2,000-row fileHappy path, flagged rows, crash mid-commit, performance budgetST006 T007 T008Shared · 4All
T010 (critical path)Feature flag and rolloutOff by default; on for three pilot customers, then everyoneXST009Shared · 5-

Ember dot = on the critical path. Each ticket becomes a Jira issue (or a local task file) with sections for description, user value, scope, acceptance criteria, technical notes and open decisions, and an implementation checklist. Harness artifacts: reduce/tasks_gold.json, task_dag.md, final/tasks/T*.md.

Every Requirement Has a Test Before It Has Code

The tester agent maps each acceptance criterion to a named test. A ticket isn't done until its tests pass and the reviewer has seen them.

Scroll the table sideways →

ReqWhat's provenTestsTypeTicket
R1Limits are enforced on the serverrejects_2001_rows · rejects_over_5mb · rejects_renamed_xlsxUnit, APIT002 T003
R2Template round-tripstemplate_parses_cleanUnitT003
R3Each rule gives row, column and fixvalidator_rules_table (14 cases)UnitT002
R4Flags are visible and filterable without colorpreview_flagged_filter · status_has_text_label · axe_previewComponent, a11yT005 T007
R5Duplicates caught in DB and in filedup_existing_order · dup_within_file_first_winsIntegrationT004
R6Created orders equal approved rowsonly_approved_rows_created · error_rows_not_selectableIntegration, E2ET006 T007
R7No double orders on retry or crashdouble_submit_idempotent · worker_kill_resumes · race_dup_at_commitIntegrationT006
R8Error CSV is correct and safeerror_csv_only_skipped · formula_injection_escapedUnitT006
R9Support sees every batchhistory_lists_batch · events_emittedIntegrationT008
NFR2,000 rows: preview < 10 s, commit < 60 sperf_2000_rowsE2ET009

Step 5. What Happens After You Approve the Plan

  1. Each ticket is built on its own branch Agents Agents pick up tickets whose dependencies are done, each in an isolated copy of the repo. Wave 1's four tickets run at the same time, overnight if you like.
  2. A separate agent reviews every change Reviewer agent It didn't write the code. It checks the change against the ticket's acceptance criteria, the constraints and the tests, and sends it back if anything is missing.
  3. A human merges You Every change arrives as a pull request with passing CI and a review. Nothing reaches main until someone on your team merges it.

Lessons from each ticket are written to the project's memory and read before the next one starts.

Get This for Your Next Feature

Send us one paragraph about a feature on your roadmap. On a scoping call we'll walk through what Nebula Swarm would produce for it, using your codebase and your Jira, and tell you plainly whether it fits your team.

Book a Scoping Call [Download This Sample as PDF: free, no form; link target TBD]