diff --git a/docs/screenshots/press-rollers/after-press-step-3.png b/docs/screenshots/press-rollers/after-press-step-3.png new file mode 100644 index 000000000..0dc2e79f3 Binary files /dev/null and b/docs/screenshots/press-rollers/after-press-step-3.png differ diff --git a/docs/screenshots/press-rollers/after-shifts.png b/docs/screenshots/press-rollers/after-shifts.png new file mode 100644 index 000000000..59f6e9722 Binary files /dev/null and b/docs/screenshots/press-rollers/after-shifts.png differ diff --git a/docs/screenshots/press-rollers/before-press-step-3.png b/docs/screenshots/press-rollers/before-press-step-3.png new file mode 100644 index 000000000..88f80f2c2 Binary files /dev/null and b/docs/screenshots/press-rollers/before-press-step-3.png differ diff --git a/docs/screenshots/press-rollers/before-shifts.png b/docs/screenshots/press-rollers/before-shifts.png new file mode 100644 index 000000000..48104ea34 Binary files /dev/null and b/docs/screenshots/press-rollers/before-shifts.png differ diff --git a/site/index.html b/site/index.html index 830923384..7238f10ee 100644 --- a/site/index.html +++ b/site/index.html @@ -51,8 +51,8 @@

Your issues go to press overnight.

-

The humans are the day shift: you talk the idea through, write the spec and cut it into issues. The agents work the third shift: give thirdshift an Issue URL and it implements the issue, reviews its own work and opens a pull request that is ready for review by morning.

-

Built on Matt Pocock's skills: aihero.dev/skills · mattpocock/skills

+

The humans are the day shift: you talk the idea through, write the spec and cut it into tickets. The agents work the third shift: give thirdshift an Issue URL and it implements the issue, reviews its own work and opens a pull request that is ready for review by morning.

+

Built on Matt Pocock's skills: aihero.dev/skills · mattpocock/skills. Read every prompt and skill thirdshift sends.

Install

@@ -73,11 +73,12 @@

Your issues go to press overnight.

Two shifts

You plan by day. The press runs at night.

Day shift

Humans, with Matt Pocock's skills, used interactively

-
  1. grill
  2. spec
  3. issues
-

The human half of the workflow: shaping work into issues the factory can take on, by grilling the idea, writing the spec and cutting it into issues, and reviewing the pull requests it delivers.

+
  1. /grill-with-docs
  2. /to-spec
  3. /to-tickets
+

The human half of the workflow: shaping work into issues the factory can take on, by grilling the idea with /grill-with-docs, writing the spec with /to-spec and cutting it into tickets with /to-tickets, and reviewing the pull requests it delivers.

Third shift

Agents, with headless copies of the same skills

-
  1. implement
  2. review
  3. pull request
-

thirdshift takes one Issue URL per Run. Its Factory skills, adapted to run with no human in the loop, implement the issue, review the work and open a pull request that is ready for review.

+
  1. /implement
  2. /code-review
  3. /pr
+

thirdshift takes one Issue URL per Run. Its Factory skills, adapted to run with no human in the loop, implement the issue with /implement, review the work with /code-review and open a pull request that is ready for review with /pr.

+

Read every prompt and skill the agents get →

@@ -88,7 +89,7 @@

Your issues go to press overnight.

How a Run works

One issue in, one pull request out.

-

A Run feeds one issue through four units and delivers a pull request that is ready for review. Units 2 and 3 are one agent session. Under each unit are the lines thirdshift printed on stderr during a real Run: issue #24, which produced pull request #25.

+

A Run feeds one issue through four units and delivers a pull request that is ready for review. Units 2 and 3 are one agent session. Under each unit are the lines thirdshift printed on stderr during a real Run: issue #24, which produced pull request #25. Click a unit to see what it does. Every prompt and skill it sends is on the Prompts and skills page.

@@ -101,8 +102,9 @@

One issue in, one pull request out.

Issue #24 goes in at the feeder and passes through four press units: 1 · C · Prepare, 2 · M · Implement, 3 · Y · Review and 4 · K · Finish. A bracket over units M and Y marks them as one agent session. Pull request #25, ready for review, comes out on the delivery pile. - - + + + @@ -127,8 +129,8 @@

One issue in, one pull request out.

C - - + + UNIT 1 1 · C · PREPARE @@ -137,8 +139,8 @@

One issue in, one pull request out.

M - - + + UNIT 2 2 · M · IMPLEMENT @@ -147,8 +149,8 @@

One issue in, one pull request out.

Y - - + + UNIT 3 3 · Y · REVIEW @@ -158,8 +160,8 @@

One issue in, one pull request out.

K - - + + UNIT 4 4 · K · FINISH @@ -194,7 +196,7 @@

1 · C · Prepare

2 · M · Implement

A headless Claude Code session, with the Factory skills loaded, implements the issue in the worktree, test-first where it can, and commits.

- +
  1. thirdshift: logging the session to /home/jacob/.thirdshift/logs/JacobStephens2-thirdshift-issue-24-20260925T134143Z-implement.jsonl
  2. thirdshift: implement: session started
  3. @@ -214,7 +216,7 @@

    2 · M · Implement<

    3 · Y · Review

    The same session reviews its work against the Base branch, fixes the Standards findings and Spec findings it agrees with, and lists the rest as Unaddressed findings in the pull request body. Then it opens the pull request, ready for review.

    - +
    1. thirdshift: implement: skill thirdshift:code-review
    2. thirdshift: implement: $ git rev-parse main && git log main..HEAD --oneline && git diff main...HEAD --stat; ls .agents/skills…
    3. @@ -239,7 +241,7 @@

      3 · Y · Review

      4 · K · Finish

      thirdshift pushes, checks the pull request, merges the Base branch in and watches CI. A merge conflict or failing CI starts a Repair, at most 3. A Resume can happen in any session and isn't a Repair. The Run ends once the pull request is open, ready, mergeable and passing CI. This Run needed no Repair.

      - +
      1. thirdshift: pushing issue-24
      2. thirdshift: checking the PR
      3. @@ -451,6 +453,7 @@

        Pre-flight ch diff --git a/site/main.js b/site/main.js index ec67a1d58..a1ab2e8c3 100644 --- a/site/main.js +++ b/site/main.js @@ -116,13 +116,23 @@ function stepPressLine(section) { if (inBand.size && n !== step) render(n); }, { rootMargin: "-45% 0px -45% 0px" }); - // A step button scrolls, instantly, to the middle of that step's marker, so the buttons and scrolling agree. - for (const b of stepButtons) { - b.addEventListener("click", () => { - const n = Number(b.dataset.step); - const r = markers[n - 1].getBoundingClientRect(); - scrollTo({ top: scrollY + r.top + r.height / 2 - innerHeight / 2, behavior: "instant" }); - render(n); + // Going to a step scrolls, instantly, to the middle of that step's marker, so the buttons and scrolling agree. + function goTo(n) { + const r = markers[n - 1].getBoundingClientRect(); + scrollTo({ top: scrollY + r.top + r.height / 2 - innerHeight / 2, behavior: "instant" }); + render(n); + } + + for (const b of stepButtons) b.addEventListener("click", () => goTo(Number(b.dataset.step))); + + // Clicking a unit in the drawing goes to its step, or, in the static version, to its column. The delivery pile + // is unit 4's output. The step buttons are the keyboard and screen reader equivalent, so the drawing stays an image. + section.classList.add("units-clickable"); + for (const el of [...units, delivery]) { + const n = el === delivery ? 4 : Number(el.dataset.unit); + el.addEventListener("click", () => { + if (step) goTo(n); + else cols[n - 1].scrollIntoView({ block: "start" }); }); } diff --git a/site/prompts/index.html b/site/prompts/index.html index 9afea9e06..e61ee432b 100644 --- a/site/prompts/index.html +++ b/site/prompts/index.html @@ -715,6 +715,7 @@

        LICENSE

        diff --git a/site/share-card.png b/site/share-card.png index fc4fa61d2..17c4d6abe 100644 Binary files a/site/share-card.png and b/site/share-card.png differ diff --git a/site/styles.css b/site/styles.css index d06b162fa..d4b7d778f 100644 --- a/site/styles.css +++ b/site/styles.css @@ -196,6 +196,15 @@ body::after { /* scanlines */ .press.is-stepped .unit-col:not(.lit), .press.is-stepped .unit-col .stderr-lines { display: none; } .press.is-stepped .unit-col.lit { animation: step-in .25s ease-out; } @keyframes step-in { from { opacity: 0; } } +/* The lit unit's rollers and drum turn; Pause stops them. Neighbouring rollers turn opposite ways, as they would on a press. */ +.press-svg .spin { animation: spin 1.4s linear infinite paused; } +.press-svg .rollers > g:nth-child(2) .spin, .press-svg .drum { animation-direction: reverse; } +.press-svg .drum { animation-duration: 3.2s; } +.press.is-stepped:not(.is-paused) .press-svg .unit.lit .spin { animation-play-state: running; } +@keyframes spin { to { transform: rotate(1turn); } } +/* Clicking a unit goes to it (main.js adds .units-clickable). The step buttons are the keyboard equivalent. */ +.press.units-clickable .press-svg .unit, .press.units-clickable .press-svg .delivery { cursor: pointer; } +.press.is-stepped .press-svg .unit:not(.lit):hover, .press.is-stepped .press-svg .delivery:not(.lit):hover { opacity: .65; } .press-controls { display: flex; flex-wrap: wrap; gap: 8px; } .press-controls button, .press-term .pause { font: 700 12px/1 var(--f-mono); letter-spacing: .08em; text-transform: uppercase; cursor: pointer; background: transparent; color: var(--paper); border: 1px solid var(--dim); padding: 9px 12px; min-height: 36px; } @@ -223,6 +232,9 @@ body::after { /* scanlines */ .chain li { font: 700 13px/1 var(--f-mono); padding: 8px 10px; border: 1px solid var(--dim); } .chain li + li::before { content: "→"; margin-right: 8px; color: var(--dim); } .shift.third .chain li { border-color: var(--c); } +.chain a { color: inherit; } +.chain a:hover { color: var(--nc); } +.shift code { font-size: .92em; color: var(--paper); white-space: nowrap; } /* ---------- What comes off the press ---------- */ .offpress { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }