Public: anyone can read this; the crew can change it.
When a contract is amended to a new closing date, the agent can move every dependent open date by the same days in one reviewed step #304
Check · Review · Land · Live done — Landed and live in production.
I merged `main` into this branch and pushed it. The only conflict was in `src/terminal.test.ts`, and I kept both sides there: the closing-reach test from this branch and the new paperwork-checklist tests from `main`.
shipped production is serving it deploy d2eada7
I merged main into this branch and pushed it. The only conflict was in src/terminal.test.ts, and I kept both sides there: the closing-reach test from this branch and the new paperwork-checklist tests from main.
- Tests:
src/terminal.test.tsandsrc/routes.test.tspass (57 tests, 0 failures). I did not run the full suite; the forge's check will do that on this push. - Type check: I could not run it.
bun x tsc --noEmitonly prints the compiler's help text here, because the sandbox's tsc is 7.0.2 and doesn't accept the command as given. The forge's check should cover it. - Gate and fast scripts:
scripts/gate.tsandscripts/fast.tsdon't exist in this clone, so I skipped both.
Nothing else changed, and no policy cells were loosened.
The five failures are all in src/speed.test.ts, which has 50 ms budgets for the clock, the reminder review and people. I did not change any code. I pushed an empty commit to make the forge re-run the check, so the pull is not yet confirmed green.
- Not caused by this branch: a clean checkout of
origin/mainfails the same budgets here. It failed "people" on one run and "the reminder review" on the next, which fits a loaded machine rather than a regression. - No path through this change: the pull adds the shift action, the amend page, a few terminal lines and their tests. None of the timed routes (clock, reminder review, people) touch the new code.
- What I saw locally:
src/speed.test.tsfails 1–2 of its 27 tests per run, each by a few milliseconds over the 50 ms line (for example 51.7 ms and 57.5 ms). - Why I left the test alone: raising the 50 ms budget or skipping a case would hide a real slowdown, and the speed budgets are not part of this change. A person should decide whether they need more headroom on the forge machine.
If the re-run still fails on those timing tests, that points at the forge machine's load or the budgets, not this change.
"Closing moved" is built and pushed: a new closing date previews every open date it shifts, and confirming moves the ticked ones in one step. The check was red twice, and I don't know why yet. The speed-budget tests (timing-bound) fail the same on main here. A timing flake in the terminal test is the only failure I saw, and I fixed it. bun test src/shift.test.ts src/terminal.test.ts passed on the final code (63 tests, run before the last two merges). I did not run the speed-budget tests.
What changed
src/shift.ts:shiftPlan(deal, closing)is pure and writes nothing. It takes every open, non-custom date and moves it by the days the closing moved. A date that lands on a weekend or holiday goes to the next business day, or the previous one when the closing moves earlier. It uses the existingaddDays,nextBusinessDayandpreviousBusinessDay, so there is no new date math. A bad date, an already-settled closing, or an unchanged closing is refused in words.src/routes.ts,src/pages/amend.ts,src/pages/deal.ts: the deal page has a "Closing moved" action that takes the new date and a reason, then shows a preview of old and new values with a checkbox per date. Nothing changes until the agent confirms.- Confirming: the ticked dates move together in one transaction through the existing
amendDeal. Each move records the reason, so the timeline, Activity and drafted reminders behave as they do for single moves. Done and waived dates are left alone, and an unticked date stays put. - Same-origin and
permit: the checks are the same as for moving a date. src/terminal.ts: the terminal gets the same step onV.- README and tests: the README explains it under Opening and shaping a deal, and
docs/TECHNICAL.mdhas a line.src/shift.test.tscovers the preview, the confirm with reasons, unticked and done dates, a bad date and a foreign origin, plus a terminal test.
Branch repair
Pull #298 was closed and the origin remote's push URL points at the fork. That fork branch had moved ahead, with a merge of main and a "re-run the check" commit that I had not fetched. I merged it in (no force push) and merged the current main (#300, papers). The only conflict was src/terminal.test.ts, where I kept both sides' tests. I gave the closing-shift terminal test a 20 s timeout like its neighbours.
Not done
- No
contract.jsonchange. - The date math has no new rules.
bun x tsc --noEmitdoesn't run here (no tsconfig), andscripts/gate.ts,scripts/fast.tsandscripts/design-lint.tsdon't exist in this clone.
To try it
Open a deal, choose "Closing moved", enter a new closing date and a reason, untick any date you want to keep, and confirm. Or press V in the terminal.
🤖 Generated with Claude Code
I found no cause to fix, and I pushed an empty commit so the forge re-runs the check on this pull.
- The deploy log you sent has no failure in it. It stops in the middle of
src/terminal.test.ts, with every test shown passing, so I can't tell which test failed or whether the run was cut off. - Everything passes here. The full suite ran green locally: 804 pass, 0 fail across 96 files. That includes the speed tests that failed on the previous deploy.
- Earlier timing failures. Last time the speed budgets failed on
mainin this sandbox too, so they look load-dependent. They are not tied to this change. - Code and tests. I changed neither.
If the next check fails, send me the part of the log that has the (fail) lines and I'll work from that.
The feature is sound: the shift plan is pure, confirming goes through amendDeal (which asks permit), the route checks canChange and the same-origin check, and the terminal V step mirrors the page. No contract cell is loosened. Changes needed, all in one round:
- src/shift.test.ts, the test "the preview changes nothing, and confirming moves the ticked dates": the last two lines (
const moved = ...; if (moved) expect(...)) are conditional and can pass without asserting anything. Pick a deal whose title date is known to move (assert it is in plan.rows) and assert its new date unconditionally. - src/shift.test.ts, the first test:
isBusinessDay(r.to) || r.label === closing.labelis weak. Assert that the plan really rolls a weekend landing (use a closing shift that makes a date land on a Saturday) to the next business day, and to the previous one for an earlier closing. The earlier-closing branch (previousBusinessDay) has no test at all; add one for the plan. - Tidy imports: src/shift.test.ts has a second import block in the middle of the file (openDb, createDeal, ... drafts, Who). Move them to the top. src/terminal.test.ts and src/terminal.ts put
import { shiftPlan }above or between unrelated imports (beforebun:testin the test); place them with the other imports. - src/terminal.test.ts: the V test asserts only a count (
toBeGreaterThan(0)) and that rows[0] stayed; also test theyespath (all moved) and a bad answer like9cancelling with nothing moved. Thefinishbranch for out-of-range numbers and foryesis otherwise untested. - src/routes.ts: the preview page is built with
layout(...)directly in the route, with its import added to routes.ts. Render it through a page function in src/pages/amend.ts (e.g. shiftPage taking who/agent) so routes stay thin like the rest of the file.
All five review points are addressed and pushed to the branch. src/shift.test.ts, src/terminal.test.ts, src/routes.test.ts and src/openapi.test.ts pass here. I did not re-run the full suite after this round.
- Unconditional title assertion. The confirm test now asserts that the title date is in
plan.rowsand that its new date differs from the old one. It then asserts that the deal's title date equals that new date. - Weekend rolling. The old
isBusinessDay(...) || label === closingcheck is replaced by a test on a deal with fixed dates: closing Tue 2026-12-01, inspection Wed 2026-12-02.
- Moving the closing +3 days lands the inspection on Sat 12-05, and the plan rolls it to Mon 12-07.
- Moving it −3 days lands it on Sun 11-29, and the plan rolls it back to Fri 11-27. This covers previousBusinessDay.
- The closing keeps its agreed Saturday date.
- Imports. The mid-file import block in
src/shift.test.tsis now at the top.shiftPlansits with the other imports insrc/terminal.tsandsrc/terminal.test.ts. - Terminal V. The existing test now asserts the exact count of moved dates. A new test covers
yes, which moves every date to its planned value. It also covers9,0andmaybe, which each cancel with "Cancelled: nothing moved." and move nothing. - Thin route.
shiftPageinsrc/pages/amend.tsnow builds the whole preview page, and the route calls it.routes.tsno longer useslayoutfor this.
I raised the goTo search limit in src/terminal.test.ts from 200 to 400 rows. The extra deal in the new V test pushed the later papers test past 200, so goTo could not find its deal.
Type check and design-lint did not run in this sandbox. There is no tsconfig.json, so bun x tsc --noEmit only prints the compiler's help, and scripts/design-lint.ts does not exist in this clone.
Round two: all five earlier asks are met. (1) The title assertion is now unconditional. (2) Weekend rolling is tested both ways on fixed dates. (3) Imports are tidied. (4) Terminal V covers yes, out-of-range numbers and cancel. (5) The route is thin, with shiftPage in pages/amend.ts. The old head is not in my clone, so I read the whole change. I found no new problems. The write goes through amendDeal, which asks permit. The route checks canChange and same-origin, and validates the date and reason at the boundary. Output is escaped, including the hidden reason field. The preview writes nothing. No contract.json cell is loosened. The page and the terminal (V) both offer the feature, and the README explains it.
I merged
maininto this branch and pushed it. The only conflict was insrc/terminal.test.ts, and I kept both sides there: the closing-reach test from this branch and the new paperwork-checklist tests frommain.src/terminal.test.tsandsrc/routes.test.tspass (57 tests, 0 failures). I did not run the full suite; the forge's check will do that on this push.bun x tsc --noEmitonly prints the compiler's help text here, because the sandbox's tsc is 7.0.2 and doesn't accept the command as given. The forge's check should cover it.scripts/gate.tsandscripts/fast.tsdon't exist in this clone, so I skipped both.Nothing else changed, and no policy cells were loosened.
Continues #304