Skip to content

docs(companions): tell the truth — rulestead/rindle are unpublished - #84

Merged
szTheory merged 2 commits into
mainfrom
fix/companion-publish-truth
Jul 28, 2026
Merged

docs(companions): tell the truth — rulestead/rindle are unpublished#84
szTheory merged 2 commits into
mainfrom
fix/companion-publish-truth

Conversation

@szTheory

Copy link
Copy Markdown
Owner

The defect

crosswake_rulestead and crosswake_rindle have never published to Hex, but the docs said they had.

Package hex.pm API
crosswake, crosswake_sigra, crosswake_chimeway, crosswake_threadline ✅ 200
crosswake_rulestead, crosswake_rindle 404

No crosswake_rulestead-v0.1.0 / crosswake_rindle-v0.1.0 tags exist either. Their Release PRs (#39, #38) are open and unmerged.

Meanwhile:

  • guides/companion_compatibility.md — a public guide — listed both at 0.1.0 and linked hexdocs.pm/crosswake_rulestead / crosswake_rindle (both dead), and the prose said adding crosswake_rindle "resolves cleanly without pinning core back."
  • .planning/RETROSPECTIVE.md claimed v16.0 shipped "two live Hex publishes (crosswake_rulestead, crosswake_rindle)."
  • .planning/PROJECT.md / .planning/MILESTONES.md called all five "Hex packages" without separating published from release-wired.

Only CHANGELOG.md:22 hedged correctly.

For a project whose brand is support-truth honesty — advisory, emulator evidence, never overclaim — this is the exact defect class the gates exist to catch, sitting in a public guide.

The fix

The compat matrix already had the vocabulary. The merge-blocking drift test accepts a Current Version cell of `unpublished`, and its own remediation text says to use it pre-publish:

set the <pkg> Current Version cell to unpublished (pre-publish) or the confirmed hex.pm X.Y.Z semver post-publish
test/crosswake/proof/phase132_compat_matrix_drift_test.exs:218

The rows were simply wrong. So: rows stay (the drift test bans phantom rows and derives the ~> 0.1 floor from each package's crosswake_dep/0); only the publish-status claim and the dead links change.

Not doing

No Hex publish. This corrects the claim rather than shipping to match it — deliberate, because Hex publishes are irreversible and packages/crosswake_rulestead/CHANGELOG.md still contains core-inherited history (0.1.2 storefront/RevenueCat entries) while sitting in that package's files: allowlist. It would ship permanently as rulestead's changelog. That must be fixed before any future publish.

#38/#39 stay open as standing publish gates, per docs/MILESTONE-BOUNDARY-HYGIENE.md §4.

Tests

mix test test/crosswake/guides/ + phase132 + phase42 + phase43176 tests, 0 failures. Full suite running.

Review ask

Sanity-check that unpublished + "not yet on hexdocs" is the framing you want in the public matrix, vs. dropping the rows entirely until publish.

🤖 Generated with Claude Code

`crosswake_rulestead` and `crosswake_rindle` have never published to Hex
(hex.pm API returns 404 for both; no `crosswake_rulestead-v0.1.0` /
`crosswake_rindle-v0.1.0` tags exist). Their Release PRs (#39, #38) are open
and unmerged. But the docs advertised them as live:

- `guides/companion_compatibility.md` listed both at version `0.1.0` and
  linked `hexdocs.pm/crosswake_{rulestead,rindle}` — both dead — and the
  prose claimed adding `crosswake_rindle` "resolves cleanly" today.
- `.planning/RETROSPECTIVE.md` claimed v16.0 shipped "two live Hex publishes".
- `.planning/PROJECT.md` and `.planning/MILESTONES.md` described all five
  companions as extracted "Hex packages" without distinguishing published
  from merely release-wired.

Only `CHANGELOG.md` hedged correctly.

The compat matrix already had a sanctioned vocabulary for this: the
merge-blocking drift test
(`test/crosswake/proof/phase132_compat_matrix_drift_test.exs:211`) accepts a
`Current Version` cell of `unpublished`, and its own remediation text says to
use it pre-publish. The rows were simply wrong. Rows stay (the drift test bans
phantom rows and derives the `~> 0.1` floor from each package's
`crosswake_dep/0`); only the publish-status claim and the dead links change.

No publish is performed here. This corrects the claim rather than shipping to
match it — a deliberate choice, since Hex publishes are irreversible and
`packages/crosswake_rulestead/CHANGELOG.md` still carries core-inherited
history that would ship permanently.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@szTheory
szTheory merged commit 568b215 into main Jul 28, 2026
73 checks passed
@szTheory
szTheory deleted the fix/companion-publish-truth branch July 28, 2026 19:31
szTheory added a commit that referenced this pull request Jul 28, 2026
Replaces the anecdotal "draining 6 PRs took ~2h" note with hard numbers from the
2026-07-28 session, so the milestone opens with evidence rather than a memory.

The exhibit is PR #84 — a documentation-only change touching four markdown files
(.planning/MILESTONES.md, PROJECT.md, RETROSPECTIVE.md, guides/companion_
compatibility.md):

  - 78 workflow runs, in two full 39-workflow cycles (16:28 and 18:46)
  - 0 failures, at every point
  - 3h03m from open to merge

None of those 39 workflows can be affected by a markdown edit, because no paths:
filtering exists anywhere. The second cycle exists only because strict: true
invalidated the branch when another PR merged. Nothing was wrong; it just waited.

Session totals: >=200 workflow runs in one day, 8 PRs serialized through the
queue -- on a day that also surfaced a config regression (#89) CI structurally
could not see. That contrast is the thesis in one line: the spend is uncorrelated
with the risk.

Two structural contributors confirmed live and recorded:

  - allow_update_branch was false, so auto-merge could not update stale branches
    and the queue silently deadlocked with every PR green-but-BEHIND. Flipped to
    true 2026-07-28; that removes the deadlock, not the serialization.
  - With strict: true, N queued PRs cost O(N^2) rebuild work.

Adds a concrete CONSOL-* acceptance criterion: a markdown-only PR must run a
small, named, always-reporting set and merge without the native lanes -- using
the paths-filter -> job-level if: -> aggregating gate shape, never a
workflow-level paths: on a required context.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
szTheory added a commit that referenced this pull request Jul 28, 2026
Replaces the anecdotal "draining 6 PRs took ~2h" note with hard numbers from the
2026-07-28 session, so the milestone opens with evidence rather than a memory.

The exhibit is PR #84 — a documentation-only change touching four markdown files
(.planning/MILESTONES.md, PROJECT.md, RETROSPECTIVE.md, guides/companion_
compatibility.md):

  - 78 workflow runs, in two full 39-workflow cycles (16:28 and 18:46)
  - 0 failures, at every point
  - 3h03m from open to merge

None of those 39 workflows can be affected by a markdown edit, because no paths:
filtering exists anywhere. The second cycle exists only because strict: true
invalidated the branch when another PR merged. Nothing was wrong; it just waited.

Session totals: >=200 workflow runs in one day, 8 PRs serialized through the
queue -- on a day that also surfaced a config regression (#89) CI structurally
could not see. That contrast is the thesis in one line: the spend is uncorrelated
with the risk.

Two structural contributors confirmed live and recorded:

  - allow_update_branch was false, so auto-merge could not update stale branches
    and the queue silently deadlocked with every PR green-but-BEHIND. Flipped to
    true 2026-07-28; that removes the deadlock, not the serialization.
  - With strict: true, N queued PRs cost O(N^2) rebuild work.

Adds a concrete CONSOL-* acceptance criterion: a markdown-only PR must run a
small, named, always-reporting set and merge without the native lanes -- using
the paths-filter -> job-level if: -> aggregating gate shape, never a
workflow-level paths: on a required context.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
szTheory added a commit that referenced this pull request Jul 29, 2026
…y job (#93)

* perf(153.1): move 13 non-Apple CI jobs from macos-15 to ubuntu-latest

GitHub bills macOS runners at a 10x multiplier, and the Phase 153.1 baseline
measured a 163x QUEUE ratio on top of that: 490s mean queue per macOS job vs
3s per ubuntu job. 19 macOS jobs accounted for 9,305s of the 9,454s total
queue time on a single push.

Per-job audit (RUNNER-01), following every `run:` into its scripts
transitively rather than grepping the workflow file:

  22 macOS jobs -> 9 genuinely need a macOS host, 13 do not.

Moved (13):
  - phase23/34/41/43/45/48/52/58/70/71/73 merge-blocking proofs. Each is
    checkout + setup-beam + `mix deps.get` / `mix compile` / `mix test`.
    No scripts, no native toolchain.
  - phase10-proof. Its three verify_*.sh are 10-line wrappers around
    `mix run` + `mix test` against examples/phoenix_host.
  - phase68 android-emulator-advisory. It boots an `arch: x86_64` AVD;
    macos-15 runners are arm64, so that image was running under full CPU
    emulation. On ubuntu it gets KVM, which is the path
    ReactiveCircus/android-emulator-runner documents. Added the standard
    /dev/kvm udev step.

Stayed on macOS (9), each with file:line evidence:
  - phase5, phase18, phase79, see-it-run-collateral, and both
    native-collateral-advisory jobs -> xcodebuild via
    script/verify_generated_ios_shell.sh:14
  - native-behavioral-proof-gate/ios-package-unit -> `swift test`
  - release-please/clean-room-proof-ios -> `swift build`
  - native-behavioral-proof-gate/android-generated-shell-unit -> NOT an
    Apple-toolchain dependency but a macOS-HOST one: the verify script
    downloads a JDK from adoptium `.../ga/mac/$(arch)/...` and falls back to
    Homebrew. The existing `# REVIEW FIX finding 2` comment was right.

Every moved job keeps its `name:` byte-identical — branch protection matches
required contexts by string, so a rename here would silently un-protect main.
Verified: zero `name:` lines in this diff, and
check_required_checks_registered.sh still reports all 26 declared lanes
registered and uniquely emitted.

DEVELOPER_DIR was set at the workflow `env:` level in 11 of these files and
had exactly one consumer each; with no macOS job left in those workflows it
is now dead, so it is removed rather than left implying an Xcode dependency.

Refs: Phase 153.1 RUNNER-01, SEED-007

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* perf(153.1): give every CI job a timeout-minutes (47 jobs, 16 workflows)

A job with no `timeout-minutes` inherits GitHub's 360-minute default. On a
10x-billed macOS runner that is 60 hours of billable time for one hung job,
and the baseline session already saw a real 20-minute hang while compiling
deps on #84 — the failure mode is not hypothetical.

Values are scoped to observed runtimes with headroom, not uniform:
  - 45  release-please clean-room-proof-* (full dependency resolution from
        Hex plus a native build)
  - 40  native-collateral-advisory macOS simulator/emulator lanes
  - 30  publish-* jobs, remaining macOS jobs, see-it-run web-and-gif
  - 20  everything else

release-please.yml is security-sensitive (REL-05 SHA pinning, two previously
armed fuses). This commit adds timeout-minutes lines and nothing else there —
its concurrency settings (`cancel-in-progress: false`, `queue: max`) are
deliberate and untouched. Verified: the whole-file diff is exactly three
distinct added-line shapes, all timeout-minutes.

No job `name:` is modified anywhere in this diff, so every registered
required context still matches by string.

Refs: Phase 153.1 RUNNER-02, SEED-007

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant