Conversation
…+ landed-content close guard (debottleneck B1)
B1.1: --integration becomes DEFAULT with auto-generated batch-<YYYYMMDD-HHMM> names;
--serial escape hatch for legacy mode; add --dry-run trial merge in scratch worktree.
B1.2: Stacked PRs chain graph building (baseRefName reads); drop entire chain on conflict;
independent chains ordered by dependency depth.
B1.3: TDD-FIRST: ancestor check (git merge-base --is-ancestor) blocks close of unlanded content;
correctness bug fix prevents closing PRs whose content never merged to main.
B1.4: enforce_admins runtime assert at train start (gh api check); abort if not enabled.
B1.5: Integration mode never calls update_branch (FLAG 1 APPROVED: strict:false verified live);
serial mode only updates BEHIND/UNKNOWN with --rebase-behind flag (default OFF).
B1.6: Regeneration hook stub (A1/A2/A3 generators plug in here); commits if files changed.
Test suite: 43 passing (1 new TDD-first test for B1.3 ancestor check).
Gates: secret_scan --staged exit 0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three verified P1s in the merged cost drawer (#676) and its browser proof. a1 — CostSummaryDrawer showed stale spend forever after backend death. `isError` was gated on `!cost`, but useSSE's EventSource error handler spreads `prev` and retains the last cost payload. After ANY first payload both isLoading and isError were unreachable, so a dead backend rendered the healthy loaded branch with arbitrarily stale Total/Rate/Model-mix on every view, with zero indication. `isError` is now `connectionStatus.status !== 'live'` ALONE — connection status wins over cached data. A retained payload renders under an explicit `cost-summary-stale` label inside the error state, never as current. a2 — Model-mix percentages were dimensionally wrong. The share divided a model's ALL-TIME tokens by (LATEST-DAY tokens x model count): a share of nothing, unbounded above, then clamped by `width: min(pct * 2, 100)%` so a true 50% share rendered full and a long history with a quiet latest day rendered every model at 100%. Shares are now each model's fraction of the all-time token total, both sides from `summary.models` (the only per-model breakdown the contract carries). Same window on both sides, so shares sum to 100%; the window is labelled in the UI and the numeric share is rendered beside each bar. Rounding to 0.1% happens once, so label and bar width cannot disagree. a3 — verify_cost_summary_drawer.py asserted materially less than its docstring claimed. Console-clean (a/h/l) and the "No data yet" message (k) were print-only: a page throwing on every render printed [WARN] and exited 0. Every enumerated claim is now an assert. Also: the console filter dropped any message containing "warning"/"deprecated" as a substring (swallowing "Uncaught TypeError: warning banner is undefined") and is now an explicit full-match allowlist; 4xx/5xx responses and uncaught pageerrors are captured and asserted; the empty phase's vacuous `has_pricing is False or len(models) == 0` is now two real assertions and the phase sets AESOP_CONFIG_ROOT so it is hermetic; non-auto-waiting `is_visible()` checks became `wait_for(state=...)`; `wait_for_server` fails fast if the server process exits; stderr is always surfaced. TDD: the 8 new vitest cases were written first and all 8 fail against the pre-fix component (23/31 pass) and all pass after (31/31). Falsifiability of the proof was demonstrated by breaking the console-clean and empty-message assertions locally — both turn the run red (exit 1) — then restoring. Gates: vitest 532/532 (42 files), tsc --noEmit clean, vite build + dist committed, verify_cost_summary_drawer.py exit 0, stateapi_lint 0 new (40 = baseline), claudemd contract/sync/domain-map green, secret_scan --staged CLEAN. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…gration-default # Conflicts: # tools/CLAUDE.md
The origin/main merge added the merge_queue.py entry alongside this branch's own entries, taking the file to 151 lines and failing the "CLAUDE.md linter gate (scope invariant)" step in ci (0). Folds alert_bridge.py and dep_graph.py onto one row -- the same pairing this file already uses for launch_tui.py / orchestrator_status.py. No entry is lost. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rd test, make epoch fencing real
Deep-scan findings B1/B2/B3 in the multibox coordination layer.
B1 (split-brain): LeaseStore derived claim keys with case_policy="platform",
which case-folds when os.name == 'nt' and preserves case otherwise. Two
instances sharing one coordination db therefore derived DIFFERENT keys for the
same file ('tools/Runner.py' -> 'tools/runner.py' on Windows, 'tools/Runner.py'
on Linux), so _check_conflicts (exact match) missed and BOTH were granted the
claim. Case policy is now configuration, not a property of the host OS, resolved
explicit-arg > multibox.case_policy > $AESOP_CLAIM_CASE_POLICY > "insensitive".
An unrecognized policy raises ValueError (fail-closed).
B2 (vacuous guard): the heterogeneity guard called canonical_claim_path directly
with case_policy="insensitive" -- a value production never passed -- and never
touched _normalize_path, so it stayed green while B1 was live and survived
mutating _normalize_path to the identity function. Rewritten to exercise the real
production entry point, plus an end-to-end LeaseStore split-brain reproducer.
B3 (inert epoch): nothing in the repo ever incremented the persisted epoch, so
get_identity_with_epoch returned 1 forever and could not distinguish a pre- from
a post-crash instance, while the module documented it as a monotonic boot
counter. Acquisition now increments and durably persists the epoch (temp file +
fsync + os.replace), fail-closed on persist failure (EpochPersistError, a
subclass of IdentityCorruptionError) and on a non-integer epoch. Existing
corrupt-file fail-closed hardening and fresh-box epoch=1 are preserved.
release_own_stale() now raises NotImplementedError instead of returning an
unconditional True while doing nothing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gration-default # Conflicts: # tests/CLAUDE.md # tools/CLAUDE.md # tools/merge_train.py
Owner
Author
|
Dissolving merge-queue batch: required check(s) absent from rollup: windows |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merge-queue batch built by tools/merge_queue.py.
Members: #693, #703, #754
Members are closed only after
git merge-base --is-ancestorproves their content landed on main.