<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Of Tomorrow build log — Signals</title>
    <link>https://oftomorrow.net/log/signals/</link>
    <description>What the people and agents building Of Tomorrow did, as the ledger recorded it.</description>
    <atom:link href="https://oftomorrow.net/log/signals/rss.xml" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Wed, 14 Oct 2026 16:47:13 GMT</lastBuildDate>
    <ttl>1</ttl>
    <item>
      <title>[ccs, for todd · ot.signals] done #1187: A person&apos;s comment on a card reaches CW: the board&apos;s Say posts &apos;needs check&apos; by default, a read-only &apos;signals asks&apos; lists open asks, and the scope page breaks out open asks and open decisions at the top</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1187</link>
      <description>Committed 318598a on signals/1187 (not pushed, no migration). (1) sayOnJob (apps/web/lib/actions.ts) now posts needs &apos;check&apos; with no lane, so the existing sig_open_asks routing sends it to the scope&apos;s cw lane. It posts &apos;nothing&apos; when the person ticks the new &apos;just a note&apos; box in the job modal, when they hold the card (claimed by them, or in review with them as reviewer), or when they are a runner. jobDetail returns asked_of per message using sig_open_asks&apos;s rule (a later message on the subject from anyone holding the role at or above its scope; nobody is asked what they asked), and the modal shows an &apos;asked CW&apos; marker that disappears once CW replies. (2) GET /api/asks?lane= (apps/web/lib/handlers/asks.ts) calls sig_open_asks over the named lanes, or every lane the caller holds (each role at its scope and every scope beneath). The client gained asks(), and the CLI gained `signals asks [--lane ...]`, printing &apos;#&lt;id&gt; &lt;kind&gt;  &lt;who&gt;  &lt;first line&gt;  (&lt;age&gt;)&apos; per ask. It makes no claim and no poll write. (3) The board page loads openAsks(scope) and openDecisions(scope) (views.ts) into a new AttentionStrip above the toolbar: &apos;Open asks&apos; (card, who, first line, age; click opens the job or decision modal) and &apos;Open decisions&apos; (title, age, waits on, taken from the policy&apos;s who_may_rule). It renders nothing when both lists are empty. Tests: new tests/integration/a-board-say-is-an-ask.test.ts (8 cases) covers: a person&apos;s say is an open ask on &lt;scope&gt;:cw and marked asked_of cw; the note toggle posts &apos;nothing&apos;; the claimant&apos;s say is a note while cw&apos;s say on the same card is a check; cw&apos;s reply closes the ask and clears the marker; `signals asks` with and without --lane lists the ask by card, who and first line only, and afterwards sig_next_head on the cw lane is the same job, still available and unclaimed; the strip&apos;s reads find a child-scope ask and an open decision (&apos;cw or todd&apos;) from both the child scope and ot.signals, and nothing for an empty scope. New tests/components/attention-strip.test.tsx (3 cases: asks line &apos;#820 todd is the db push done? · 1h&apos; opens the card; decision line &apos;#55 Where does a message go? · 2d · waits on cw or todd&apos; opens it; empty strip renders &apos;&apos;). Two job-modal cases (the &apos;just a note&apos; checkbox sends note:true; the &apos;asked CW&apos; marker shows only on an unanswered ask) and one board case (clicking a strip ask loads that card). Mutations, each run with the mutated text asserted present before the run and restored after: M1 default back to &apos;nothing&apos; failed 5 cases including M1; M2 note flag ignored (&apos;$4 and false&apos;) failed only M2; M3 claimant carve-out removed failed only M3; M4 answered-check removed failed only M4; M5 /api/asks answered via sig_claim_next failed only M5; M6 strip lanes from the page scope&apos;s own roles only failed only M6. Verified with: pnpm typecheck (clean), pnpm lint (clean), pnpm test:unit &apos;Tests 896 passed (896)&apos;, pnpm test:components &apos;Tests 243 passed (243)&apos;, pnpm test:integration &apos;Tests 789 passed (789)&apos;, pnpm build:web &apos;Compiled successfully&apos; with ƒ /api/asks listed. (8m)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4365</guid>
      <pubDate>Wed, 14 Oct 2026 16:47:13 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1217: a reviewer&apos;s comment is a note too</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1217</link>
      <description>&quot;their own claim&quot; covers a card the viewer holds by claim or by review, plus anything a runner posts</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4364</guid>
      <pubDate>Wed, 14 Oct 2026 16:47:11 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] said #1187: A person&apos;s comment on a card reaches CW: the board&apos;s Say posts &apos;needs check&apos; by default, a read-only &apos;signals asks&apos; lists open asks, and the scope page breaks out open asks and open decisions at the top</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1187</link>
      <description>A comment a person leaves on a card is now a question for CW by default, and the board shows open questions and open decisions at the top.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4363</guid>
      <pubDate>Wed, 14 Oct 2026 16:46:54 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] landed #1141: Rows-present reads Press&apos;s own pull record, not row counts: a day with no ads is not a day Press did not pull</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1141</link>
      <description>Landed as 50b041b in signals.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4338</guid>
      <pubDate>Wed, 14 Oct 2026 16:40:39 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] done #1141: Rows-present reads Press&apos;s own pull record, not row counts: a day with no ads is not a day Press did not pull</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1141</link>
      <description>Commit 50b041b on signals/1141 (not pushed). Press&apos;s job_runs (modules/jobs 0001) records what each pull covered: import-fb-ads puts since..until in its summary, and a kdp-daily upload puts its days in summary.covered (or period for one day). So no Press data change is needed. Added watch metrics press.pull.ads (T-1) and press.pull.sales (T-2): the count of succeeded runs that read as_of and started after it was over (UTC). job_runs is read only when a brief asks for a pull. breachType now makes press.pull.* the blocker; a threshold on press.rows.* is a threat. Migration 20261023120000_rows_present_reads_press_pulls.sql (later than every branch&apos;s) moves the watch.press.rows_present template, its expectation and any unclaimed card to thresholds ads_not_pulled and sales_not_pulled, with press.rows.ads and press.rows.sales observed beside them and no threshold. README updated. The fixture gains Press&apos;s job_runs DDL and a run history. Tests: ads 10-14 and sales 10-13 pulled with zero rows give no blocker; ads 10-15, whose only later run failed, gives a blocker; ads 10-19 with no pull gives a blocker. Also covered: pullCovers edge cases, and the adapter reading job_runs from a real Postgres equal to the fixture. VERIFIED: pnpm typecheck and pnpm lint clean; pnpm test:unit printed &apos;Tests 907 passed (907)&apos;; pnpm test:integration printed &apos;Tests 783 passed (783)&apos;. Three deliberate breaks each failed tests: no status check failed 1, no started-after rule failed 7, blocker on rows again failed 4 unit plus 1 integration. NEEDS PRESS (Kevin&apos;s lane, posted as needs-check #4319, not filed): watch_ro has no grant on job_runs. One migration: grant select on public.job_runs to watch_ro; create policy watch_ro_read on public.job_runs for select to watch_ro using (true). Until then rows-present fails with &apos;permission denied for table job_runs&apos; (a watch.failed to devops); the other four watches are unaffected. Also: Press refuses a KDP Daily file with no sales rows and records no run, so a real zero-sales KDP day still reads as not pulled. (10m)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4327</guid>
      <pubDate>Wed, 14 Oct 2026 16:37:49 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1207: Propose, not file, the Press grant on job_runs</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1207</link>
      <description>posted as needs-check #4319 for the reviewer</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4326</guid>
      <pubDate>Wed, 14 Oct 2026 16:37:49 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1206: The sales pull is kdp-daily only</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1206</link>
      <description>ACX daily is not counted</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4325</guid>
      <pubDate>Wed, 14 Oct 2026 16:37:48 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1205: Ads coverage is the Meta import&apos;s summary since..until, sales coverage is kdp-daily&apos;s summary.covered or one-day period</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1205</link>
      <description>never a cron run&apos;s period or covered</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4324</guid>
      <pubDate>Wed, 14 Oct 2026 16:37:48 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1204: A pull counts only after the day is over</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1204</link>
      <description>press.pull.* counts succeeded job_runs whose window holds as_of and that started on or after as_of+1 (UTC)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4323</guid>
      <pubDate>Wed, 14 Oct 2026 16:37:48 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] said #1141: Rows-present reads Press&apos;s own pull record, not row counts: a day with no ads is not a day Press did not pull</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1141</link>
      <description>The rows-present watch now asks Press whether it pulled the day, not how many rows it wrote — a day with no ads no longer pages anyone.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4320</guid>
      <pubDate>Wed, 14 Oct 2026 16:37:23 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] landed #1140: A watch job has no reviewer: its success is done, its expectation is the check — the daily trigger files the five cards reviewer-less, and a person reviews only a failure</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1140</link>
      <description>Landed as 996f527 in signals.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4298</guid>
      <pubDate>Wed, 14 Oct 2026 16:27:46 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] done #1140: A watch job has no reviewer: its success is done, its expectation is the check — the daily trigger files the five cards reviewer-less, and a person reviews only a failure</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1140</link>
      <description>Watch jobs can now skip review (job 1140). Migration 20261022120000_a_watch_job_has_no_reviewer.sql, later than every migration on origin/main and in the other worktrees, adds sig_jobs.no_review with a check refusing it alongside a repo, so reviewer-is-not-builder is untouched for anything that lands code. sig_create_job gains p_no_review (dropped and recreated, as for skills), with a by-name refusal when a repo is also given. sig_finish_job: a no_review success goes to done with landed_at = now, no commit and no reviewer; job.done is written with landed_in &apos;done&apos; and no_review true, job.result is emitted as before, waiting jobs are unblocked, and no job.landed is written. Failure is unchanged: available, then exhausted, then #1113&apos;s ops signal. File_job templates may say no_review (anything but a boolean is refused); the five watch.press.* triggers now carry no_review: true, and watch jobs filed but not yet finished got the flag (ones already in review were left alone). sig_log returns a no_review column on job.done rows and the log entry carries it, so the build log can say Done instead of Built. The word Built comes from of-tomorrow-website src/lib/log.ts, a separate repo that still needs a one-line change; I did not make it. API no_review key, client type, signals job --no-review, and the watch README updated. Verified: new tests/integration/a-watch-job-has-no-reviewer.test.ts (9 tests: success is done with no reviewer and no landing, job.done payload, job.result, waiting jobs unblocked, build-log no_review true/false, failure path identical to a reviewed job including the ceiling, refusal with a repo at filing and in the database, triggers file five no_review cards, a non-boolean template refused, API accepts no_review and refuses a non-boolean with 422) plus a CLI test for --no-review. Mutation check: making the success branch unreachable and dropping the trigger update turned 5 tests red; restored. pnpm typecheck and lint clean; test:unit 894 passed; test:components 237 passed; test:integration 57 files, 775 passed; build:web built. Commit 8b59d05, not pushed.

rebase conflict in apps/web/lib/migrations-manifest.ts resolved by a session in 10s; it is on the tip it will land on, and the verify at landing is still ahead of it.

No attempt was opened for this and the attempt counter did not move — a conflict
with a sibling that landed first is a machine reason, not a rejection.

Reopen the job if the resolution is wrong. It is a diff of the branch before and
after the rebase:

  git -C ~/Github/signals range-diff 8b59d053503e...996f527dee5b (9m)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4283</guid>
      <pubDate>Wed, 14 Oct 2026 16:25:08 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1190: no-review is refused with a repo</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1190</link>
      <description>a database check plus a refusal at filing (API, CLI, template)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4281</guid>
      <pubDate>Wed, 14 Oct 2026 16:24:57 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1189: a no-review job lands in done with landed_at and no job.landed event</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1189</link>
      <description>the builder&apos;s success stamps landed_at = now with no commit and no reviewer; no job.landed is written</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4280</guid>
      <pubDate>Wed, 14 Oct 2026 16:24:57 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] said #1140: A watch job has no reviewer: its success is done, its expectation is the check — the daily trigger files the five cards reviewer-less, and a person reviews only a failure</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1140</link>
      <description>A watch job no longer waits for a reviewer: when the daily Press watch succeeds, its card goes straight to Done, and its expectation is the check. A failure still comes back to a person.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4279</guid>
      <pubDate>Wed, 14 Oct 2026 16:24:41 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] landed #1139: A metric observed again for the same as_of with a different value supersedes the earlier observation — the dedupe key keeps a replay quiet, but not a correction</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1139</link>
      <description>Landed as 79e39fb in signals.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4274</guid>
      <pubDate>Wed, 14 Oct 2026 16:23:24 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[todd · ot.signals] done #1176: Push 20261020120000_a_refused_landing_goes_back_to_the_builder.sql</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1176</link>
      <description>Applying migration 20261020120000_a_refused_landing_goes_back_to_the_builder.sql...
Finished supabase db push. (0m)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4256</guid>
      <pubDate>Wed, 14 Oct 2026 16:14:48 GMT</pubDate>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] done #1139: A metric observed again for the same as_of with a different value supersedes the earlier observation — the dedupe key keeps a replay quiet, but not a correction</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1139</link>
      <description>A metric.observed sent again for the same dedupe key with a different payload.value now supersedes the earlier one instead of being deduped. Migration 20261021120000 (later than everything on main, the remote branches and the local worktrees, newest 20261020120000) adds sig_signals.supersedes_id. The unique dedupe index now covers only originals, plus sig_signals_superseded_once, so a key names a chain and a dedupe hit returns its head. sig_emit_signal records the correction as a new signal (its signal.opened event carries the superseded short id) and closes the old one via sig_close_signal with &apos;superseded by &lt;id&gt;: value changed&apos;, caused by the new signal&apos;s event. The same value, or any other type (threat included), is deduped as before. New view sig_metric_latest (security_invoker, select for authenticated) gives the newest non-closed observation per scope x metric x as_of x dimensions. The watch counts non-deduped emits with supersedes_id and reports &apos;11 metrics (N corrected)&apos; only when N &gt; 0. Client Signal type, watch README and migrations manifest updated. Verified: pnpm typecheck and pnpm lint clean; pnpm test:unit 64 files / 888 passed; pnpm test:integration 57 files / 766 passed (test:components and build:web not run; this change does not touch them). New tests/integration/metric-corrections.test.ts: same value -&gt; 200 deduped with no new rows or events; different value -&gt; 201 with supersedes_id, original closed with the reason, view shows the new value, close caused by the new signal&apos;s event; a second correction supersedes the first and replaying it is deduped; a threat reffing the old value keeps its refs and stays open, and a threat re-sent with another value stays deduped; an observation closed by hand leaves the view. watch-press.test.ts: a run where Press shows no rows reports &apos;(N corrected)&apos; and the view shows 0, the normal run restores the real value and closes the old row, the roas_low threat is unchanged, and a replay adds no events. Mutations, each restored and diffed: value check -&gt; false (4 red); type check -&gt; true (breach test red); head-of-chain condition removed (2 red); close removed (5 red); view status filter removed (green at first, so a hand-closed case was added and now catches it); filter removed plus oldest-first order (3 red); oldest-first order alone (green, the filter covers it); watch counts deduped rows (unit and watch tests red). Committed 73f993d on signals/1139, not pushed. After landing: CW re-cuts the five cards for 10-14.

rebase conflict in apps/web/lib/migrations-manifest.ts resolved by a session in 11s; it is on the tip it will land on, and the verify at landing is still ahead of it.

No attempt was opened for this and the attempt counter did not move — a conflict
with a sibling that landed first is a machine reason, not a rejection.

Reopen the job if the resolution is wrong. It is a diff of the branch before and
after the rebase:

  git -C ~/Github/signals range-diff 73f993d5a0cb...79e39fba9ff8 (8m)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4249</guid>
      <pubDate>Wed, 14 Oct 2026 16:14:24 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1184: `sig_metric_latest` is new</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1184</link>
      <description>no metrics view existed</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4248</guid>
      <pubDate>Wed, 14 Oct 2026 16:14:12 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1183: a dedupe key now names a chain</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1183</link>
      <description>the unique index covers only originals (`supersedes_id is null`), plus `sig_signals_superseded_once` on `supersedes_id`; a dedupe hit compares with and returns the row nobody supersedes</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4247</guid>
      <pubDate>Wed, 14 Oct 2026 16:14:12 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1182: the correction lives in the ledger, not the watch</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1182</link>
      <description>`sig_emit_signal` supersedes on a dedupe hit when the type is `metric.observed` and `payload.value` differs</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4246</guid>
      <pubDate>Wed, 14 Oct 2026 16:14:12 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] said #1139: A metric observed again for the same as_of with a different value supersedes the earlier observation — the dedupe key keeps a replay quiet, but not a correction</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1139</link>
      <description>The ledger now takes a corrected number: when the watch sees a different value for a day it already reported, it records a new observation and closes the old one, instead of keeping the first value.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4245</guid>
      <pubDate>Wed, 14 Oct 2026 16:13:49 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] landed #1123: A card the lander sent back says so: &apos;landing refused&apos; on the board and in the feed, with the first line of why — approved to review is never silent</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1123</link>
      <description>Landed as ac88e36 in signals.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4229</guid>
      <pubDate>Wed, 14 Oct 2026 16:12:17 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] landed #1114: Something makes packages/runner/src/main.ts executable in ccs worktrees and the lander refuses the mode-only diff as a dirty tree — find it, and treat a mode-only change as clean</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1114</link>
      <description>Landed as b532bd8 in signals.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4227</guid>
      <pubDate>Wed, 14 Oct 2026 16:10:07 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] done #1114: Something makes packages/runner/src/main.ts executable in ccs worktrees and the lander refuses the mode-only diff as a dirty tree — find it, and treat a mode-only change as clean</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1114</link>
      <description>Reviewer&apos;s send-back fixed. The failing integration test, runner-end-to-end.test.ts &apos;SIG-94 — puts the checkout&apos;s refusal on the CARD&apos;, had a fake git command that matched the status call by position (argv[3] === &apos;status&apos;). IGNORE_MODE now puts -c core.fileMode=false ahead of the subcommand, so position 3 held &apos;-c&apos;, the fake never returned &apos; M f.txt&apos;, and the checkout refusal never reached the card. The production code was correct; I changed the test at line 746 to argv.includes(&apos;status&apos;), matching the five rebase checks changed in attempt 1, and a search of tests/ and packages/ found no other position-based subcommand check. Commit e11ae9c on signals/1114, not pushed. Reproduced: with the old line restored, pnpm test:integration tests/integration/runner-end-to-end.test.ts printed &apos;Tests 1 failed | 23 passed (24)&apos;, the failure being SIG-94; with the fix all 24 pass. Verified: pnpm verify ran typecheck and lint cleanly, then printed unit &apos;Test Files 64 passed / Tests 886 passed&apos;, components &apos;10 passed / 230 passed&apos;, integration &apos;56 passed / 760 passed&apos;, and &apos;verified e11ae9ca0052 (web build included)&apos;. Attempt 1&apos;s findings stand: pnpm install makes packages/runner/src/main.ts executable when it links the signals-runner bin into @signals/watch; main has stored the file as 100755 since job 1106; the lander&apos;s dirty check, its rebase and its restamp git add -u ignore mode-only changes via IGNORE_MODE. The job thread had no new reviewer or owner messages. (8m · 2 attempts)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4210</guid>
      <pubDate>Wed, 14 Oct 2026 16:05:16 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] done #1123: A card the lander sent back says so: &apos;landing refused&apos; on the board and in the feed, with the first line of why — approved to review is never silent</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1123</link>
      <description>Amended by #4112: a landing refusal now sends the card to the TOP OF THE BUILDER&apos;S BACKLOG instead of review. New migration 20261020120000_a_refused_landing_goes_back_to_the_builder.sql supersedes decision #170 for landings. sig_send_to_builder is the one door for both sig_reject_review and sig_landing_blocked (work, or machine at the 5-retry ceiling): available, rank first in the project, ceiling raised as SIG-86, claim and reviewer cleared. The lander stamps the thread &apos;landing refused (MM-DD HH:MI UTC): &lt;first line&gt;&apos; as the runner. sig_latest_rejection reports either send-back (kind/first_line/times). sig_back_from_landing marks the review card after the rebuild. sig_log serves job.landing_refused as &apos;Landing refused #N: &lt;first line&gt;&apos;. Runner: landingHeadline() puts the first line first on the note; the session brief says LANDING refused it. Board: &apos;Landing refused&apos; stripe on the backlog card, cleared on claim; &apos;Back from landing, nth time&apos; on the review card, cleared on approval; whole note on hover. Tests cover all of it at the integration, build-log, prompt, unit and component levels. Verified: pnpm verify exited 0 (unit 887, components 237, integration 765 passed). Committed 19cfc2a, not pushed. The optional progress &apos;signals say&apos; timed out and was not posted. (14m)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4197</guid>
      <pubDate>Wed, 14 Oct 2026 16:00:29 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1168: &quot;nth time&quot; only from the second time on</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1168</link>
      <description>a first refusal shows only the reason</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4196</guid>
      <pubDate>Wed, 14 Oct 2026 16:00:27 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1167: no stripe on the runner strip</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1167</link>
      <description>the strip lists runner health, not what is next; the refused card is first in the backlog</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4195</guid>
      <pubDate>Wed, 14 Oct 2026 16:00:27 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1166: the lander&apos;s note opens with a one-line headline</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1166</link>
      <description>landingHeadline() writes &quot;rebase conflicted in &lt;files&gt;&quot;, &quot;verify failed in &lt;files&gt;&quot;, &quot;restamp refused&quot;</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4194</guid>
      <pubDate>Wed, 14 Oct 2026 16:00:27 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1165: stamp time is UTC wall-clock</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1165</link>
      <description>the thread stamp reads &quot;landing refused (MM-DD HH:MI UTC): &lt;first line&gt;&quot;</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4193</guid>
      <pubDate>Wed, 14 Oct 2026 16:00:27 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1164: amended by message #4112</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1164</link>
      <description>a landing refusal (work, or machine at the retry ceiling) goes to available at the top of the builder&apos;s backlog through one shared sig_send_to_builder, with a lander-authored thread stamp and a &quot;Back from landing, nth time&quot; marker on the review card</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4192</guid>
      <pubDate>Wed, 14 Oct 2026 16:00:27 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] landed #1116: The watch exits on source move like the runners (SIG-72), so a landing in packages/watch takes effect without a hand restart</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1116</link>
      <description>Landed as 2c30d47 in signals.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4185</guid>
      <pubDate>Wed, 14 Oct 2026 15:54:42 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[todd · ot.signals] done #1154: Push 20261019120000_an_exhausted_job_is_an_ops_signal.sql</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1154</link>
      <description>pnpm exec supabase db push --include-all
Initialising login role...
Connecting to remote database...
│
◇  Do you want to push these migrations to the remote database?
│   • 20261019120000_an_exhausted_job_is_an_ops_signal.sql
│
│  Yes
Applying migration 20261019120000_an_exhausted_job_is_an_ops_signal.sql...
Finished supabase db push. (0m)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4171</guid>
      <pubDate>Wed, 14 Oct 2026 15:47:57 GMT</pubDate>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] done #1116: The watch exits on source move like the runners (SIG-72), so a landing in packages/watch takes effect without a hand restart</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1116</link>
      <description>Ported SIG-72 into the watch and, per #4050, moved its logging to the shared log. watchLoop reads git&apos;s tree hash for packages/watch at start and before each claim (never mid-job). On a change it logs &apos;source moved &lt;a&gt;→&lt;b&gt;, exiting for launchd&apos; and main exits 0 so launchd&apos;s KeepAlive restarts it; an unreadable hash counts as unmoved, so the watch keeps working. Implemented by giving the runner&apos;s sourceId a package-path argument (default packages/runner) and reusing sourceMoved. main.ts now opens ~/.oftomorrow/signals/runner.log through the runner&apos;s openSharedLog with handle &apos;watch&apos;, echoing to stdout only at a tty. README updated. Committed as 2c30d47, not pushed. Verified: 4 new tests in tests/unit/watch-loop.test.ts with a fake reader (moved: stops before the next claim and logs the line; unreadable: keeps claiming). Mutation checks: removing the early exit failed 1 test; dropping the unreadable-is-unmoved rule failed 2. Real git: sourceId on packages/watch/src returned a4e7760a… matching `git rev-parse HEAD:packages/watch`, and null from /tmp. Real process: `node packages/watch/src/main.ts /tmp/w1116/signals/runners/watch` exited 1 and wrote &apos;[watch] watch refused to start: …config.json: is missing&apos; to /tmp/w1116/signals/runner.log with nothing on stdout. `tsc -b` exit 0, eslint exit 0, `vitest run --project unit` 64 files / 887 tests passed. Left for a person: the live plist ~/Library/LaunchAgents/net.oftomorrow.signals.runner.watch.plist still points StandardOutPath/StandardErrorPath at runners/watch/runner.log, so only launchd&apos;s crash output still goes there; repoint it at ~/.oftomorrow/signals/runner.log as the README now says. (3m)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4161</guid>
      <pubDate>Wed, 14 Oct 2026 15:44:52 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1159: do not edit the live watch plist in ~/Library/LaunchAgents</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1159</link>
      <description>the README tells the operator to point StandardOutPath/StandardErrorPath at the shared log</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4160</guid>
      <pubDate>Wed, 14 Oct 2026 15:44:51 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1158: watch only the packages/watch tree, as the brief says</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1158</link>
      <description>a landing that changes only the runner modules the watch imports (config/log/loop) will not restart it</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4159</guid>
      <pubDate>Wed, 14 Oct 2026 15:44:51 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1157: the check lives in watchLoop, before each claim, not in main</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1157</link>
      <description>watchLoop returns &quot;source moved&quot; and main exits 0</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4158</guid>
      <pubDate>Wed, 14 Oct 2026 15:44:50 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1156: reuse the runner&apos;s sourceId/sourceMoved rather than copy them</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1156</link>
      <description>sourceId takes the package path (default packages/runner) and the watch passes packages/watch</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4157</guid>
      <pubDate>Wed, 14 Oct 2026 15:44:50 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1155: amended by message #4050</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1155</link>
      <description>the watch writes every line to the shared ~/.oftomorrow/signals/runner.log via the runner&apos;s openSharedLog (handle from the directory, [watch]), echoing to stdout only at a tty</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4156</guid>
      <pubDate>Wed, 14 Oct 2026 15:44:50 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] said #1116: The watch exits on source move like the runners (SIG-72), so a landing in packages/watch takes effect without a hand restart</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1116</link>
      <description>The watch now restarts itself when its own code lands, and writes to the same shared log as the other runners.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4155</guid>
      <pubDate>Wed, 14 Oct 2026 15:44:32 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] landing refused #1114: Something makes packages/runner/src/main.ts executable in ccs worktrees and the lander refuses the mode-only diff as a dirty tree — find it, and treat a mode-only change as clean</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1114</link>
      <description>Landing refused #1114: VERIFY AT LANDING FAILED on signals/1114 at fb03c6c977e3 — nothing was pushed.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4152</guid>
      <pubDate>Wed, 14 Oct 2026 15:41:42 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] landed #1113: An exhausted job opens one ops signal, not a deliberation: no decision, no walk-through, no red team for a job that failed three times; a ruling never revives a cancelled job; a ruled decision cancels its pair</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1113</link>
      <description>Landed as e37cc57 in signals.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4147</guid>
      <pubDate>Wed, 14 Oct 2026 15:39:57 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] done #1114: Something makes packages/runner/src/main.ts executable in ccs worktrees and the lander refuses the mode-only diff as a dirty tree — find it, and treat a mode-only change as clean</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1114</link>
      <description>Cause: pnpm install. @signals/watch depends on @signals/runner, so pnpm links the signals-runner bin into packages/watch/node_modules/.bin and chmods its target, packages/runner/src/main.ts, to 755, in any worktree install (the builder&apos;s own or the lander&apos;s frozen install before verify). The runner&apos;s own chmods only touch the pre-push hook and the bin/signals shim. Reproduced in a clone at cd1dbf2^: after pnpm install --frozen-lockfile --offline, git diff --summary printed &apos;mode change 100644 =&gt; 100755 packages/runner/src/main.ts&apos; and nothing else. Main is no longer 644: job 1106 (cd1dbf2) already committed main.ts as 100755, and that stays, so on current main an install changes nothing (this worktree&apos;s install left git diff --summary empty); branches cut earlier still drift. Fix (commit 11c76a8 on signals/1114, not pushed): new IGNORE_MODE = [&apos;-c&apos;,&apos;core.fileMode=false&apos;] in packages/runner/src/fast-forward.ts, used by trackedChanges, by rebasePlan&apos;s rebase command, and by the restamp step&apos;s git add -u so a stray +x is never committed at landing. It is per command because git config in a worktree would write the shared repo config. Tests added in tests/unit/runner-landing.test.ts: a chmod-only worktree rebases and lands with origin keeping f.txt at 100644; an uncommitted content change still refuses and nothing is pushed; trackedChanges calls a chmod clean and a content edit dirty. Five existing argv[3]===&apos;rebase&apos; assertions changed to argv.includes(&apos;rebase&apos;). Verified: pnpm typecheck and pnpm lint clean; pnpm test:unit printed 64 files, 886 tests passed; with IGNORE_MODE emptied the chmod-lands and trackedChanges tests fail and the content-refuses test passes (2 failed, 1 passed). (8m · 2 attempts)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4136</guid>
      <pubDate>Wed, 14 Oct 2026 15:37:08 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1152: the cause is not removed at its source</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1152</link>
      <description>keep @signals/watch depending on @signals/runner and keep the runner&apos;s bin</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4135</guid>
      <pubDate>Wed, 14 Oct 2026 15:37:07 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1151: per-command -c core.fileMode=false, not git config</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1151</link>
      <description>pass IGNORE_MODE to the dirty check, the rebase and the restamp add -u</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4134</guid>
      <pubDate>Wed, 14 Oct 2026 15:37:07 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1150: main.ts stays 100755</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1150</link>
      <description>keep the mode job 1106 already committed rather than reverting to 644</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4133</guid>
      <pubDate>Wed, 14 Oct 2026 15:37:07 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] said #1114: Something makes packages/runner/src/main.ts executable in ccs worktrees and the lander refuses the mode-only diff as a dirty tree — find it, and treat a mode-only change as clean</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1114</link>
      <description>Found why a runner file kept turning executable in build worktrees (pnpm marks linked bin targets executable), and the lander now treats a permission-bit-only change as a clean tree instead of refusing the landing.</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4132</guid>
      <pubDate>Wed, 14 Oct 2026 15:36:49 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] done #1113: An exhausted job opens one ops signal, not a deliberation: no decision, no walk-through, no red team for a job that failed three times; a ruling never revives a cancelled job; a ruled decision cancels its pair</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1113</link>
      <description>Answering the check on /tmp/j1113/verify.txt: that file is the FIRST pnpm verify run and it exited 1. Integration had 2 failures out of 760, both in tests/integration/seed.test.ts, because those tests list every signal type exactly and did not yet include job.exhausted. I added job.exhausted to both lists. The second full run (/tmp/j1113/verify2.txt) exited 0: unit 870 passed, components 230 passed, integration 760 passed, with typecheck, lint and the web build clean; it printed &apos;verified 3dfa3b985814 (web build included)&apos;. That passing run is what is committed as c1757ec on signals/1113, not pushed. (32m)</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4119</guid>
      <pubDate>Wed, 14 Oct 2026 15:31:08 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
      <category>cw</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1145: there is no &quot;give it more attempts&quot; door on a job.exhausted signal</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1145</link>
      <description>`signals close` cancels the job, and a fourth attempt is a refile</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4118</guid>
      <pubDate>Wed, 14 Oct 2026 15:31:07 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
    <item>
      <title>[ccs, for todd · ot.signals] decided #1144: the brief points at sig_close_decision, which SIG-69 deleted</title>
      <link>https://signals.oftomorrow.net/board?scope=ot.signals&amp;card=1144</link>
      <description>fixes 2 and 3 go in sig_rule_decision only</description>
      <guid isPermaLink="false">https://signals.oftomorrow.net/api/log?scope=ot.signals#4117</guid>
      <pubDate>Wed, 14 Oct 2026 15:31:07 GMT</pubDate>
      <category>ccs</category>
      <category>todd</category>
    </item>
  </channel>
</rss>
