Public: anyone can read this; the crew can change it.
The planner's refusals live in one module, read by dependencies, plan and limb replan #5632
Check · Review · Land · Live done — Landed and live in production.
The planner's two refusals, "an issue cannot wait for itself" and "the planner has it in hand already", are now typed in one place: a new module, `src/actions/plan_words.ts`. It exports them as `SELF_WAIT` and `IN_HAND`. No existing module owned words like these, so I created it rather than adding to another file. The wording is unchanged, so answers and pages read exactly as before.
shipped production is serving it deploy 5a6a4f7
The planner's two refusals, "an issue cannot wait for itself" and "the planner has it in hand already", are now typed in one place: a new module, src/actions/plan_words.ts. It exports them as SELF_WAIT and IN_HAND. No existing module owned words like these, so I created it rather than adding to another file. The wording is unchanged, so answers and pages read exactly as before.
What moved where:
src/actions/dependencies.ts:dependencyWords.selfis nowSELF_WAIT.src/actions/plan.ts: the refusal for a plan item that waits for itself now usesSELF_WAIT.src/actions/limb_replan.ts: the take-back refusal now usesIN_HAND.src/tui/screens/limbs.ts: thepkey's message now usesIN_HAND.src/contract/openapi.ts: this file isn't in the issue's list, but it had a fifth copy,"an issue cannot wait for itself (422)". The issue'sgrep -rncheck would have found it, so it is now `${SELF_WAIT} (422), which gives the same string.src/contract/probes.tsalready imports fromactions/`, so this doesn't open a new dependency between layers.
Under src/, grep -rn for either sentence now finds only plan_words.ts. In each file only the sentence's line changed, plus one import line.
New test: test/plan-words.test.ts checks that each exported sentence is non-empty. It also reads each of the five files as text and fails if either sentence is typed back in.
Checks run: bun x tsc --noEmit is clean. These test files pass (117 tests, 0 failures): plan-words, dependencies, limb-replan, limbs, tui-limbs, plan-pillars, plan-route, contract, openapi, openapi-coverage and openapi-served. One later command ran the whole suite by mistake; it was still running when I pushed, so I have no result from it. src/web didn't change, so the design lint wasn't needed.
🤖 Generated with Claude Code
Does exactly what #5595 asked: both sentences live in src/actions/plan_words.ts, every named file imports them, wording is unchanged, and the preview answers 200 on /. The openapi.ts fifth copy is a sensible, declared extension. The new test reads the sources as text and fails if a copy is typed back. No security, tty or web surface is touched. Two things I would do next: (1) the tests only guard these two sentences; if more planner words drift, extend plan_words.ts and READERS together or derive the file list by scanning src/ for the literals. (2) Tidy import order in dependencies.ts/plan.ts (plan_words after pillars) and run prettier on the now-short multi-line calls in plan.ts and limb_replan.ts. Note this is a small cleanup, not on the NOW list (arm stability); it is cheap and harmless to land.
The planner's two refusals, "an issue cannot wait for itself" and "the planner has it in hand already", are now typed in one place: a new module,
src/actions/plan_words.ts. It exports them asSELF_WAITandIN_HAND. No existing module owned words like these, so I created it rather than adding to another file. The wording is unchanged, so answers and pages read exactly as before.What moved where:
src/actions/dependencies.ts:dependencyWords.selfis nowSELF_WAIT.src/actions/plan.ts: the refusal for a plan item that waits for itself now usesSELF_WAIT.src/actions/limb_replan.ts: the take-back refusal now usesIN_HAND.src/tui/screens/limbs.ts: thepkey's message now usesIN_HAND.src/contract/openapi.ts: this file isn't in the issue's list, but it had a fifth copy,"an issue cannot wait for itself (422)". The issue'sgrep -rncheck would have found it, so it is now `${SELF_WAIT} (422), which gives the same string.src/contract/probes.tsalready imports fromactions/`, so this doesn't open a new dependency between layers.Under
src/,grep -rnfor either sentence now finds onlyplan_words.ts. In each file only the sentence's line changed, plus one import line.New test:
test/plan-words.test.tschecks that each exported sentence is non-empty. It also reads each of the five files as text and fails if either sentence is typed back in.Checks run:
bun x tsc --noEmitis clean. These test files pass (117 tests, 0 failures): plan-words, dependencies, limb-replan, limbs, tui-limbs, plan-pillars, plan-route, contract, openapi, openapi-coverage and openapi-served. One later command ran the whole suite by mistake; it was still running when I pushed, so I have no result from it.src/webdidn't change, so the design lint wasn't needed.🤖 Generated with Claude Code
Closes #5595