Skip to content

docs(boilerplate): the alpha ledger has no run path, and the claim-binary trap (Refs #12444) - #13040

Merged
gHashTag merged 2 commits into
masterfrom
claude/boiler-e3-12449
Nov 1, 2026
Merged

gHashTag merged 2 commits into
masterfrom
claude/boiler-e3-12449

Conversation

@gHashTag

@gHashTag gHashTag commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

Row E phase 3 reconnaissance for epic #12444. Docs only: seven lines in
.claude/skills/boilerplate-loop/SKILL.md. No spec, no seal, no generated file,
no foreign line.

What this tick measured

  • The plain ledger still holds on master 7acdfb1c9c: 1796 duplicate bodies in
    688 groups across 2918 specs. PR spec(policy): dupe_bodies, the duplicate-bodies gate in t27 with the alpha key (Refs #12449) #12579 measured the same ledger numbers on
    2819 specs and 22234 bodies, so 99 specs and 427 bodies arrived in five days
    without moving the ratchet. Command: python3 tools/dupe_scan.py with no
    argument (there is no --check flag).
  • The alpha ledger, tools/duplicate_bodies_alpha_baseline.txt, has not been
    checked since it was blessed on 2026-10-26, and cannot be checked on this Mac.
    The GATE: command in the header of specs/policy/dupe_bodies.t27 is refused
    three separate ways here: the Bash tool's MAC LOAD hook denies cc; the
    Terminal hook reads 1<<26 as a here-document, reads the identifier r as the
    shell's history command, and then reads the {...} of int main as a glued
    zsh brace list, which no respelling of C avoids. The lab the Bash hook
    recommends, the fs-lab.sh under the old t27-lanes home, no longer exists. So the alpha
    key row E delivered is unverifiable until phase 3 wires it or it is built where
    the hooks allow. Materialising the shim as a .c file is not the way out: the
    gate spec's design is printf'd command text precisely so no foreign file
    exists, and only-t27 forbids the scratch file as well.

Two traps recorded so the next tick does not pay them again

  • tri loop claim lives only in the repo-built binary. ~/t27/target/release/tri
    has the loop subcommand; ~/.cargo/bin/tri is a different tool and answers
    unrecognized subcommand 'loop'; ~/.local/bin/tri does not exist. An exit 2
    from the wrong binary is the wrong binary, not "the claim could not be
    attempted" -- reporting it as the latter stops a tick that had no blocker.
  • A stale claim can belong to a finished row. boiler-12449 was HELD for six days
    by the agent that had already merged phase 2 and never released. Read the row's
    last comment and its PR before a TAKEOVER:: a DONE: comment plus a merged
    PR plus a deleted branch means the row is free, not that someone is working.

What was not done, and why

The two command corrections belong in the header of specs/policy/dupe_bodies.t27,
but that spec is sealed (.trinity/seals/policy_policy::dupe_bodies.json), and
correcting even a comment line there stales the seal. This Mac has no legitimate
seal re-save route, so the corrections are in the skill and the spec is left to a
tick that has one.

Phase 3's real wiring -- switching STEP_DUPES / STEP_DUPES_BASE in
specs/tri/pr/preflight.t27 to the gate -- is still open. That spec has tracked
generated output (gen/rust/tri/pr/preflight.rs) and is in the seal closure, so it
needs the same seal route.

Checks

  • Docs-only diff; foreign-budget, own-language and secret-gate pre-push
    hooks reported "no matching push files".
  • English, ASCII only.

Refs #12444

🤖 Generated with Claude Code

… claim-binary trap (Refs #12444)

Row E phase 3 reconnaissance, written into the loop skill so the next tick does
not re-derive it.

- The plain ledger still holds on master 7acdfb1: 1796 duplicate bodies in
  688 groups across 2918 specs, the same ledger numbers PR #12579 measured on
  2819 specs and 22234 bodies, so 99 specs and 427 bodies arrived in five days
  without moving the ratchet.
- The alpha ledger has not been checked since it was blessed, and cannot be on
  this Mac: the GATE command in the header of specs/policy/dupe_bodies.t27 is
  refused by the Bash MAC LOAD hook (cc), and by the Terminal hook three ways
  (1<<26 reads as a here-document, the identifier r reads as the shell history
  command, the C function body reads as a glued zsh brace list). The lab the
  Bash hook recommends no longer exists.
- tri loop claim exists only in the repo-built target/release/tri; the cargo
  binary has no loop subcommand and ~/.local/bin/tri is gone, so an exit 2 from
  the wrong binary must not be reported as an unattemptable claim.
- The gate spec is sealed, so the two command corrections cannot be made in its
  header by a tick without a seal route; they are in the skill instead.

Refs #12444

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

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-11-01 05:43:37 UTC

Summary

Status Count
Total Open PRs 40
PRs with Failing Checks 34
PRs with All Checks Green 6
READY 5
FAILING 34
PENDING 0
NO CHECKS YET 0

These columns do not partition: 5 + 34 + 0 + 0 = 39, and there are 40 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=e75b498e5e79 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

… (Refs #12444)

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

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-11-01 06:50:53 UTC

Summary

Status Count
Total Open PRs 41
PRs with Failing Checks 34
PRs with All Checks Green 7
READY 6
FAILING 34
PENDING 0
NO CHECKS YET 0

These columns do not partition: 6 + 34 + 0 + 0 = 40, and there are 41 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=e75b498e5e79 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag merged commit 05ff1b7 into master Nov 1, 2026
32 of 33 checks passed
@gHashTag
gHashTag deleted the claude/boiler-e3-12449 branch November 1, 2026 09:10
gHashTag added a commit that referenced this pull request Nov 1, 2026
… OS (see #13055) (#13062)

* feat(t27os): DSH MCP to ACP bridge table and gate, nothing wired (#13037)

* feat(t27os): DSH MCP to ACP bridge table and gate, nothing wired (Closes #13028)

Pure decision spec: six expected MCP tool names, each mapped to the ACP
method verified in the DSH server (session/new, prompt, cancel, list,
resume, close; cancel is a notification), and a gate that answers hold
(conductor go absent), refuse (issue 0, unknown tool, create out of scope)
or map (exactly one ACP session request). Precedence is refuse before hold:
a request that can never become valid is refused even while the go is absent.

It registers nothing, starts nothing and dispatches nothing. 21 test blocks;
they have been run by CI only, not on the Mac.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(t27os): DSH bridge stop levers skip the go, real map check (Closes #13028)

Review findings F1-F3 on the DSH MCP to ACP bridge gate.

F1: T_CANCEL and T_CLOSE no longer answer R_NO_GO. needs_go(tool) is false
for them, so a runaway session can be stopped while the conductor go file
is missing. They still need a non-zero issue (issue 0 is refused for every
tool) and ignore the scope fact. The header says so and that the owner can
overrule it; two new tests pin both halves.

F2: the vacuous one_ok test is replaced. map_consistent ties
acp_requests(decide(...)) and mapped_method(...) to (decide == D_MAP), and
all_combos_consistent checks the 8 combinations of go, issue and scope for
each tool.

F3: T_LIST stays held without go; one header line says a read also waits
for the go.

23 test blocks (was 21); parse and spec-status run locally, the tests are
run by CI only, not on the Mac.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* spec(t27os): general conductor tick decision, pure, stays off until the go file (#13042)

* spec(t27os): general conductor tick decision, pure, stays off until the go file (Closes #13029)

Pure decision spec in the style of godmode_tick: reads crons::general_conductor::tick_decision,
lists five numbered host needs (three GAPs), scores the five duties against GC_MAX_SECONDS_PER_DUTY,
returns tick rows as data (STAY_OFF / RUN / SKIP zero the seconds), answers stay off while ENABLED is
false or the go file is absent, and treats scaling output as proposal only. 20 tests, 0 vacuous.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* spec(t27os): general conductor tick drops its dec_len twin, fixed worst-case row buffer (Closes #13029)

CI duplicate-bodies refused the private dec_len (a third copy of a body
in godmode_tick.t27 and t27b/emit_kit.t27). tick_row now checks the
buffer against GCT_ROW_MAX (152, the worst-case row) and writes nothing
when it is smaller, so no digit counter is needed. One new test,
row_max_boundary. Gate on a T27 OS shell-cell pane: 21 tests, 21 pass,
0 vacuous.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* docs(boilerplate): the alpha ledger has no run path, and the claim-binary trap (Refs #12444) (#13040)

* docs(boilerplate): record the alpha ledger's missing run path and the claim-binary trap (Refs #12444)

Row E phase 3 reconnaissance, written into the loop skill so the next tick does
not re-derive it.

- The plain ledger still holds on master 7acdfb1: 1796 duplicate bodies in
  688 groups across 2918 specs, the same ledger numbers PR #12579 measured on
  2819 specs and 22234 bodies, so 99 specs and 427 bodies arrived in five days
  without moving the ratchet.
- The alpha ledger has not been checked since it was blessed, and cannot be on
  this Mac: the GATE command in the header of specs/policy/dupe_bodies.t27 is
  refused by the Bash MAC LOAD hook (cc), and by the Terminal hook three ways
  (1<<26 reads as a here-document, the identifier r reads as the shell history
  command, the C function body reads as a glued zsh brace list). The lab the
  Bash hook recommends no longer exists.
- tri loop claim exists only in the repo-built target/release/tri; the cargo
  binary has no loop subcommand and ~/.local/bin/tri is gone, so an exit 2 from
  the wrong binary must not be reported as an unattemptable claim.
- The gate spec is sealed, so the two command corrections cannot be made in its
  header by a tick without a seal route; they are in the skill instead.

Refs #12444

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

* docs(boilerplate): drop the developer home path the scan gate refuses (Refs #12444)

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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

* feat(t27os): Ladder Doctor decision spec: classes, breaker, incident, recipes (Refs #13036) (#13038)

* feat(t27os): Ladder Doctor decision spec: classes, breaker, incident, recipes (Refs #13036)

Spec only: refusal classes from status plus rung, a per-rung breaker pinned to keys.t27 CIRCUIT_FAILS and CIRCUIT_COOLDOWN_S, one incident per rung and cause, a closed recipe list, resolution only on a 200 control request, and a fail-closed 503 body line. No dependency on the rung table of #13035.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* feat(t27os): Ladder Doctor SLOW class, per-rung deadline and walk budget (Refs #13036)

FR-010: a response not complete within LD_DEADLINE_MS is class SLOW, handled
like TRANSIENT for the breaker; a 200 after the deadline counts as a failure,
never a success, and a SLOW rung is not repeated inside one turn.
FR-011: one walk is bounded by LD_WALK_BUDGET_MS (above one deadline, under
120000); when it is spent the walk ends with the 503 body of FR-007.
Tests: 25 in total, 5 new.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* spec(t27os): a SLOW 200 is served and takes a capped strike (Refs #13036)

Review of PR 13038: a 200 past the 30000 ms deadline is still an answer.

- response_action: a 200 is SERVED however long it took; never dropped,
  never retried (LD_SLOW_RETRIES = 0).
- Capped strike (header law 9): a SLOW 200 adds one strike but never
  resets the count and never takes it past CIRCUIT_FAILS - 1, so slowness
  alone cannot open a rung that still answers. A SLOW non-answer (0 or 5xx
  past the deadline, or a call cut at the walk budget) still counts like
  TRANSIENT and can open the breaker.
- The deadline is a naming threshold, not an abort: call_deadline_ms is
  replaced by walk_left_ms and within_budget. A 134000 ms answer is past
  the 100000 ms budget and is cut.
- New tests: the measured 40000 / 90000 ms sequence stays closed, and a
  200 at 31000 ms is served once with one strike. 27 tests in all.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* spec(t27os): the walk budget stops starting calls, a call ceiling cuts (Refs #13036)

Review round 3 of PR 13038. Real data, T27 OS ladder log 2026-11-01: 3 of
the last 9 rung-0 answers were 200s taking 150937, 138044 and 225921 ms,
and DSH waits at least 209 s. Cutting at the 100000 ms walk budget would
have turned them into 503s.

- Choice B (header law 10, marked as the owner's to overrule): the budget
  only stops STARTING calls (may_start_call). The call in flight is waited
  for up to LD_CALL_CEILING_MS = 240000, which is at least LD_DSH_WAIT_MS =
  209000 (the lower bound read from the ladder log line of 2026-11-01).
  Choice A (cut every call at the budget) is named as the choice not taken.
- timed_status(status, took_ms) is the pure function the breaker and the
  walk use: 0 when the call is cut at the ceiling, else the status.
  call_spent_ms caps what a call adds to the walk, action_after_call and
  breaker_record_call are the walk's two uses. within_budget is gone.
- A cut 200 is status 0, LC_SLOW, LA_REFUSED, counts like TRANSIENT and
  can open the breaker; a 200 at exactly the ceiling is served, one ms
  later it is cut; a 200 past the 30000 ms deadline but inside the ceiling
  keeps its one capped strike.
- Stated cost: a walk can run to 339999 ms, so the literal FR-011 reading
  (no turn waits 209 s for a refusal) is relaxed; the owner decides.
- New tests: both sides of the ceiling, the three logged answers served,
  the budget-versus-ceiling pins. 29 tests in all.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(t27os): the window no longer traps at startup (key-age words overlapped the orbit's spans) (#13016)

* fix(t27os): key-age packing no longer overflows a u64 at startup (Refs #13015)

The window trapped (brk #1, Overflow) about 2 s after launch. The provider-age
writer weighted slot 8 with 65536 to the 4th, which is 2^64. One helper,
keyage_lane(slot) = 65536^(slot % 4), now serves both key-age loops, with a
test that packs all ten providers and reads each back.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* chore(seals): re-save t27os_T27osGlassWindow after the key-age lane fix (Refs #13015)

Re-saved with the post-#12824 t27c from a T27 OS shell-cell pane on the owner's word. Tests 93/93.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(t27os): hold the orbit pointer within a million points so squaring a gap cannot overflow (Refs #13015)

The window built from the key-age fix still died at launch: the first frame
reported a pointer x of 219269006857735, and ov_nearest_gap squared the gap
(dx * dx on i64) in Trap mode. orbit_tick and orbit_pick now read the pointer
through orb_pt, which holds it within +-1000000 scene points and reads a NaN
as 0 (an out-of-range @intFromFloat would be a third trap). The test
the_orbit_tick_survives_a_pointer_far_outside_the_stage failed with
"integer overflow ... (* on i64)" before the change and passes after it;
glass_window: 95 passed, 0 failed. The seal is stale until re-saved.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* seal(t27os): re-save t27os_T27osGlassWindow after the orbit pointer clamp and the master merge (Refs #13015)

Re-saved with the post-#12824 t27c from a T27 OS shell-cell pane on the owner's word; glass_window 100/100.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(t27os): move the key-age words above the orbit's spans; the orbit read a packed age as a radius (Refs #13015)

The startup trap was a third overflow, and the real one. TPG_KEYAGE (137..139),
TPG_KEYAGE2 (140..159), TPG_KEYSTATE (201) and TPG_KEYFLEET (202) sat inside the
orbit's HX span (136..167) and HP span (200..231). main writes the packed key
ages every frame, so on the next tick orbit_tick read tg[137] (a row of four
u16 minute ages, about 2.2e14) as formula 1's radius, and ov_nearest_gap squared
the gap to the pointer in i64 and overflowed (Trap mode, brk #1). The earlier
orb_pt clamp and the keyage_lane fix stay as guards; neither was the cause of
this trap.

TPG_N grows from 256 to 288 and the four words move to 256..280. The word-map
test now claims them (it never did), with negative controls for the old
numbers, and a new test packs 220113431788053 into every key word, ticks the
orbit and relayouts it. With the old numbers it fails with `integer overflow
(* on i64)` and the word-map test fails too; with the new ones 101 pass, 0 fail.

The seal t27os_T27osGlassWindow is stale again until it is re-saved on the
owner's word.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* seal(t27os): re-save t27os_T27osGlassWindow after the key-age words moved above the orbit's spans (Refs #13015)

Re-saved on the owner's word from a T27 OS shell-cell pane with the post-#12824
t27c; 101/101 tests pass; the diff holds no home path.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* seal(t27os): re-save FrameGate and QueenDash, stale on master since 4c54f77 and 7b38a9c (Refs #13015)

coverage and spec-guards fail on the master tip 4037358 on these two
seals: the specs changed without a re-save. Saved with the post-#12824
t27c from a T27 OS shell-cell pane, on the owner's word. Tests 13/13 and
8/8, no home path in the diff.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* spec(port): main to specs/port/trios/apps/trios-macos/rings/RUST-04/clade-improve/src/main.t27 (Closes #9579) (#12919)

Co-authored-by: Dmitrii Fedorov <dmitrii-f-t27@users.noreply.github.com>

* spec(port): diff to specs/port/trios/crates/trios-git/src/diff.t27 (Closes #5540) (#12918)

Co-authored-by: Dmitrii Fedorov <dmitrii-f-t27@users.noreply.github.com>

* spec(t27os): research-graph card from the heat bench, HeatBench seal (Refs #13055)

Card lines law/params/conditions/observable/reference/verdict formatted
from physics/heat_bench public API; unstable-dt control test pins the
stability gate. HeatBench sealed first: a new import resolves against
its seal. Standalone test-report splice of cross-module imports is
blocked (issue #13055); project-wide build path next.

* spec(t27os): draw the research-graph card on the orbit page (Refs #13055)

Minimal wiring: use t27os::research_card, one plate on the formula-orbit
page, card_heading + six card_line rows, measured obs/ref mK via
bench dec_digits/dec_char, verdict word from card_verdict. card_title
renamed card_heading in the spec: bench::card_title(cu) already occupies
the name in this module. t27b test glass_window: 101/101 pass.

* seal(t27os): homes reseal after master merge (Refs #13055)

* spec(t27os): one stable identity per launch channel (Refs #13055)

install.t27: CHANNEL_PROD_ID ai.t27.os / CHANNEL_DEV_ID ai.t27.os.dev,
channel_ok + channel_is_dev (byte-exact compare, #5980 trap), plist_text
becomes the production wrapper over plist_text_channel(dev). plist_main
reads T27OS_CHANNEL (absent/empty = production, dev = development, any
other name exits 2). LaunchServices keeps the two channels as separate
applications: reopening the dev bundle activates one instance instead of
replacing the installed app (measured: three dev instances vanished under
the shared id before this change). install tests 27/27, plist_main 1/1,
make t27os build 7750 both channels verified end to end.

* spec(t27os): the research card's measured values ride the live module (Refs #13055)

Slice 2, data reload only: hot_reload gains RC_OBS_MK / RC_REF_MK keys
(same file, same revision gate, no second watcher; a theme-only module
leaves the card alone, an out-of-bound entry is refused). research_card
separates verdict_of(obs, ref) from the built-in values - data reloads
move values, never the rule. glass_window seeds TPG_RC_OBS/REF from the
card spec at start, live_load applies the same generation into the slots,
the draw reads the slots. Text/layout changes stay executable-code reload
(restart boundary). t27b glass_window: 101/101. hot_reload: 13/13, 0
vacuous. research_card verdict-rule tests added.

* spec(t27os): RC bound fits the real measured value (Refs #13055)

RC_MAX 1000 -> 1000000000: the FTCS midpoint is ~43000 mK, so the old
theme-sized bound refused the card's own real numbers. The bound test now
refuses 4000000000 and the doc line names the real magnitude.

* spec(t27os): a dev build never self-updates and never takes release live data (Refs #13055)

glass_window reads its own CFBundleIdentifier at start (NSBundle, the
same extern path as CFBundleVersion): a  suffix sets TPG_IS_DEV -
runtime evidence written by install.t27 plist_text_channel, not a build
flag. update_tick is gated on it: a dev build neither replaces its own
binary (swap_ready/UP_SWAP unreachable) nor runs check_cmd, whose first
act is downloading t27os-live.t27 over the local live file
(release.t27:1047). Local hot reload (live_load) is a separate path and
still runs. RC bound fixed to the parser's own 9-digit ceiling
(999999999): field_num refuses 10 digits, so 1000000000 was undeliverable.
t27b: glass_window 101/101, hot_reload 14/14.

* spec(t27os): ownership fence on the live file + dev diagnostics (Refs #13055)

Writers coordinate through the live module itself (one registry): a
candidate may name OWNER and OWNED_UNTIL; at the application boundary
owner_gate refuses a candidate written by another session while the
applied writer's lease holds - a contending writer cannot replace the
active valid surface, an expired lease falls through to the revision
gate. owner_hash is masked to 56 bits per step (h*33 by shifts and
adds): the dialect has no wrapping multiply. Rejections are visible:
TPG_RC_LAST carries applied / stale revision / invalid module / fenced
foreign writer, drawn as dev diagnostics under the research card on the
orbit page (channel, applied generation, owner, updates: disabled).
verdict_of tests: the rule moves with the values, not with the build.
t27b: glass_window 101/101, hot_reload 16/16.

* spec(t27os): validated all-or-none research-card candidate (Refs #13055)

Slice 3, data path: rc_candidate_ok gates a candidate on a sound module,
a strictly newer generation, and interface schema RC_SCHEMA=1;
rc_apply_atomic takes both card values together or leaves the
last-known-good pair untouched (slice 2 applied per-entry, which could
mix generations). artifact_hash binds the exact candidate bytes.
glass_window live_load uses the gate + atomic pair. Data path only - no
native-code swap claims. t27b: hot_reload 20/20, glass_window 101/101.

* spec(t27os): the dev channel reads its own live file (Refs #13055)

F_LIVE_DEV live-dev.t27 for TPG_IS_DEV instances: the release stream
owns live.t27 and rewrites it on its minute cadence, which clobbered a
dev operator's edits (measured 2026-11-01). Production reads live.t27
unchanged. glass_window 101/101.

* spec(t27os): dev-swap gate contract and the documented restore set (Refs #13055)

Slice 3 executable-path contract, rules only, no wiring: swap_allowed
gates the existing update machine for the dev channel (dev bundle id,
same-channel candidate, staged, schema 1); production keeps SWAP_NOT_DEV.
restore_key_at pins the eight NSUserDefaults keys main() re-reads at
startup, so the re-exec restore set is contract, not folklore. The
re-exec changes the PID - state preservation here is the documented
restore set, not a same-process guarantee. DevSwap: 3/3.

* spec(t27os): wire the dev-swap gate into the self-reload exec site (Refs #13055)

Before exec_self after a rebuild, the window validates the swapped-in
bundle: NSBundle bundleWithPath on the candidate reads
CFBundleIdentifier (must be ai.t27.os.dev, install.t27 channel id) and
CFBundleVersion (must parse, parse_build). Refusal keeps the CURRENT
binary running, records TPG_RC_LAST=5, and the dev diagnostics render
'swap: candidate refused, current binary kept'. Explicit trigger
unchanged: the rebuild itself is the command; the poll only reloads on a
real modification. t27b: glass_window 101/101, DevSwap 3/3.

* docs(compiler-defects): pinned repros and full issue drafts for C2/C3 (Refs #13055)

Known-failing repro set, held OUT of the swept specs tree and out of any
required-green gate: inputs, commands, tool versions, expected vs
observed, status, cause locations. C3 draft criteria corrected per
review: invalid input must be refused naming the builtin and the type
mismatch; an @intFromFloat hint is optional and explicit - no silent
reinterpretation, no lowering of an invalid cast. Publication awaits
owner confirmation.

* spec(t27os): exec-failure handling and kept-state round-trip checks (Refs #13055)

execv returning nonzero records TPG_RC_LAST=6 ('exec failed, still on
the old binary') and keeps serving; the dev diagnostics line renders it.
window_keep gains model-level round-trip checks for the kept state: flags
build/read for combinations, key identity for varied values, debounce
semantics (missing key settles before a write), restore gate (Option,
nothing kept, foreign kept value). Full re-exec observation stays a
separate stage. t27b: glass_window 101/101, window_keep 8/8.

* spec(t27os): explicit stage-validate-apply for the dev candidate (Refs #13055)

The rebuild only PREPARES the candidate. Application requires the dev
live module to carry APPLY_NOW=1 for APPLY_REV strictly newer than the
persisted applied generation (t27os.applied_rev in defaults, written
before the exec so one request fires exactly once across the re-exec).
On request: NSFileManager stages the candidate bundle beside the app,
the STAGED copy is re-validated (dev bundle id + parseable build), and
exec binds to the staged path - a later change at the build path cannot
replace the artifact being applied. Exec failure records TPG_RC_LAST=6
and keeps serving on the current binary. execv replaces the image: the
PID survives, the path becomes the staged bundle - observable proof of
which artifact is running. No request: the rebuild changes nothing.
hot_reload 21/21, glass_window 101/101.

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Dmitrii Fedorov <dmitrii.f@t27.ai>
Co-authored-by: Dmitrii Fedorov <dmitrii-f-t27@users.noreply.github.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