Repository navigation
source-hygiene sees all production code (column-zero split) + head_cuts ratchet - #5227
Conversation
|
Review #5227 exact head 24f51e7 against canary, 2026-10-20 18:49 UTC. [P1] Isolate the advertised hygiene change before landing. The actual PR diff includes context epoch/render behavior, request checkpoint logic, generated request protocol changes, and LLAMA_CPP_PIN 50b02b8 -> 76a1d605 (plus submodule update). This is not a hygiene-only prerequisite or pure move. Landing in the requested prerequisite order also lands those serving/context changes without their separate acceptance. Rebase/cherry-pick the intended hygiene commits onto current canary, or explicitly declare and independently validate the expanded scope; do not approve the narrow title as the full diff. [P2] production_half still does not scan all production code. In core/source-hygiene/src/lib.rs it stops at any column-zero #[cfg(test)], including a top-level test helper followed by production functions. An indented inner #![cfg(test)] also still terminates the whole enclosing file. Column zero fixes the observed impl helper but is not item scope. Add fixtures with a gated top-level helper followed by production and a nested test module with an inner attribute, and preserve following production when excluding test items. Documentation saying it errs only toward noise is false for these valid Rust shapes. Validation: read exact-head GitHub file patches and full PR changed-file inventory; no compilation, runtime mutation or claimed live regression. Existing #5221 bcedd84 gate finding remains unchanged: failed diff producer can exit success. No full approval. |
…t column zero production_half stopped at the first #[cfg(test)] anywhere, so an indented test-only helper inside an impl ended "production" for the rest of the file. In cognition/llm_deliberation_faculty.rs that hid ~9,000 production lines from every ratchet except derived_bounds, which already cut at column zero for this reason (it carried its own copy of the split). Found 2026-10-20 when deleting one such helper surfaced 4 hidden unwraps. One split for every rule, at column zero; derived_bounds' private copy is deleted. Baselines re-measured to what was always there (not new debt): unwraps 2,119 -> 2,274, serialization 234 -> 245, spawn sites 123 -> 128, hand-built homes 72 -> 79. source-hygiene 39/39. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
A cut that keeps the start of text drops what happened last (the newest message, result, outcome), so she acts as if time never moved and loops (Joel, 2026-10-20); and one source shrinking itself by its own number breaks the budget for everything else. The rule counts, on prompt paths (cognition, persona, rag, modules, airc, positron): head keepers (chars().take, head_to_tokens, truncate_chars, lines().next()), literal take/truncate/[..N], and literal .min/.clamp ceilings beside a size word (plain arithmetic such as backoff exponents is not flagged). A cut that never reaches a prompt says `head-cut-ok: <why>`. Measured 179 on this branch; the count may only fall. source-hygiene 41/41. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
…cannot move it A per-file count read +7 on #5224, which only moves test modules into sibling files: the same `use crate::modules::x` counted once per file it now sits in. A line is the coupling site; a pure move leaves it unchanged. The baseline is re-measured under the new unit in the next commit, from this tree's CI run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
44de4f3 to
c559c90
Compare
…e per-line unit CI on canary a854548 + this branch: boundary serialization 246, spawn sites 127, unjustified unwraps 2,279 (the split now sees production code that an indented #[cfg(test)] helper hid), upward imports 674 lines across 73 pairs (the unit changed from files to lines). No code changed between the two counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
|
Exact head 2fe46c2: previous stacked epoch/engine scope finding is resolved (eight source-hygiene files only). [P2] Shared production projection still hides actual production. Independent review found a concrete unchanged consumer: cognition/deliberation_prompt.rs:259 gates only test helper compose with a column-zero #[cfg(test)]. Production stable_blocks, volatile_blocks and helpers follow it; the real test module starts at546. production_half truncates all of them. Fix item-range exclusion and resume scanning afterward, retaining original line coordinates; extend coverage to a top-level test helper followed by violating production and production following a test module. The indented-helper fixture does not cover this. The new claim that the projection never hides production is false. Independent source replay substantiates layer baseline253 file/module pairs ->674 line/module pairs across73 module pairs, and head-cut baseline179 on unchanged base. Other baselines not independently reproduced here. Per-line metric is a textual-reference ratchet: two qualified refs on one line or replacing refs with an import changes counts without changing coupling. Describe that limit; it is not architectural coupling proof by itself. No builds/runtime changes. Scoped hold remains for shared production projection; scope cleanup and the two replayed baseline values pass. |
…st of the file The cut stopped at the first column-zero #[cfg(test)], which is the end of production only when the test mod is the file's last item. It is not in many files: ipc/mod.rs has ~3,400 production lines (start_server) after its test mod; commands/benchmark.rs has production between three test mods; persona_tools.rs and positron_source.rs gate a helper fn near the top. Found on #5225, where llamacpp_adapter.rs declared 'mod tests;' at line 93 of 934 and the split read as 10 unwraps removed when none were. The gated item's extent is read as one character stream (string escapes and continuations, raw strings, char literals vs lifetimes, comments), because test fixtures carry braces in multi-line strings. Audited on canary: of 1,249 gates, 1,248 close where rustfmt closes them; the one other is a #[cfg(test)] inside the generator's raw-string template, where the new cut keeps more real code. Regression test: only_the_gated_item_is_test_code_never_the_rest_of_the_file. Baselines re-measured on canary a854548 + this change (no code changed): unwraps 2,279 -> 2,377, homes 79 -> 103, spawns 127 -> 132, head cuts 179 -> 188, serialization 246 -> 251, underived bounds 159 -> 164, unwired 60 -> 61. Each is code that was always production and was never scanned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
|
Independent source review of bcbab21: the concrete deliberation_prompt compose-helper defect is fixed and subsequent production retains its original line coordinates. Two remaining valid-source counterexamples still hide production: [P2] Same-line gated item (lib.rs:233): [P2] Comment punctuation after closing brace (lib.rs:325-327): a gated module ending Extend existing tests with both cases, checking retained production and original line number. These are source-traced counterexamples, not compiled test receipts. Update stale SourceFile::production truncation wording and avoid claiming textual per-line coupling count is invariant under formatting/import regrouping. No builds or runtime changes; scoped hold remains. |
|
Concrete candidate for the three reviewed scanner cases on exact bcbab21. Prepared outside your checkout; no baseline edits. Exact-base apply check and parse-only rustfmt pass; Rust fixtures have NOT been executed. This is a proposed patch for owner review/integration, not approval of the PR. Independent candidate review is underway. Extends existing fixtures for same-line gated declarations, trailing-comment semicolon, real constructor closing syntax and restricted visibility. It retains the existing approximate projector: multiple items/attributes on one physical line and arbitrary nested block comments are not covered. Re-run affected fixtures and full hygiene on the authorized compiler, investigating measured totals before changing baselines. --- a/core/source-hygiene/src/lib.rs
+++ b/core/source-hygiene/src/lib.rs
@@ -230,7 +230,11 @@
i += 1;
continue;
}
- let end = gated_item_end(&lines, i + 1);
+ // The gated item can begin on the attribute's own line. Keep the slice's
+ // line count intact so blanking still preserves source line numbers.
+ let mut item_lines = lines[i..].to_vec();
+ item_lines[0] = &lines[i]["#[cfg(test)]".len()..];
+ let end = i + gated_item_end(&item_lines, 0);
out.extend(std::iter::repeat_n("", end + 1 - i));
gated = true;
i = end + 1;
@@ -324,7 +328,11 @@
depth = depth.saturating_sub(1);
// `};` / `});` closes the item on this line too; the `;` arm takes it.
let rest = text[i + 1..].split('\n').next().unwrap_or(""); // unwrap_or: split always yields one piece
- if depth == 0 && opened && !rest.contains(';') {
+ let rest = split_code_and_comment(rest).0.trim_start();
+ // Only immediate closing syntax continues this item. Punctuation in
+ // a trailing comment or a later statement cannot extend its lifetime.
+ let continues = matches!(rest.as_bytes().first(), Some(b';' | b')' | b']'));
+ if depth == 0 && opened && !continues {
return line;
}
}
@@ -717,6 +725,18 @@
assert_eq!(p.lines().count(), 5, "line numbers stay true");
let helper = "fn real() {}\n#[cfg(test)]\nfn helper() {\n q.unwrap();\n}\nfn more() {}\n";
assert_eq!(production_half(helper), "fn real() {}\n\n\n\n\nfn more() {}");
+ // Regression for #5227: a same-line test item must not consume its successor.
+ let inline = "#[cfg(test)] mod tests {}\nfn real() { x.unwrap(); }\n";
+ assert_eq!(production_half(inline), "\nfn real() { x.unwrap(); }");
+ let inline_decl = "#[cfg(test)] mod tests;\nfn real() { x.unwrap(); }\n";
+ assert_eq!(production_half(inline_decl), "\nfn real() { x.unwrap(); }");
+ // A comment's semicolon cannot make the closed test module swallow production.
+ let commented = "#[cfg(test)]\nmod tests {\n} // diagnostic; not syntax\nfn real() { x.unwrap(); }\n";
+ assert_eq!(production_half(commented), "\n\n\nfn real() { x.unwrap(); }");
+ // Real constructor closing syntax still belongs to the gated static.
+ let constructor = "#[cfg(test)]\nstatic X: LazyLock<()> = LazyLock::new(|| {\n});\nfn real() { x.unwrap(); }\n";
+ assert_eq!(production_half(constructor), "\n\n\nfn real() { x.unwrap(); }");
+
}
/// What this catches: the production/test split silently swallowing the whole
--- a/core/source-hygiene/src/derived_bounds.rs
+++ b/core/source-hygiene/src/derived_bounds.rs
@@ -111,14 +111,6 @@
"u8", "u16", "u32", "usize", "u64", "i32", "i64", "f32", "f64",
];
-/// Const declaration prefixes, longest first so `pub const` is not read as `const`.
-const CONST_PREFIXES: &[&str] = &[
- "pub(crate) const ",
- "pub(super) const ",
- "pub const ",
- "const ",
-];
-
pub struct DerivedBounds;
impl DerivedBounds {
@@ -188,9 +180,16 @@
/// `(name, type, value)` if this line declares a numeric constant.
fn const_declaration<'a>(code: &'a str) -> Option<(&'a str, &'a str, &'a str)> {
let trimmed = code.trim_start();
- let rest = CONST_PREFIXES
- .iter()
- .find_map(|p| trimmed.strip_prefix(*p))?;
+ // Visibility does not change whether a declaration is a numeric constant.
+ // Restricted visibility includes pub(in crate::owner), not only crate/super.
+ let declaration = if let Some(restricted) = trimmed.strip_prefix("pub(") {
+ restricted.split_once(')')?.1.trim_start()
+ } else if let Some(public) = trimmed.strip_prefix("pub ") {
+ public.trim_start()
+ } else {
+ trimmed
+ };
+ let rest = declaration.strip_prefix("const ")?;
let (name, tail) = rest.split_once(':')?;
let (ty, value) = tail.split_once('=')?;
let ty = ty.trim();
@@ -410,6 +409,11 @@
assert_eq!(DerivedBounds.check(&mk("let c = A_SECONDS * B_TOKENS_PER_S;")).len(), 1);
// A live-path bound with a bare literal and nothing said about it.
assert_eq!(DerivedBounds.check(&mk("const FILL_CAP_TOKENS: usize = 15_000;")).len(), 1);
+ // Regression for #5227: restricting visibility must not hide the same bound.
+ for visibility in ["pub", "pub(crate)", "pub(super)", "pub(self)", "pub(in crate::owner)"] {
+ let raw = format!("{visibility} const FILL_CAP_TOKENS: usize = 15_000;");
+ assert_eq!(DerivedBounds.check(&mk(&raw)).len(), 1, "{visibility}");
+ }
// The same, derived from a measurement or another named bound: fine.
assert!(DerivedBounds
.check(&mk("const FILL_CAP_TOKENS: usize = BOOTSTRAP_WORKING_SET as usize;"))
|
|
HOLD candidate comment6303540448: independent review found the closing-brace punctuation allowlist can stop early in valid gated static initializers ( |
|
Separately reviewed scoped patch against bcbab21: same-line cfg(test) handling and restricted const visibility, with existing-fixture additions. Independent Astra source approval plus parent exact-content check; apply check passes. No compilation claimed. This deliberately excludes the held closing-item repair. Run fixtures/full hygiene and remeasure on the authorized compiler before promotion. Do not use prior full candidate. --- a/core/source-hygiene/src/lib.rs
+++ b/core/source-hygiene/src/lib.rs
@@ -230,7 +230,11 @@
i += 1;
continue;
}
- let end = gated_item_end(&lines, i + 1);
+ // The gated item can begin on the attribute's own line. Keep the slice's
+ // line count intact so blanking still preserves source line numbers.
+ let mut item_lines = lines[i..].to_vec();
+ item_lines[0] = &lines[i]["#[cfg(test)]".len()..];
+ let end = i + gated_item_end(&item_lines, 0);
out.extend(std::iter::repeat_n("", end + 1 - i));
gated = true;
i = end + 1;
@@ -717,6 +721,12 @@
assert_eq!(p.lines().count(), 5, "line numbers stay true");
let helper = "fn real() {}\n#[cfg(test)]\nfn helper() {\n q.unwrap();\n}\nfn more() {}\n";
assert_eq!(production_half(helper), "fn real() {}\n\n\n\n\nfn more() {}");
+ // Regression for #5227: a same-line test item must not consume its successor.
+ let inline = "#[cfg(test)] mod tests {}\nfn real() { x.unwrap(); }\n";
+ assert_eq!(production_half(inline), "\nfn real() { x.unwrap(); }");
+ let inline_decl = "#[cfg(test)] mod tests;\nfn real() { x.unwrap(); }\n";
+ assert_eq!(production_half(inline_decl), "\nfn real() { x.unwrap(); }");
+
}
/// What this catches: the production/test split silently swallowing the whole
--- a/core/source-hygiene/src/derived_bounds.rs
+++ b/core/source-hygiene/src/derived_bounds.rs
@@ -111,14 +111,6 @@
"u8", "u16", "u32", "usize", "u64", "i32", "i64", "f32", "f64",
];
-/// Const declaration prefixes, longest first so `pub const` is not read as `const`.
-const CONST_PREFIXES: &[&str] = &[
- "pub(crate) const ",
- "pub(super) const ",
- "pub const ",
- "const ",
-];
-
pub struct DerivedBounds;
impl DerivedBounds {
@@ -188,9 +180,16 @@
/// `(name, type, value)` if this line declares a numeric constant.
fn const_declaration<'a>(code: &'a str) -> Option<(&'a str, &'a str, &'a str)> {
let trimmed = code.trim_start();
- let rest = CONST_PREFIXES
- .iter()
- .find_map(|p| trimmed.strip_prefix(*p))?;
+ // Visibility does not change whether a declaration is a numeric constant.
+ // Restricted visibility includes pub(in crate::owner), not only crate/super.
+ let declaration = if let Some(restricted) = trimmed.strip_prefix("pub(") {
+ restricted.split_once(')')?.1.trim_start()
+ } else if let Some(public) = trimmed.strip_prefix("pub ") {
+ public.trim_start()
+ } else {
+ trimmed
+ };
+ let rest = declaration.strip_prefix("const ")?;
let (name, tail) = rest.split_once(':')?;
let (ty, value) = tail.split_once('=')?;
let ty = ty.trim();
@@ -410,6 +409,11 @@
assert_eq!(DerivedBounds.check(&mk("let c = A_SECONDS * B_TOKENS_PER_S;")).len(), 1);
// A live-path bound with a bare literal and nothing said about it.
assert_eq!(DerivedBounds.check(&mk("const FILL_CAP_TOKENS: usize = 15_000;")).len(), 1);
+ // Regression for #5227: restricting visibility must not hide the same bound.
+ for visibility in ["pub", "pub(crate)", "pub(super)", "pub(self)", "pub(in crate::owner)"] {
+ let raw = format!("{visibility} const FILL_CAP_TOKENS: usize = 15_000;");
+ assert_eq!(DerivedBounds.check(&mk(&raw)).len(), 1, "{visibility}");
+ }
// The same, derived from a measurement or another named bound: fine.
assert!(DerivedBounds
.check(&mk("const FILL_CAP_TOKENS: usize = BOOTSTRAP_WORKING_SET as usize;"))
|
|
Replacement full candidate, revision 5, against exact bcbab21. Supersedes the HELD original candidate6303540448; safe.patch6303848883 is a subset, do not apply both. Independent Astra source review approves this frozen SHA ce579e35aff9b5ebd98db15e644ddbed2be96682cf7ee5c35bea5bebcfcc1159 after resolving every reported regression. Parent checked source. Same-line cfg, restricted const visibility, item termination and shared nested-comment parsing are covered by existing-fixture extensions, including source-line preservation. Exact-base applicability and syntax parsing pass. NO compiled test execution claimed; run affected fixtures/full hygiene and remeasure on the authorized compiler before promotion. No baseline edits. Existing line-based projection limitations remain; this is not a complete Rust parser. --- a/core/source-hygiene/src/lib.rs
+++ b/core/source-hygiene/src/lib.rs
@@ -230,7 +230,11 @@
i += 1;
continue;
}
- let end = gated_item_end(&lines, i + 1);
+ // The gated item can begin on the attribute's own line. Keep the slice's
+ // line count intact so blanking still preserves source line numbers.
+ let mut item_lines = lines[i..].to_vec();
+ item_lines[0] = &lines[i]["#[cfg(test)]".len()..];
+ let end = i + gated_item_end(&item_lines, 0);
out.extend(std::iter::repeat_n("", end + 1 - i));
gated = true;
i = end + 1;
@@ -242,6 +246,51 @@
out.pop();
}
out.join("\n")
+}
+
+/// Byte offset after a block comment's closing delimiter, given its body (after `/*`).
+/// Rust block comments nest; punctuation inside every nesting level is trivia.
+fn block_comment_end(bytes: &[u8]) -> Option<usize> {
+ let (mut depth, mut at) = (1usize, 0usize);
+ while at < bytes.len() {
+ if bytes[at..].starts_with(b"/*") {
+ depth += 1;
+ at += 2;
+ } else if bytes[at..].starts_with(b"*/") {
+ depth -= 1;
+ at += 2;
+ if depth == 0 { return Some(at); }
+ } else {
+ at += 1;
+ }
+ }
+ None
+}
+
+/// Skip Rust whitespace and comments. Comments are trivia even
+/// between `const` and `fn`; nested block comments are consumed as one comment.
+fn skip_item_trivia(mut src: &str) -> &str {
+ loop {
+ src = src.trim_start();
+ if let Some(comment) = src.strip_prefix("//") {
+ match comment.find('\n') {
+ Some(end) => src = &comment[end + 1..],
+ None => return "",
+ }
+ } else if let Some(comment) = src.strip_prefix("/*") {
+ let Some(end) = block_comment_end(comment.as_bytes()) else { return "" };
+ src = &comment[end..];
+ } else {
+ break;
+ }
+ }
+ src
+}
+
+fn significant_word(src: &str) -> (Option<&str>, &str) {
+ let src = skip_item_trivia(src);
+ let end = src.bytes().take_while(|b| b.is_ascii_alphanumeric() || *b == b'_').count();
+ if end == 0 { (None, src) } else { (Some(&src[..end]), &src[end..]) }
}
/// Index of the last line of the item starting at or after `from` (attributes, blank
@@ -260,9 +309,36 @@
return last;
};
let text = lines[head..].join("\n");
+ // Initializer blocks can be followed by operators, method calls, or more blocks.
+ // A static/const ends at its outer semicolon, never at an initializer's `}`.
+ let (mut keyword, mut rest) = significant_word(&text);
+ if keyword == Some("pub") {
+ rest = skip_item_trivia(rest);
+ if let Some(restricted) = rest.strip_prefix('(') {
+ rest = restricted;
+ loop {
+ rest = skip_item_trivia(rest);
+ match rest.chars().next() {
+ Some(')') => {
+ rest = &rest[1..];
+ break;
+ }
+ Some(ch) => rest = &rest[ch.len_utf8()..],
+ None => return last,
+ }
+ }
+ }
+ (keyword, rest) = significant_word(rest);
+ }
+ let semicolon_terminated = match keyword {
+ Some("static") => true,
+ Some("const") => !matches!(significant_word(rest).0, Some("fn" | "unsafe" | "extern")),
+ _ => false,
+ };
let b = text.as_bytes();
let ident = |at: usize| b[at].is_ascii_alphanumeric() || b[at] == b'_';
let (mut depth, mut line, mut i, mut opened) = (0usize, head, 0usize, false);
+ let (mut parentheses, mut brackets) = (0usize, 0usize);
while i < b.len() {
match b[i] {
b'\n' => line += 1,
@@ -272,12 +348,10 @@
}
}
b'/' if b.get(i + 1) == Some(&b'*') => {
- i += 2;
- while i + 1 < b.len() && !(b[i] == b'*' && b[i + 1] == b'/') {
- line += usize::from(b[i] == b'\n');
- i += 1;
- }
- i += 1;
+ let start = i + 2;
+ let Some(length) = block_comment_end(&b[start..]) else { return last };
+ line += b[start..start + length].iter().filter(|&&c| c == b'\n').count();
+ i = start + length - 1;
}
// A raw string, r"…" / r#"…"# / br#"…"#: no escapes, ends at `"` + the same hashes.
b'r' if (i == 0 || !ident(i - 1)) || (b[i - 1] == b'b' && (i < 2 || !ident(i - 2))) => {
@@ -322,13 +396,17 @@
}
b'}' => {
depth = depth.saturating_sub(1);
- // `};` / `});` closes the item on this line too; the `;` arm takes it.
- let rest = text[i + 1..].split('\n').next().unwrap_or(""); // unwrap_or: split always yields one piece
- if depth == 0 && opened && !rest.contains(';') {
+ if depth == 0 && parentheses == 0 && brackets == 0
+ && opened && !semicolon_terminated
+ {
return line;
}
}
- b';' if depth == 0 => return line,
+ b'(' => parentheses += 1,
+ b')' => parentheses = parentheses.saturating_sub(1),
+ b'[' => brackets += 1,
+ b']' => brackets = brackets.saturating_sub(1),
+ b';' if depth == 0 && parentheses == 0 && brackets == 0 => return line,
_ => {}
}
i += 1;
@@ -717,6 +795,55 @@
assert_eq!(p.lines().count(), 5, "line numbers stay true");
let helper = "fn real() {}\n#[cfg(test)]\nfn helper() {\n q.unwrap();\n}\nfn more() {}\n";
assert_eq!(production_half(helper), "fn real() {}\n\n\n\n\nfn more() {}");
+ // Regression for #5227: a same-line test item must not consume its successor.
+ let inline = "#[cfg(test)] mod tests {}\nfn real() { x.unwrap(); }\n";
+ assert_eq!(production_half(inline), "\nfn real() { x.unwrap(); }");
+ let inline_decl = "#[cfg(test)] mod tests;\nfn real() { x.unwrap(); }\n";
+ assert_eq!(production_half(inline_decl), "\nfn real() { x.unwrap(); }");
+ // A comment's semicolon cannot make the closed test module swallow production.
+ let commented = "#[cfg(test)]\nmod tests {\n} // diagnostic; not syntax\nfn real() { x.unwrap(); }\n";
+ assert_eq!(production_half(commented), "\n\n\nfn real() { x.unwrap(); }");
+ // Real constructor closing syntax still belongs to the gated static.
+ let constructor = "#[cfg(test)]\nstatic X: LazyLock<()> = LazyLock::new(|| {\n});\nfn real() { x.unwrap(); }\n";
+ assert_eq!(production_half(constructor), "\n\n\nfn real() { x.unwrap(); }");
+ // Regression for the first proposed fix: initializer blocks do not end a static.
+ for initializer in [
+ "{1} + { let y = 2;\n const EXTRA_LIMIT: usize = 9;\n y + EXTRA_LIMIT\n}",
+ "{1usize}.wrapping_add({ let y = 2;\n const EXTRA_LIMIT: usize = 9;\n y + EXTRA_LIMIT\n})",
+ "[ { let y = 2;\n const EXTRA_LIMIT: usize = 9;\n y + EXTRA_LIMIT\n} ][0]",
+ ] {
+ for declaration in [
+ "static X", "const X", "pub(in crate::owner) const X",
+ "pub\nconst X", "pub /* comment */ (crate) const X",
+ "pub // visibility\n(in crate::owner) static X",
+ ] {
+ let raw = format!("#[cfg(test)]\n{declaration}: usize = {initializer};\nfn real() {{ x.unwrap(); }}\n");
+ let projected = production_half(&raw);
+ assert!(!projected.contains("EXTRA_LIMIT"), "{projected}");
+ assert_eq!(projected.lines().last(), Some("fn real() { x.unwrap(); }"));
+ assert_eq!(projected.lines().count(), raw.lines().count(), "line positions");
+ }
+ }
+ // Const functions still end with their body, even when a comment has punctuation.
+ let konst_fn = "#[cfg(test)]\nconst fn helper() -> usize { 1 } // ;\nfn real() { x.unwrap(); }\n";
+ assert_eq!(production_half(konst_fn), "\n\nfn real() { x.unwrap(); }");
+ // Regression for proposed revision 4: nested comment delimiters are never code.
+ let nested = "#[cfg(test)]\nfn helper() { /* outer /* inner */ ( [ { ;\n tail ) ] } */ }\nfn production() { x.unwrap(); }\n";
+ assert_eq!(production_half(nested), "\n\n\nfn production() { x.unwrap(); }");
+ let open_delimiter = "#[cfg(test)]\nfn helper() { /* outer /* inner */ ( */ }\nfn production() { x.unwrap(); }\n";
+ assert_eq!(production_half(open_delimiter), "\n\nfn production() { x.unwrap(); }");
+
+ // Regression for proposed revision 2: comments are whitespace between keywords.
+ for trivia in ["/* explanation */", "// explanation\n", "/* outer /* nested */ tail */"] {
+ let raw = format!("#[cfg(test)]\nconst {trivia} fn helper() -> usize {{ 1 }}\nfn production() {{ x.unwrap(); }}\n");
+ let projected = production_half(&raw);
+ assert_eq!(projected.lines().last(), Some("fn production() { x.unwrap(); }"));
+ assert!(!projected.contains("helper"));
+ assert_eq!(projected.lines().count(), raw.lines().count());
+ }
+
+
+
}
/// What this catches: the production/test split silently swallowing the whole
--- a/core/source-hygiene/src/derived_bounds.rs
+++ b/core/source-hygiene/src/derived_bounds.rs
@@ -111,14 +111,6 @@
"u8", "u16", "u32", "usize", "u64", "i32", "i64", "f32", "f64",
];
-/// Const declaration prefixes, longest first so `pub const` is not read as `const`.
-const CONST_PREFIXES: &[&str] = &[
- "pub(crate) const ",
- "pub(super) const ",
- "pub const ",
- "const ",
-];
-
pub struct DerivedBounds;
impl DerivedBounds {
@@ -188,9 +180,16 @@
/// `(name, type, value)` if this line declares a numeric constant.
fn const_declaration<'a>(code: &'a str) -> Option<(&'a str, &'a str, &'a str)> {
let trimmed = code.trim_start();
- let rest = CONST_PREFIXES
- .iter()
- .find_map(|p| trimmed.strip_prefix(*p))?;
+ // Visibility does not change whether a declaration is a numeric constant.
+ // Restricted visibility includes pub(in crate::owner), not only crate/super.
+ let declaration = if let Some(restricted) = trimmed.strip_prefix("pub(") {
+ restricted.split_once(')')?.1.trim_start()
+ } else if let Some(public) = trimmed.strip_prefix("pub ") {
+ public.trim_start()
+ } else {
+ trimmed
+ };
+ let rest = declaration.strip_prefix("const ")?;
let (name, tail) = rest.split_once(':')?;
let (ty, value) = tail.split_once('=')?;
let ty = ty.trim();
@@ -410,6 +409,11 @@
assert_eq!(DerivedBounds.check(&mk("let c = A_SECONDS * B_TOKENS_PER_S;")).len(), 1);
// A live-path bound with a bare literal and nothing said about it.
assert_eq!(DerivedBounds.check(&mk("const FILL_CAP_TOKENS: usize = 15_000;")).len(), 1);
+ // Regression for #5227: restricting visibility must not hide the same bound.
+ for visibility in ["pub", "pub(crate)", "pub(super)", "pub(self)", "pub(in crate::owner)"] {
+ let raw = format!("{visibility} const FILL_CAP_TOKENS: usize = 15_000;");
+ assert_eq!(DerivedBounds.check(&mk(&raw)).len(), 1, "{visibility}");
+ }
// The same, derived from a measurement or another named bound: fine.
assert!(DerivedBounds
.check(&mk("const FILL_CAP_TOKENS: usize = BOOTSTRAP_WORKING_SET as usize;"))
|
Applies the source-approved replacement from #5227 comment 6304136412 (Astra independent review) against bcbab21, unchanged: - a #[cfg(test)] item that starts on the attribute's own line is blanked, with source line numbers preserved; - item termination stays correct for static initializers and method continuations; - one nested block-comment scanner is shared (duplicate removed); - pub(in ...) and other restricted const visibilities are recognized by derived_bounds. Measured on this tree: cargo test -p source-hygiene, 42 passed. Every ratchet sits exactly at its existing baseline, so no baseline was edited. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
…canner Every ratchet sits exactly at #5227's baselines (cargo test -p source-hygiene 42/42); the earlier derived_bounds 159->158 came from the old scanner hole that blanked restricted-visibility production constants. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
cargo test -p source-hygiene 42/42 with every ratchet exactly at the values written here; each lines-over number equals the canary-plus-scanner base (154,999) minus this split's removed excess. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
cargo test -p source-hygiene 42/42 with every ratchet exactly at the values written here; each lines-over number equals the canary-plus-scanner base (154,999) minus this split's removed excess. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
…fall's cause named source-hygiene 42/42 at exactly these values. Every fall was traced by diffing the full violation sets against #5227: - lines over 1000: 147,314 = 154,999 - the three files' removed excess. - unjustified unwraps 2,377 -> 2,368: nine justified in place in afa6700, not removed. - unwired 61 -> 60: SemanticDistiller was always built in its own file; that construction now sits in a sibling. Not new wiring. - upward imports 674 -> 673: a rustdoc link became prose. No code change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
|
Codex review: SOURCE PASS at exact head 6ac1a84. My previous scanner blockers are resolved. The integrated lib.rs and derived_bounds.rs are byte-for-byte identical to bcbab21 plus independently reviewed revision5.patch (SHA256 ce579e35aff9b5ebd98db15e644ddbed2be96682cf7ee5c35bea5bebcfcc1159). This resolves the earlier patch-hash discrepancy by checking resulting source. I re-read the delta: same-line cfg items, comment punctuation, const/static initializer continuations, restricted visibility and nested-comment cases are covered without swallowing following production. No baseline changes were introduced by this final correction. Verified all eight checks green on this head. Independently read source-hygiene run39528575399: 42 tests passed, including gated-item regressions. Core tests and Windows compilation/custody/lifecycle also pass. No local compilation or deployment performed. The per-line layer rule remains a textual-reference ratchet, not proof of unchanged architectural coupling under arbitrary formatting; prior limitation still applies. Review clears #5227 at this head. #5228 remains a separate review; this does not approve its entire sweep or claim live performance/learning results. |
…a cut at the first cfg(test) Codex on #5228 (REQUEST CHANGES, comment 6307538140): the shared test reader ended production at the first column-zero #[cfg(test)], so production below a mid-file test mod or gated helper was invisible to the lived-turn exactly-one- caller guard, which the old private scan did see. That is the same hole production_half already closed for the ratchets (#5227). - production() delegates to source_hygiene::production_half (existing dev-dependency); only the gated items are removed. - code_only delegates to source_hygiene::split_code_and_comment, the one string-aware comment rule, instead of a second cruder copy. - Regression test: a function below a mid-file test mod stays production, and the gated item does not. Uncompiled locally (serving node); CI runs the guard tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
…pure moves) (#5228) * Every ratchet scans the production code that exists: the split cuts at column zero production_half stopped at the first #[cfg(test)] anywhere, so an indented test-only helper inside an impl ended "production" for the rest of the file. In cognition/llm_deliberation_faculty.rs that hid ~9,000 production lines from every ratchet except derived_bounds, which already cut at column zero for this reason (it carried its own copy of the split). Found 2026-10-20 when deleting one such helper surfaced 4 hidden unwraps. One split for every rule, at column zero; derived_bounds' private copy is deleted. Baselines re-measured to what was always there (not new debt): unwraps 2,119 -> 2,274, serialization 234 -> 245, spawn sites 123 -> 128, hand-built homes 72 -> 79. source-hygiene 39/39. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * head_cuts: a ratchet on text cuts that drop the newest end of her prompt A cut that keeps the start of text drops what happened last (the newest message, result, outcome), so she acts as if time never moved and loops (Joel, 2026-10-20); and one source shrinking itself by its own number breaks the budget for everything else. The rule counts, on prompt paths (cognition, persona, rag, modules, airc, positron): head keepers (chars().take, head_to_tokens, truncate_chars, lines().next()), literal take/truncate/[..N], and literal .min/.clamp ceilings beside a size word (plain arithmetic such as backoff exponents is not flagged). A cut that never reaches a prompt says `head-cut-ok: <why>`. Measured 179 on this branch; the count may only fall. source-hygiene 41/41. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * layer_discipline counts coupling sites per line, so a split by owner cannot move it A per-file count read +7 on #5224, which only moves test modules into sibling files: the same `use crate::modules::x` counted once per file it now sits in. A line is the coupling site; a pure move leaves it unchanged. The baseline is re-measured under the new unit in the next commit, from this tree's CI run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Ratchet baselines measured on canary for the column-zero split and the per-line unit CI on canary a854548 + this branch: boundary serialization 246, spawn sites 127, unjustified unwraps 2,279 (the split now sees production code that an indented #[cfg(test)] helper hid), upward imports 674 lines across 73 pairs (the unit changed from files to lines). No code changed between the two counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * production_half blanks only the #[cfg(test)]-gated item, never the rest of the file The cut stopped at the first column-zero #[cfg(test)], which is the end of production only when the test mod is the file's last item. It is not in many files: ipc/mod.rs has ~3,400 production lines (start_server) after its test mod; commands/benchmark.rs has production between three test mods; persona_tools.rs and positron_source.rs gate a helper fn near the top. Found on #5225, where llamacpp_adapter.rs declared 'mod tests;' at line 93 of 934 and the split read as 10 unwraps removed when none were. The gated item's extent is read as one character stream (string escapes and continuations, raw strings, char literals vs lifetimes, comments), because test fixtures carry braces in multi-line strings. Audited on canary: of 1,249 gates, 1,248 close where rustfmt closes them; the one other is a #[cfg(test)] inside the generator's raw-string template, where the new cut keeps more real code. Regression test: only_the_gated_item_is_test_code_never_the_rest_of_the_file. Baselines re-measured on canary a854548 + this change (no code changed): unwraps 2,279 -> 2,377, homes 79 -> 103, spawns 127 -> 132, head cuts 179 -> 188, serialization 246 -> 251, underived bounds 159 -> 164, unwired 60 -> 61. Each is code that was always production and was never scanned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * 69 oversized files: each one's test module moves to a sibling tests.rs New rule (Joel, 2026-10-20): no one edits a file over 1,000 lines. 76 of the 145 Rust files over 1,000 lines were over only because their inline #[cfg(test)] mod tests sat inside them. This moves that module, byte for byte (no re-indent, so string literals are untouched), to `<stem>/tests.rs`; the parent keeps `#[cfg(test)] mod tests;`. A child module keeps `use super::*` access, so nothing else changes. Moved: 69 files (66 continuum-core, 3 continuum-cli-lifecycle). Skipped: 11 being split on other branches, crate roots (main/lib/mod/bin), and 1 file with items after its test mod. One include_str! path is one level deeper (prebuilt_artifact tests). Verified: #[test]/#[tokio::test] attributes 8,320 before and after; continuum-core lib tests compile; continuum-cli-lifecycle 79 pass with the same 1 failure canary has (card 250ce9c8). Still over 1,000 after this and left to the split work: modules/forge.rs (1,003), and the tests files of cognition/recall_faculty (1,245) and commands/training_trigger/submit (1,332). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Moved test modules declare themselves test code (#![cfg(test)]) Without the inner attribute the hygiene scanner read the 69 moved tests.rs files as production (the file_engine split showed unwraps rising 150). The repo's existing convention for a test module in its own file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * One reader for the crate's own source: a moved test file is test code, owned by its module Two source-reading guards failed on #5224 because a test module moved into a sibling tests.rs read as production: experience/tests.rs became a second caller of record_lived_turn, service_module/tests.rs a registration of PersonaServiceModule. Each guard carried its own copy of the walk and the comment strip, so each would have needed its own fix. source_tree (cfg(test)) is the one reader: crate_sources(), and per file is_test_file(), production() and owner() (x/tests.rs belongs to x.rs). Migrated: the module-wiring audit (keys references by owner), the lived-turn caller count (production only), the loose-id scan, the GPU base check and the context-constant scan. Five private walks deleted. The swe env-root guard keeps its copy until the sweep splits swe_bench.rs (5,946 lines; no edits over 1,000). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * source_tree lives under test_env; baselines lowered to what #5224 measures lib.rs declaring two cfg(test) modules counted as a second test mod (19 -> 20), so the source reader nests under test_env, the crate's test environment. CI on this branch: lines past the readable size 154,999 -> 136,485, unwired public machinery 60 -> 58. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * production_reachability: a moved test module is still its owner's own test Retracts the previous commit's reason for 60 -> 58. That drop was a miscount, not a win: the rule reads a type as wired when its name appears outside its own file, test code included, so moving a test module into a sibling tests.rs made two types constructed only in their own tests read as externally used, the exact AgentContext (#27) shape this rule exists to catch. SourceFile::owning_module() names the module a file's code belongs to (x for x.rs, x/mod.rs, and a #![cfg(test)] x/tests.rs or x/tests/part_N.rs); the rule's own-mentions now include the moved tests of the same module. Baseline back to 60; regression test a_type_constructed_only_in_its_moved_tests_is_still_reported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * production_reachability: own the joined text the counts borrow from Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Split llamacpp_adapter.rs by owner: construction, payload, tests (1794 -> 934) Pure move. construction.rs: inherent builders + ensure_loaded (+Default); payload.rs: sampling/media decode; tests.rs: tests mod. Tests 12 passed/1 ignored before and after. Two tracing::warn! gain an explicit target so log targets are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Split persona/response.rs: sanitize + tests (1504 -> 918) Pure move. sanitize.rs: think-block/leaked-markup stripping; tests.rs: tests mod. Tests 19 passed before and after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Split genome/teach.rs: progress, status, tests (1410 -> 944) Pure move. progress.rs: watch cell/ledger/bus milestones; status.rs: genome/teach-status; tests.rs. Public paths kept via re-exports. Tests 15 passed before and after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Split modules/agent.rs: tools (1393 -> 841) Pure move. tools.rs: tool-call parsing and tool implementations. Tests 5 passed before and after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Split cognition/generate_response.rs: tests (1367 -> 644) Pure move of the tests mod. Tests 44 passed before and after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Split airc_remote/transport.rs: tests (1161 -> 757) Pure move of the tests mod. Tests 12 passed before and after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Split inference/handle_module.rs: tests (1095 -> 663) Pure move of the tests mod. Tests 23 passed before and after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Split persona/rag_inspect.rs: tests (1035 -> 684) Pure move of the tests mod. Tests 15 passed before and after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * file_size baseline 136,485 -> 133,731 after the eight splits (measured on this head) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * WIP: split the 59 remaining oversized files by owner (scripted, pure moves) Lines past 1000: 153,027 -> 58,046 (files over 1000: ~140 -> 18). Test attributes 8,320 = base. Workspace tests vs base: 9,573/43 vs 9,568/48; the 8 sweep-only failures were source-reading tests (fixed: loose-id declarations moved with their fields, the guard sees widened fields, three include paths). Ratchets: at or below canary's true counts once the column-zero scanner fix lands; upward-imports (per-file count) and derived-bounds (+3) still to reconcile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * The swe env-root guard reads the crate through test_env::source_tree The sixth private source walk, deferred in #5224 while swe_bench.rs was 5,946 lines; the sweep split it, so the guard now uses the shared reader. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Scanned constants keep any visibility; sweep baselines measured on this head The split widens a moved constant to pub(in crate::path), which neither derived_bounds' prefix list nor the context-constant guard recognized, so NARRATION_BUDGET left the scan the day it moved. Both now strip any visibility. Measured on this head: lines past the readable size 133,731 -> 57,268; excess test mods 19 -> 15 (multi-mod suites became nested themes in one test file); unwired 61 -> 57, which is NOT a win: four types read as wired only because their constructor moved to a sibling chunk (named at the baseline, card 7660e70f). Unjustified unwraps, upward imports, spawns, homes, serialization, head cuts and underived bounds are unchanged: the sweep moves code, it changes none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * The sweep's imports narrowed to what each module actually re-exports; zero new warnings The splitter gave every child a 'pub use child::*' in its parent. Where the child's items are crate- or module-scoped that re-export was too wide (56 'glob import doesn't reexport' warnings) or reached nothing (51 unused). Each glob now carries the visibility its items have (pub(crate), the module's own pub(in ...), or private), and the ones nothing resolves through are removed, compiler-checked after each pass. run_harness/Harness are crate-scoped (their only caller is grade.rs) instead of widening a chain of private types. Built on the M5 in a build window (serving down), cargo test --lib --no-run with --features metal,accelerate: 0 warnings that the base (#5225 head) does not have; 63 total vs the base's 72 (9 old unused imports went with them). The CI baseline is set to 66 on the inference that CI's Linux build carries the same 3 cfg-only warnings it did at the base (75 vs 72); CI prints the exact number. cargo test -p continuum-core --lib (metal, M5): 9,002 passed, 2 failed: - the lived-turn guard named settle.rs; the driver now sits in settle/, so the guard accepts the settle module (fixed here, passes). - config_env read_all_on_a_missing_file: a stale temp file from an earlier run on this machine (card 4c820b46); passes on fresh CI runners. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * kill9: the parent glob import is Windows-only, where its one caller lives Removed as unused on the macOS build; the Windows build needs it for parse_tasklist_image_name (CI: Windows core compilation, E0425). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * benchmark_dispatch: recipe path extracted to run_recipe (no behaviour change) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * voice_module: decompose handle_command into per-family files (no behaviour change) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * model catalog: models() split into per-provider-family row functions, original order kept (no behaviour change) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * launch_gate: windows module decomposed into startup gate, scheduler script, custody, recovery journal and tests (no behaviour change) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * serve_persona_loop_inner: decomposed by responsibility (no behaviour change) Wake selection, quiescence, self-tick, backlog resync + loop-filler gate, turn intake (admit/compose/burst), the WorkspaceCycle step and the spoken-turn settle each move to a sibling module; the loop reads as setup + named steps with Step enums for the continue/break exits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * start_server.rs: decomposed by boot phase (no behaviour change) start_server() was one 3,388-line function. It is now the ordered list of boot phases (259 lines); each phase lives in a child module under ipc/start_server/ that owns it (model registry, foundation modules, resource authority, serving, pressure broker, inference, cognition, live call, service modules, AIRC discovery, persona registry/hosting/ reconciler, re-home reconciler, AI+genome, closing modules, runtime start, command executor, listeners, TCP ingress, WS ingress, memory guard, accept loop). Code is moved verbatim; shared values travel as parameters or small structs (Foundation, CognitionHandles, LiveCall, CodeHandles, AircBoot, RuntimeStarted). Order of spawns, registrations and binds is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * start_server: keep the unwrap_or_else justification on its own line rustfmt moved the same-line `// unwrap_or_else: ...` comment to the next line, which the unwrap ratchet counts as unjustified (2377 -> 2378). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * persona loop: phase_timings is mutable where say_ms is recorded; baselines for the deduplicated trigger CI E0594 on turn_settle.rs. The loop built its trigger InboxMessage twice (the loop-filler gate and admission), each with a peer- id cut and an unwrap_or_else; trigger_inbox_message builds it once, so head cuts 188 -> 187 and unjustified unwraps 2,377 -> 2,376 (checked in the diff), lines past the readable size 57,268 -> 56,859. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * launch_gate: the PowerShell include is two directories deeper; file_size baseline 57,131 Windows CI: couldn't read windows-prepared.ps1 from launch_gate/windows/. The path now climbs seven levels (checked: the file resolves). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * file_size baseline 57,131 -> 54,053 with the six giant items decomposed (measured on this merge) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * fix(source-hygiene): integrate Codex's reviewed scanner revision 5 Applies the source-approved replacement from #5227 comment 6304136412 (Astra independent review) against bcbab21, unchanged: - a #[cfg(test)] item that starts on the attribute's own line is blanked, with source line numbers preserved; - item termination stays correct for static initializers and method continuations; - one nested block-comment scanner is shared (duplicate removed); - pub(in ...) and other restricted const visibilities are recognized by derived_bounds. Measured on this tree: cargo test -p source-hygiene, 42 passed. Every ratchet sits exactly at its existing baseline, so no baseline was edited. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * test_env/source_tree: production is source-hygiene's projection, not a cut at the first cfg(test) Codex on #5228 (REQUEST CHANGES, comment 6307538140): the shared test reader ended production at the first column-zero #[cfg(test)], so production below a mid-file test mod or gated helper was invisible to the lived-turn exactly-one- caller guard, which the old private scan did see. That is the same hole production_half already closed for the ratchets (#5227). - production() delegates to source_hygiene::production_half (existing dev-dependency); only the gated items are removed. - code_only delegates to source_hygiene::split_code_and_comment, the one string-aware comment rule, instead of a second cruder copy. - Regression test: a function below a mid-file test mod stays production, and the gated item does not. Uncompiled locally (serving node); CI runs the guard tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Restore the comments the split dropped; the moved Windows test file is #![cfg(test)] Independent whole-PR review of 7bcdb2b (REQUEST CHANGES, P2): the splitter carried code faithfully but dropped about 506 lines of free-standing `//` comments between items, plus trailing comments on const lines. Examples are the MAX_LANES history in serving_plan.rs, the evidence-ledger rules in benchmark.rs and the parser format examples. - 186 blocks (596 lines) restored by script. Each is placed before the line that followed it in canary, matched on the next three lines with visibility normalised; indentation follows the new nesting. - Three trailing const comments restored: `// 2 GiB`, `// 1 hour`, `// 0=Normal`. - Seven blocks placed by hand: section banners, the ipc handler pointer, the vector-params note, test-module banners and the model-family parser banner. - Not restored, on purpose: comments on test code that the shared source_tree reader replaced (experience.rs code_only, device_probe.rs). The persona-loop provenance and wake-engram notes were already carried, as rewrites, in turn_cycle.rs and turn_context.rs. - The diff adds comment lines only, apart from the three trailing comments on existing lines; no code changes. - launch_gate/windows/tests.rs now starts with #![cfg(test)] (review finding 3). source-hygiene 43/43, no count moved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo * Restore the benchmark/swe-setup rationale above SweSetupParams; trailing comments keep one space Review of ad6dc73: the last block the split dropped (canary benchmark.rs:3930-3940). The three restored trailing comments now use one space before //, as canary had. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Rebuilt as canary plus this PR's own commits (cherry-picked with -x). The old branch carried #5227/#5228's pre-squash history. Each changed count is traced to its cause in the comment beside it. cargo test -p source-hygiene passes 43/43 on a fresh per-worktree build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
Rebuilt as canary plus this PR's own commits (cherry-picked with -x). The old branch carried #5227/#5228's pre-squash history. Each changed count is traced to its cause in the comment beside it. cargo test -p source-hygiene passes 43/43 on a fresh per-worktree build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
Rebuilt as canary plus this PR's own commits (cherry-picked with -x). The old branch carried #5227/#5228's pre-squash history. Each changed count is traced to its cause in the comment beside it. cargo test -p source-hygiene passes 43/43 on a fresh per-worktree build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
Rebuilt as canary plus this PR's own commits (cherry-picked with -x). The old branch carried #5227/#5228's pre-squash history. Each changed count is traced to its cause in the comment beside it. cargo test -p source-hygiene passes 43/43 on a fresh per-worktree build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
Two changes to
source-hygiene.1. Every ratchet now scans all production code.
production_halfstopped at the first#[cfg(test)]anywhere in a file, so an indented test helper inside animplended "production" for the rest of the file. Incognition/llm_deliberation_faculty.rsthat hid about 9,000 lines from every ratchet exceptderived_bounds, which already carried its own column-zero split. There is now one split, at column zero, for every rule.Baselines are re-measured to what was always there; this is not new debt:
2.
head_cutsratchet (179 sites when measured, 2026-10-20). On prompt paths it counts cuts that keep the head of text or shrink it by a literal:chars().take,head_to_tokens, first-line-only,[..N], literaltake/truncate, andmin/clampceilings next to a size word. These drop the newest end, so the mind acts as if time never moved. A cut that never reaches a prompt opts out withhead-cut-ok: <why>.The file splits (#5224, #5225, #5226 and the sweep) are measured against these true baselines, so this should land before them.
🤖 Generated with Claude Code