Skip to content

Implementation slice

The protocol for scoping and running a unit of work inside a session.

Phase 1 — Scope before build

Before writing code, propose to the user:

  • In scope — exactly what the slice will deliver
  • Out of scope — what's deferred to later slices, named explicitly
  • Done criteria — checkable conditions (a/b/c…) that prove the slice landed
  • Time estimate — honest order-of-magnitude
  • Risks — the things that could surface as real stops

The user confirms or corrects the scope before any code is written.

Phase 2 — Caution-vs-execution distinction

Inside a confirmed slice, run end-to-end without checking in mid-slice. Be cautious at slice boundaries and architectural hinges; run inside.

Real stop conditions

Stop and surface to the user when something genuinely architectural emerges — things that change the slice's contract, regress shared surface, or invalidate an ADR specific. Real stops can land before scope is locked (during prep), mid-slice, or post-execution.

Variety from ADR-0005 Slices 2 and 4:

  • Pre-scope, ADR-spec gap (Slice 2): wrangler r2 object put exposes no --metadata flag. ADR-0005 §6 specifies x-amz-meta-original-name on every upload. Real stop because the auth path the user picked literally can't honour §6 as written. Surfaced before scope lock with a recommendation; scope updated.
  • Pre-scope, test-corpus assumption (Slice 2): the test corpus the user named wasn't in the working tree. Real stop — surface alternatives, let the user pick.
  • User-imposed prep step (Slice 2): the user required a 10-minute idempotency probe before writing any helper code, with a real-stop fallback. Honour imposed prep — it's load-bearing for downstream slices.
  • Post-execution, perf finding (Slice 2): wrangler-shellout was 8s/image, ~640 hours single-threaded for the portfolio. Real stop in the sense that it changed slice ordering — Slice 4 (SDK swap, new addition) inserted ahead of Slice 3.
  • Mid-slice, architectural fix fails for an orthogonal reason (Slice 4): the HTTP/2 hypothesis ("HTTP/1.1 connection-pool contention") had a corresponding fix queued. Tried the fix; R2's S3-compatible endpoint rejected HTTP/2 with ERR_HTTP2_ERROR. Real stop because the failure didn't test the hypothesis — it blocked the test. Wrong move: pivot to the next item on the option list. Right move: re-diagnose. (See known-patterns.md "Architectural fix fails for a reason orthogonal to the hypothesis".)
  • Mid-slice, sweep result on the wrong side of a hard target (Slice 4): parameter sweep across concurrency = [50, 100, 200, 500, 1000] showed flat throughput at ~50–70 PUT/sec, projecting ~70–110 min for the 290k-image portfolio against a hard 30-min target. Real stop because the user had explicitly named throughput miss as go/no-go in the scope-confirmation message. Surfaced with the curve data and the option set; user-directed deferral.
  • Strategic-deferral as a real-stop close-out (Slice 4): when an ADR-spec'd target is missed and the user directs deferral rather than continuation, the slice closes "mostly complete" with the open sub-issue explicitly captured: deferral contract (trigger conditions for reopen) in known-issues.md, sub-issue noted in the ADR's Slice tracker.

False stops

Resolve these yourself; don't surface. Examples from Slice 2:

  • "Should the helper live at apps/cms/scripts/upload-image.mjs or somewhere else?" (location convention; pick and move on)
  • "Slugify lib leaves underscores and doesn't collapse all-_ to empty — should I switch libs?" (no — ADR §3 specifies the contract; post-process to match. See known-patterns.md "Lib doesn't quite match ADR".)
  • A logic bug in the validator's sample-collection block — fix and move on, don't ask.
  • "Which content-type for .avif?" (look it up; pick; move on)

If it doesn't change the design, regress shared surface, or invalidate an ADR, decide and move on.

Phase 3 — Regression check on shared primitives

When a slice touches code shared by multiple consumers (canonical primitives consumed by both CMS adapters and per-site assembler), the regression check is non-negotiable: list the consumers, exercise one of each, confirm no visual regression.

This is the "same canonical, two consumers, both must work after" rule.

If the slice is a new standalone surface — like Slice 2's apps/cms/scripts/upload-image.mjs, which is invoked from CLI and a validator only — declare the regression check N/A in the wrap-up. "N/A because no shared surface touched" is a fine answer; "I forgot to check" is not.

Phase 4 — End-to-end execution without mid-slice check-ins

Once the scope is confirmed and you're not at a real stop, run the slice through to done without asking permission for false-stop questions. Mid-slice "is this OK?" interruptions are friction without value.

Example of the protocol applied

Slice 4 of ADR-0005 (SDK auth swap; throughput investigation deferred). The richer real-stop walkthrough — three real-stop episodes inside one slice, finishing with a strategic deferral.

  • Pre-scope real stop, R2 token provisioning: the user-direction named "real-stop on R2 token provisioning blockage" up-front. No S3 credentials were present in .dev.vars, env, or wrangler's OAuth session (which can't be converted to S3-compatible credentials). Surfaced with a 4-step dashboard walkthrough; user provisioned the token and pasted the four values. Cathal asked clarifying questions ("account or user API?" → R2 API tokens are account-scoped; "Token value" → not used by SDK, ignore for the SDK path). Resumed scope-locked work once credentials landed.
  • Pre-scope tooling false stop, EU vs default jurisdiction: Cloudflare's token page showed an EU jurisdiction-specific endpoint (<account>.eu.r2.cloudflarestorage.com); the user pasted that. Initial smoke test against it returned NoSuchBucket. Diagnosed (bucket is default jurisdiction, not EU), tried the standard endpoint (<account>.r2.cloudflarestorage.com), worked. False stop — config-only fix, didn't change scope — picked and moved on.
  • Mid-slice real stop, throughput miss: validator Phase 4 measured 43.3 PUT/sec at concurrency=50, projecting 111.6 min for the 30-min/290k target. Surfaced the data, four hypotheses (H1–H4), and three paths forward (skip-HEAD, HTTP/2 swap, EC2 benchmark). User directed: HTTP/2 swap first (B), then skip-HEAD on top (A), don't combine.
  • Mid-slice real stop, architectural fix fails for orthogonal reason: HTTP/2 swap returned ERR_HTTP2_ERROR: Protocol error on the smoke test — R2's S3-compatible endpoint doesn't accept HTTP/2. Hypothesis untested (not falsified, not confirmed). Per the user's explicit "if B doesn't produce expected improvement, the diagnosis was wrong and we re-think before adding more changes" — surfaced re-diagnosis, didn't pivot to A blindly. (See known-patterns.md "Architectural fix fails for a reason orthogonal to the hypothesis".)
  • Mid-slice diagnostic, parameter sweep: user-directed concurrency sweep across [50, 100, 200, 500, 1000]. Flat curve (~50–70 PUT/sec), confirming H1 (remote-imposed ceiling). Five data points told a story no single point could. (See known-patterns.md "Parameter sweep distinguishes hypotheses".)
  • Strategic deferral close: sweep data + 50-site near-term gate
  • "60 PUT/sec is sufficient through 50 sites" cost analysis → user-directed close as "Slice 4 mostly complete; throughput deferred". Wrote the deferral contract into known-issues.md with explicit reopen triggers (50-site end-to-end proven,

    200-site batch lands, R2/Cloudflare side changes); ADR-0005 Slice tracker marked Slice 4 done with the sub-issue noted.

  • False stops avoided inside Slice 4: EU vs default endpoint (config-only); npm vs pnpm install path (npm wins, repo has package-lock.json); cleanup of bench-* objects between sweep iterations; bench-{ts}/ unique-prefix scheme to force fresh PUTs (vs polluting wfpainters/).
  • Regression check: N/A — new standalone script, no shared canonical surface touched. Declared explicitly in the wrap-up.

The session-start protocol caught a separate drift earlier in the day (wiki had retroactively renumbered Slices 3 and 4); the user corrected via the forced-summary protocol before any work landed on top of the wrong numbering. See session-start.md "Forced summary catches drift".