p='crates/spt-daemon/src/webserve.rs'
b=open(p,'rb').read(); crlf=b'\r\n' in b; s=b.decode().replace('\r\n','\n')
a='''    if raw_segment == "docs" {
        return adapter_docs(home, &name, docs_subpath, uri_path, query, head_only);
    }
'''
assert s.count(a)==1
s=s.replace(a,a+'''    // `changelog` is core's segment too, decided before the registry lookup
    // for the same reason: the page is the sidecar core rendered at install,
    // never a file the adapter's `web/` root happens to carry.
    // [impl->REQ-ADAPTER-CHANGELOG]
    if raw_segment == "changelog" && docs_subpath.is_empty() {
        return adapter_changelog(home, &name, head_only);
    }
''')
a2='''/// The adapter docs facet: `/<node>/a/<adapter>/docs/…`.'''
assert s.count(a2)==1
s=s.replace(a2,'''/// The adapter changelog page: `/<node>/a/<adapter>/changelog`, the HTML core
/// rendered from the manifest's `[adapter].changelog` when the adapter was
/// installed or updated. The daemon stays a byte-server — it renders nothing
/// per request. No sidecar (no declaration, or no adapter) answers one 404
/// naming the facet, like the docs segment.
// [impl->REQ-ADAPTER-CHANGELOG]
fn adapter_changelog(home: &Path, adapter: &str, head_only: bool) -> Resolved {
    match std::fs::read(spt_store::serving::adapter_changelog_page_in(home, adapter)) {
        Ok(bytes) => Resolved::Ready(response(
            StatusCode::OK,
            "text/html; charset=utf-8",
            bytes,
            head_only,
        )),
        Err(_) => Resolved::Ready(text(
            StatusCode::NOT_FOUND,
            format!("NOT_FOUND: facet a adapter {adapter} changelog\n"),
            head_only,
        )),
    }
}

'''+a2)
if crlf: s=s.replace('\n','\r\n')
open(p,'wb').write(s.encode())
