diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a0eaa8e --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 Umbra Tools (umbratools.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..726016d --- /dev/null +++ b/NOTICE @@ -0,0 +1,2 @@ +Umbra Tools (https://umbratools.com) +Copyright 2026 Umbra Tools (umbratools.com) diff --git a/backup/Starthere.sh b/backup/Starthere.sh index 03e752f..bd91336 100755 --- a/backup/Starthere.sh +++ b/backup/Starthere.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # Restore an UmbraAudio full backup and rebuild a portable runtime. set -Eeuo pipefail diff --git a/backup/author_voice_lab/scripts/analyse_lab.py b/backup/author_voice_lab/scripts/analyse_lab.py index 1403a60..dd1f16d 100644 --- a/backup/author_voice_lab/scripts/analyse_lab.py +++ b/backup/author_voice_lab/scripts/analyse_lab.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Analyse the lab: variance vs separation, and verify a suspicious F0 reading.""" from __future__ import annotations @@ -88,4 +91,4 @@ lo = min(st(r["f0_median"], REF_F0) for r in usable) hi = max(st(r["f0_median"], REF_F0) for r in usable) step = 2 * F0_SD_ST print(f" span {lo:+.1f}..{hi:+.1f} st / {step:.1f} st per voice => " - f"~{int((hi-lo)//step)+1} reliably distinct voices on ONE axis") \ No newline at end of file + f"~{int((hi-lo)//step)+1} reliably distinct voices on ONE axis") diff --git a/backup/author_voice_lab/scripts/backup_author_matrix.py b/backup/author_voice_lab/scripts/backup_author_matrix.py index b513f56..d18f3bc 100644 --- a/backup/author_voice_lab/scripts/backup_author_matrix.py +++ b/backup/author_voice_lab/scripts/backup_author_matrix.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Durable backup of the Author voice matrix (vmatrix) + its reference chain. The live matrix lives in a git-ignored project cache and the previous version's @@ -236,4 +239,4 @@ To confirm a matrix still renders the right speaker, generate from if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/backup/author_voice_lab/scripts/fidelity.py b/backup/author_voice_lab/scripts/fidelity.py index 6e565d5..a27a4c2 100644 --- a/backup/author_voice_lab/scripts/fidelity.py +++ b/backup/author_voice_lab/scripts/fidelity.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Phase-insensitive fidelity: how faithfully does the matrix reproduce the reference? Frame-wise waveform correlation and LSD are dominated by phase, which a 12 Hz @@ -71,4 +74,4 @@ print(f"voiced frames: decoded {len(va)} reference {len(vb)}") import sys sys.path.insert(0, "/Volumes/1TB_APL_Storage/UmbraAudio") -print("\n(note: full re-encode check runs in matrix_roundtrip.py)") \ No newline at end of file +print("\n(note: full re-encode check runs in matrix_roundtrip.py)") diff --git a/backup/author_voice_lab/scripts/install_ref.py b/backup/author_voice_lab/scripts/install_ref.py index bacb449..d38fb99 100644 --- a/backup/author_voice_lab/scripts/install_ref.py +++ b/backup/author_voice_lab/scripts/install_ref.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Install the matrix-derived Author reference into the project. The matrix is the source of truth; this writes the WAV *decoded from that matrix* @@ -44,4 +47,4 @@ info = { } side = dest.with_suffix(".json") side.write_text(json.dumps(info, indent=2) + "\n") -print(json.dumps(info, indent=2)) \ No newline at end of file +print(json.dumps(info, indent=2)) diff --git a/backup/author_voice_lab/scripts/matrix_roundtrip.py b/backup/author_voice_lab/scripts/matrix_roundtrip.py index fb57c21..9baab35 100644 --- a/backup/author_voice_lab/scripts/matrix_roundtrip.py +++ b/backup/author_voice_lab/scripts/matrix_roundtrip.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Prove: the vmatrix alone can reproduce the reference WAV — and verify its provenance. 1. DECODE author.pt ref_code -> waveform (matrix -> audio; the user's requirement) @@ -126,4 +129,4 @@ def main() -> None: if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/backup/author_voice_lab/scripts/probe_dsp.py b/backup/author_voice_lab/scripts/probe_dsp.py index 7f99c59..c780b73 100644 --- a/backup/author_voice_lab/scripts/probe_dsp.py +++ b/backup/author_voice_lab/scripts/probe_dsp.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Probe 2: DSP axis limits. What does pitch_shift_pv actually move?""" from __future__ import annotations @@ -53,4 +56,4 @@ for st in (-12, -8, -4, 0, 4, 8, 12): print(f"{st:>6} {f0:>8.1f} {d_f0:>8.1f} {cen:>9.0f} {d_cen:>8.1f} {ftr:>8.0f} {d_ftr:>9.1f}") print("\nInterpretation: d_cen ~= d_f0 => full-spectrum shift => formants move WITH pitch.") -print("A true male->female conversion needs d_cen/d_F0 ~= +2.5 to +3 st, d_F0 ~= +9 to +12 st.") \ No newline at end of file +print("A true male->female conversion needs d_cen/d_F0 ~= +2.5 to +3 st, d_F0 ~= +9 to +12 st.") diff --git a/backup/author_voice_lab/scripts/probe_formant.py b/backup/author_voice_lab/scripts/probe_formant.py index d17305f..0aa0113 100644 --- a/backup/author_voice_lab/scripts/probe_formant.py +++ b/backup/author_voice_lab/scripts/probe_formant.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Probe 3: prove the missing primitive is an INDEPENDENT FORMANT SHIFTER. pitch_shift_pv is a phase vocoder -> it moves F0 and the spectral envelope by @@ -66,4 +69,4 @@ o = formant_shift(_pv(y, sr, semitones=-10.0), sr, -8.0) f0, ftr = m(o, sr) print(f" F0={f0:.1f}Hz ({12*np.log2(f0/b_f0):+.1f} st) LTAS4k={ftr:.0f}Hz " f"({12*np.log2(ftr/b_ftr):+.1f} st)") -sf.write(OUT / "dragon_recipe.wav", o, sr) \ No newline at end of file +sf.write(OUT / "dragon_recipe.wav", o, sr) diff --git a/backup/author_voice_lab/scripts/probe_morph.py b/backup/author_voice_lab/scripts/probe_morph.py index 716604e..0b1257c 100644 --- a/backup/author_voice_lab/scripts/probe_morph.py +++ b/backup/author_voice_lab/scripts/probe_morph.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Probe: can the narrator vmatrix be morphed (gender / creature) via instruct? Read-only against the project; writes WAVs + measurements to an off-volume temp dir. @@ -88,4 +91,4 @@ CASES = [ if __name__ == "__main__": results = [gen(label, instruct=instr) for label, instr in CASES] (OUT / "probe_results.json").write_text(json.dumps(results, indent=2)) - print("WROTE", OUT / "probe_results.json") \ No newline at end of file + print("WROTE", OUT / "probe_results.json") diff --git a/backup/author_voice_lab/scripts/verify_cliff.py b/backup/author_voice_lab/scripts/verify_cliff.py index 5b6cf25..eda1c87 100644 --- a/backup/author_voice_lab/scripts/verify_cliff.py +++ b/backup/author_voice_lab/scripts/verify_cliff.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Verify the downward-pitch intelligibility cliff on a LONGER text, 2 seeds. The 25-word probe suggested WER collapses below ~0 st. WER on 25 words is coarse @@ -83,4 +86,4 @@ for st in (0, -2, -4, -6, +2): print("\n--- mean WER by shift ---") for st in (0, -2, -4, -6, +2): ws = [r["wer"] for r in rows if r["shift_st"] == st] - print(f" {st:+3d} st: mean WER {sum(ws)/len(ws):.3f} {ws}") \ No newline at end of file + print(f" {st:+3d} st: mean WER {sum(ws)/len(ws):.3f} {ws}") diff --git a/backup/author_voice_lab/scripts/voice_lab.py b/backup/author_voice_lab/scripts/voice_lab.py index 8655c24..007fe24 100644 --- a/backup/author_voice_lab/scripts/voice_lab.py +++ b/backup/author_voice_lab/scripts/voice_lab.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """voice_lab — measure what the Author voice matrix can become. One fixed text for every sample (comparisons are only valid at constant text). @@ -217,4 +220,4 @@ REF_ENV = None REF_WORDS: list[str] = [] if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/backup/create_full_backup.sh b/backup/create_full_backup.sh index cfd209f..d46f3f5 100755 --- a/backup/create_full_backup.sh +++ b/backup/create_full_backup.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # Create a complete, restorable UmbraAudio snapshot on a mounted filesystem/NAS. set -Eeuo pipefail diff --git a/backup/restore_support.py b/backup/restore_support.py index 5858793..6f4dd63 100644 --- a/backup/restore_support.py +++ b/backup/restore_support.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Portable backup/restore support helpers for UmbraAudio. This module uses only the Python standard library. It snapshots global Umbra diff --git a/infra/agent_bridge/__init__.py b/infra/agent_bridge/__init__.py index 37a18e3..6a1e3c7 100644 --- a/infra/agent_bridge/__init__.py +++ b/infra/agent_bridge/__init__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Temporary browser-to-agent bridge for UmbraTrans.""" __all__: list[str] = [] diff --git a/infra/agent_bridge/__main__.py b/infra/agent_bridge/__main__.py index 0a68a64..7c1c7c8 100644 --- a/infra/agent_bridge/__main__.py +++ b/infra/agent_bridge/__main__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from .server import main raise SystemExit(main()) diff --git a/infra/agent_bridge/client.py b/infra/agent_bridge/client.py index c67d52e..31185cd 100644 --- a/infra/agent_bridge/client.py +++ b/infra/agent_bridge/client.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import argparse diff --git a/infra/agent_bridge/server.py b/infra/agent_bridge/server.py index 48f729d..09d9988 100644 --- a/infra/agent_bridge/server.py +++ b/infra/agent_bridge/server.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import argparse diff --git a/infra/agent_bridge/tests/test_bridge.py b/infra/agent_bridge/tests/test_bridge.py index cea0ea3..dfa32eb 100644 --- a/infra/agent_bridge/tests/test_bridge.py +++ b/infra/agent_bridge/tests/test_bridge.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/infra/bootstrap_enterprise_mint.sh b/infra/bootstrap_enterprise_mint.sh index 5840b21..9747f53 100755 --- a/infra/bootstrap_enterprise_mint.sh +++ b/infra/bootstrap_enterprise_mint.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # Phase-one enterprise control-plane bootstrap for Linux Mint 22.x. # This provisions PostgreSQL, database roles, core tenancy/identity tables, # and least-privilege service accounts. It does not install application code, diff --git a/infra/bootstrap_umbracontrol_database.sh b/infra/bootstrap_umbracontrol_database.sh index 81b9717..5475760 100755 --- a/infra/bootstrap_umbracontrol_database.sh +++ b/infra/bootstrap_umbracontrol_database.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # Database-only bootstrap for the UmbraTrans control plane. # This intentionally does not install packages, create application directories, # install application services, or modify Qwen/Docker/firewall settings. diff --git a/infra/remote_credential_broker/__init__.py b/infra/remote_credential_broker/__init__.py index 5b3b702..8ea87b3 100644 --- a/infra/remote_credential_broker/__init__.py +++ b/infra/remote_credential_broker/__init__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Local, stdio MCP broker for controlled remote operations. The broker keeps passwords in the macOS Keychain and exposes only operations, diff --git a/infra/remote_credential_broker/__main__.py b/infra/remote_credential_broker/__main__.py index 84cbe71..6b3009e 100644 --- a/infra/remote_credential_broker/__main__.py +++ b/infra/remote_credential_broker/__main__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from .broker import main raise SystemExit(main()) diff --git a/infra/remote_credential_broker/askpass_helper.py b/infra/remote_credential_broker/askpass_helper.py index 1883316..3f80714 100755 --- a/infra/remote_credential_broker/askpass_helper.py +++ b/infra/remote_credential_broker/askpass_helper.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import os diff --git a/infra/remote_credential_broker/broker.py b/infra/remote_credential_broker/broker.py index bfc07fa..bded697 100644 --- a/infra/remote_credential_broker/broker.py +++ b/infra/remote_credential_broker/broker.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import argparse diff --git a/infra/remote_credential_broker/config.py b/infra/remote_credential_broker/config.py index 3b273ba..ffa5b55 100644 --- a/infra/remote_credential_broker/config.py +++ b/infra/remote_credential_broker/config.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/infra/remote_credential_broker/executor.py b/infra/remote_credential_broker/executor.py index b2fd982..d8bef6a 100644 --- a/infra/remote_credential_broker/executor.py +++ b/infra/remote_credential_broker/executor.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import os diff --git a/infra/remote_credential_broker/keychain.py b/infra/remote_credential_broker/keychain.py index 924b5d3..b2819f8 100644 --- a/infra/remote_credential_broker/keychain.py +++ b/infra/remote_credential_broker/keychain.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import ctypes diff --git a/infra/remote_credential_broker/popup.py b/infra/remote_credential_broker/popup.py index d6e9157..cda7cbc 100644 --- a/infra/remote_credential_broker/popup.py +++ b/infra/remote_credential_broker/popup.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import subprocess diff --git a/infra/remote_credential_broker/tests/test_broker.py b/infra/remote_credential_broker/tests/test_broker.py index c8c921d..205358d 100644 --- a/infra/remote_credential_broker/tests/test_broker.py +++ b/infra/remote_credential_broker/tests/test_broker.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/scripts/alignment_report.py b/scripts/alignment_report.py index 7af7aef..9d2b2eb 100644 --- a/scripts/alignment_report.py +++ b/scripts/alignment_report.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Controller alignment reports (spec 21 §6.6) - read-only, never guesses. Emits the envelope the controller diffs mechanically: diff --git a/scripts/analyze_emotions.py b/scripts/analyze_emotions.py index a395dbb..617a085 100644 --- a/scripts/analyze_emotions.py +++ b/scripts/analyze_emotions.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Run LLM emotion/tone analysis on existing utterances without re-segmenting.""" from __future__ import annotations diff --git a/scripts/assign_voices.py b/scripts/assign_voices.py index c2db1ff..a637177 100644 --- a/scripts/assign_voices.py +++ b/scripts/assign_voices.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Assign unique Edge-TTS voices to all speakers.""" from __future__ import annotations diff --git a/scripts/backfill_source_unit_keys.py b/scripts/backfill_source_unit_keys.py index 5a4b275..537cda4 100644 --- a/scripts/backfill_source_unit_keys.py +++ b/scripts/backfill_source_unit_keys.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Backfill content-addressed ``source_unit_key`` values (spec 21 §9.1 M4-04). The key is derived from the chapter's source text and the utterance's own text, so diff --git a/scripts/backup_system.sh b/scripts/backup_system.sh index b6fe641..be23353 100755 --- a/scripts/backup_system.sh +++ b/scripts/backup_system.sh @@ -1,4 +1,7 @@ #!/bin/zsh +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # backup_system.sh - Complete UmbraAudio system backup set -e diff --git a/scripts/build_sample_translations.py b/scripts/build_sample_translations.py index 5438039..e269949 100644 --- a/scripts/build_sample_translations.py +++ b/scripts/build_sample_translations.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Generate the Deal Hunter sample chapter in every language Qwen3-TTS produces. IMPORTANT - what this is and is not diff --git a/scripts/cluster_worker.py b/scripts/cluster_worker.py index e25f5aa..b2dd37d 100644 --- a/scripts/cluster_worker.py +++ b/scripts/cluster_worker.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """UmbraAudio cluster worker entry point. Registers this node with UmbraTrans and polls for jobs. diff --git a/scripts/commit_check.sh b/scripts/commit_check.sh index c0dc224..ffee2ec 100755 --- a/scripts/commit_check.sh +++ b/scripts/commit_check.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # # commit_check.sh — warn when the working tree has been dirty too long. # diff --git a/scripts/commit_check_notify.py b/scripts/commit_check_notify.py index 3084ef5..08a5091 100644 --- a/scripts/commit_check_notify.py +++ b/scripts/commit_check_notify.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Weekly commit reminder for the UmbraAudio working tree. Invoked by ``~/.umbraaudio/umbra_commit_check.sh`` from the launchd job diff --git a/scripts/create_vocals_project.py b/scripts/create_vocals_project.py index e31f308..15d2ab7 100644 --- a/scripts/create_vocals_project.py +++ b/scripts/create_vocals_project.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Create the standalone "Vocals" example-vocals project (no upload needed). The project has a single chapter that speaks the Rainbow Passage once per diff --git a/scripts/download_models.sh b/scripts/download_models.sh index 3916a60..094dae4 100644 --- a/scripts/download_models.sh +++ b/scripts/download_models.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # Downloads the Qwen3-TTS model weights required by UmbraAudio. # # These models are stock HuggingFace downloads (~9 GB). They are NOT tracked diff --git a/scripts/extract_embeddings.py b/scripts/extract_embeddings.py index 02ac3a5..50e4950 100644 --- a/scripts/extract_embeddings.py +++ b/scripts/extract_embeddings.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Extract Qwen TTS speaker embeddings from existing voice reference WAVs. Usage: diff --git a/scripts/fix_chapter6.py b/scripts/fix_chapter6.py index f8cc3e1..39fed9e 100644 --- a/scripts/fix_chapter6.py +++ b/scripts/fix_chapter6.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Fix Chapter 6 (Salvage) utterance issues: 1. Split utterance 56 into 3 utterances with correct speakers 2. Fix utterance 145 - Kainda with pleading tone diff --git a/scripts/generate_all_audio.py b/scripts/generate_all_audio.py index e4500c0..974ab4b 100644 --- a/scripts/generate_all_audio.py +++ b/scripts/generate_all_audio.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Background chapter audio generation with Qwen3-TTS. Run as: nohup python scripts/generate_all_audio.py [--project NAME] > generation.log 2>&1 & """ diff --git a/scripts/generate_chapter_audio.py b/scripts/generate_chapter_audio.py index 71b09c9..19d6ea5 100644 --- a/scripts/generate_chapter_audio.py +++ b/scripts/generate_chapter_audio.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Generate audio for chapters using Qwen3-TTS with voice cloning from references.""" from __future__ import annotations diff --git a/scripts/generate_long_voice_refs.py b/scripts/generate_long_voice_refs.py index 1407b22..598a144 100644 --- a/scripts/generate_long_voice_refs.py +++ b/scripts/generate_long_voice_refs.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Generate longer voice references (30+ seconds) for speakers using VoiceDesign.""" from __future__ import annotations diff --git a/scripts/generate_narrator_refs.py b/scripts/generate_narrator_refs.py index 99f9bcc..43bec8a 100644 --- a/scripts/generate_narrator_refs.py +++ b/scripts/generate_narrator_refs.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Generate a narrator reference voice for each target language. Specification change (2026-10-13): diff --git a/scripts/generate_test_samples.py b/scripts/generate_test_samples.py index cf6eae6..488d5bb 100644 --- a/scripts/generate_test_samples.py +++ b/scripts/generate_test_samples.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Generate test samples for all speakers using Edge-TTS with speaker attributes.""" from __future__ import annotations diff --git a/scripts/generate_voice_references.py b/scripts/generate_voice_references.py index 9ac04ec..fd3841f 100644 --- a/scripts/generate_voice_references.py +++ b/scripts/generate_voice_references.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/scripts/generate_voice_samples.py b/scripts/generate_voice_samples.py index 3cbe062..b286708 100644 --- a/scripts/generate_voice_samples.py +++ b/scripts/generate_voice_samples.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Generate Rainbow Passage samples from cached speaker embeddings. For each speaker in the given chapter, generates a WAV file of the Rainbow Passage diff --git a/scripts/lmstudio_control.py b/scripts/lmstudio_control.py index 80f8125..65aa09e 100644 --- a/scripts/lmstudio_control.py +++ b/scripts/lmstudio_control.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """LM Studio model control script for UmbraAudio. Usage: diff --git a/scripts/merge_designations.py b/scripts/merge_designations.py index 4260c70..1645837 100644 --- a/scripts/merge_designations.py +++ b/scripts/merge_designations.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Merge mechanically-detected speaker designations into speakers.json. Discovery is LLM-driven and will always miss *some* characters — on Last Dwarf diff --git a/scripts/model_coordinator.py b/scripts/model_coordinator.py index 8fec00c..b5f0201 100644 --- a/scripts/model_coordinator.py +++ b/scripts/model_coordinator.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """CLI for the model coordinator. Ensures only the model needed by the current pipeline stage is resident in diff --git a/scripts/nas_lifecycle.py b/scripts/nas_lifecycle.py index b603d62..2807090 100644 --- a/scripts/nas_lifecycle.py +++ b/scripts/nas_lifecycle.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """NAS sync + local prune lifecycle for UmbraAudio. Primary store: local SSD. Secondary: NAS mirror. On each run: diff --git a/scripts/publish_release.py b/scripts/publish_release.py index aff989d..da33b1f 100644 --- a/scripts/publish_release.py +++ b/scripts/publish_release.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Publish a release: author a comment, approve it, then pin what shipped (spec 22). A release is a pinned set of artifacts plus an authored comment. The comment is a step, not diff --git a/scripts/qa_attribution.py b/scripts/qa_attribution.py index 606806e..ea2ec3e 100644 --- a/scripts/qa_attribution.py +++ b/scripts/qa_attribution.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Mechanical QA cross-check of speaker attribution against speech tags. Usage: diff --git a/scripts/qwen_tts_server.py b/scripts/qwen_tts_server.py index fd83439..b81c73f 100644 --- a/scripts/qwen_tts_server.py +++ b/scripts/qwen_tts_server.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Qwen3-TTS FastAPI Server for UmbraAudio. Provides REST endpoints for voice design and voice cloning. diff --git a/scripts/reattribute_all.py b/scripts/reattribute_all.py index a3610b7..bc972be 100644 --- a/scripts/reattribute_all.py +++ b/scripts/reattribute_all.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Re-run LLM speaker attribution on existing utterances without re-segmenting. Preserves utterance IDs and mechanical segmentation; only updates speaker_name. diff --git a/scripts/reindex_chapter6.py b/scripts/reindex_chapter6.py index d492080..bf7617c 100644 --- a/scripts/reindex_chapter6.py +++ b/scripts/reindex_chapter6.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Re-index utterance_index values and fix remaining issues for Chapter 6.""" from __future__ import annotations diff --git a/scripts/remigrate_speakers.py b/scripts/remigrate_speakers.py index e90288a..8c6785e 100644 --- a/scripts/remigrate_speakers.py +++ b/scripts/remigrate_speakers.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Deterministic re-merge of existing discovery chapter data with fixed logic. Regenerates .umbra/speakers.json from .umbra/discovery/discovery_pass1.json diff --git a/scripts/render_lang_test.py b/scripts/render_lang_test.py index b39637a..43a9e33 100644 --- a/scripts/render_lang_test.py +++ b/scripts/render_lang_test.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Render the sample chapter in every language Qwen3-TTS supports. Reads the translation JSONs produced by ``build_sample_translations.py`` and diff --git a/scripts/report_speech_evidence.py b/scripts/report_speech_evidence.py index 905a3a5..b4b1e84 100644 --- a/scripts/report_speech_evidence.py +++ b/scripts/report_speech_evidence.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Report mechanical speech-evidence support over a project's dialogue lines. Read-only. Prints the verdict mix, then every contradicted line with the narration the diff --git a/scripts/resegment_all.py b/scripts/resegment_all.py index 0e06ea6..6421c61 100644 --- a/scripts/resegment_all.py +++ b/scripts/resegment_all.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Re-segment all chapters using mechanical splitter + LLM attribution.""" from __future__ import annotations diff --git a/scripts/resegment_merge.py b/scripts/resegment_merge.py index bcc234d..a3e6e92 100644 --- a/scripts/resegment_merge.py +++ b/scripts/resegment_merge.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Non-destructive chapter re-segmentation. Re-runs the *current* Segmenter over selected chapters and merges the result diff --git a/scripts/run_discovery.py b/scripts/run_discovery.py index 912259e..ef189ae 100644 --- a/scripts/run_discovery.py +++ b/scripts/run_discovery.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Run character discovery to a SEPARATE output file (never overwrites speakers.json). Discovery is slow (4 LLM passes/chapter). This runner lets you validate the diff --git a/scripts/run_llm_attribution.py b/scripts/run_llm_attribution.py index 9bd7da2..8d257ce 100644 --- a/scripts/run_llm_attribution.py +++ b/scripts/run_llm_attribution.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/scripts/run_voice_analysis.py b/scripts/run_voice_analysis.py index 72b669c..702ad53 100644 --- a/scripts/run_voice_analysis.py +++ b/scripts/run_voice_analysis.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/scripts/scan_name_tokens.py b/scripts/scan_name_tokens.py index 8ac7b2a..2cfac74 100644 --- a/scripts/scan_name_tokens.py +++ b/scripts/scan_name_tokens.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Scan the manuscript for orphan name tokens (unresolved speaker identities). Walks every chapter's utterances, collects proper-noun tokens used as speaker diff --git a/scripts/scan_speaker_duplicates.py b/scripts/scan_speaker_duplicates.py index 72cd4f8..0058180 100644 --- a/scripts/scan_speaker_duplicates.py +++ b/scripts/scan_speaker_duplicates.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Scan for duplicate speakers and report them ranked by how safe the merge is. Read-only by default. Nothing is merged without ``--apply`` and an explicit group choice. diff --git a/scripts/speaker_review_audit.py b/scripts/speaker_review_audit.py index 6a5962b..2f32112 100644 --- a/scripts/speaker_review_audit.py +++ b/scripts/speaker_review_audit.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Speaker-review audit: is the attribution data fit to hand to the next stage? Answers the two questions asked after a speaker review completes: diff --git a/scripts/start.sh b/scripts/start.sh index e3cb2aa..7f34b56 100755 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -1,4 +1,7 @@ #!/bin/bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # UmbraAudio Startup Script set -e diff --git a/scripts/start_web_server.sh b/scripts/start_web_server.sh index 485f9b4..f89892c 100755 --- a/scripts/start_web_server.sh +++ b/scripts/start_web_server.sh @@ -1,6 +1,9 @@ #!/bin/zsh +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + PROJ=/Volumes/1TB_APL_Storage/UmbraAudio exec >> "$PROJ/logs/web_server.log" 2>&1 echo "[$(date '+%F %T')] web server starting (wrapper pid $$)" cd "$PROJ" -exec "$PROJ/.venv/bin/python" -c "from pathlib import Path; from umbraaudio.web import create_app; from umbraaudio.config import load_config; import uvicorn; c = load_config(Path('/Volumes/1TB_APL_Storage/UmbraAudio')); uvicorn.run(create_app(c), host='0.0.0.0', port=8420, log_level='info')" \ No newline at end of file +exec "$PROJ/.venv/bin/python" -c "from pathlib import Path; from umbraaudio.web import create_app; from umbraaudio.config import load_config; import uvicorn; c = load_config(Path('/Volumes/1TB_APL_Storage/UmbraAudio')); uvicorn.run(create_app(c), host='0.0.0.0', port=8420, log_level='info')" diff --git a/scripts/test_parser.py b/scripts/test_parser.py index c5e69dd..c1934d5 100644 --- a/scripts/test_parser.py +++ b/scripts/test_parser.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """ Test script for document parser and entity extraction. Tests the parsing of DealHunterShip manuscript. diff --git a/scripts/test_speaker_scottish.py b/scripts/test_speaker_scottish.py index ccba868..ff9e9da 100644 --- a/scripts/test_speaker_scottish.py +++ b/scripts/test_speaker_scottish.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Test a Scottish voice for a given speaker once project discovery completes. Waits for ``analysis_status.json`` to reach ``complete`` (or ``error``), then: @@ -246,4 +249,4 @@ if __name__ == "__main__": main() except Exception as e: log(f"HALLR SCOTTISH TEST FAILED: {e}") - raise \ No newline at end of file + raise diff --git a/scripts/test_tts.py b/scripts/test_tts.py index ad2fe82..df09759 100644 --- a/scripts/test_tts.py +++ b/scripts/test_tts.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """ Test script for Qwen3-TTS voice synthesis. Tests the TTS server with character voice prompts. diff --git a/scripts/umbra_node_report.py b/scripts/umbra_node_report.py index f8cd54d..11ad289 100644 --- a/scripts/umbra_node_report.py +++ b/scripts/umbra_node_report.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Read-only Umbra node report: the facts another machine needs to align with. Every Umbra machine is a *node* in the Umbra system (spec 21). Before any data diff --git a/scripts/verify_backup.sh b/scripts/verify_backup.sh index 26aae08..914ca9f 100755 --- a/scripts/verify_backup.sh +++ b/scripts/verify_backup.sh @@ -1,4 +1,7 @@ #!/bin/zsh +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # verify_backup.sh - Verify UmbraAudio backup integrity set -e diff --git a/scripts/verify_nas.py b/scripts/verify_nas.py index a0d5834..ee06e75 100644 --- a/scripts/verify_nas.py +++ b/scripts/verify_nas.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """verify_nas.py — NAS mirror consistency verifier (Phase D2). Idempotent, safe to run anytime. After a sync to the NAS mirror it asserts, for diff --git a/scripts/verify_projects.py b/scripts/verify_projects.py index dc3b666..0704ce7 100644 --- a/scripts/verify_projects.py +++ b/scripts/verify_projects.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """verify_projects.py — multi-project integrity verifier (Phase D1). Idempotent, safe to run anytime. For every project under PROJECT_BASE it: diff --git a/start_server.sh b/start_server.sh index 9599604..f37b56d 100755 --- a/start_server.sh +++ b/start_server.sh @@ -1,4 +1,7 @@ #!/bin/bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # Qwen3-TTS 1.7B-Base Gradio server launcher (all paths on the 1TB drive) export HF_HOME=/Volumes/1TB_APL_Storage/UmbraAudio/.hf_home export PATH=/Volumes/1TB_APL_Storage/UmbraAudio/.venv/bin:$PATH diff --git a/test_voice_clone.py b/test_voice_clone.py index 8f05356..9ece3a3 100644 --- a/test_voice_clone.py +++ b/test_voice_clone.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + import os import torch import soundfile as sf diff --git a/tests/conftest.py b/tests/conftest.py index 9cdefa6..0fcc028 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import tempfile diff --git a/tests/test_ar_export.py b/tests/test_ar_export.py index fdd8f6f..3021234 100644 --- a/tests/test_ar_export.py +++ b/tests/test_ar_export.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/tests/test_assembly.py b/tests/test_assembly.py index 94c720d..b4fe268 100644 --- a/tests/test_assembly.py +++ b/tests/test_assembly.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from pathlib import Path diff --git a/tests/test_attribution_qa.py b/tests/test_attribution_qa.py index 3a04e6b..189e00b 100644 --- a/tests/test_attribution_qa.py +++ b/tests/test_attribution_qa.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from umbraaudio.analysis.attribution_qa import ( diff --git a/tests/test_auth.py b/tests/test_auth.py index bf45a99..57e3aac 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for the single-user auth gate. The review UI previously had no authentication at all, reachable by anything diff --git a/tests/test_character_discovery.py b/tests/test_character_discovery.py index 39c8bdb..347e7ec 100644 --- a/tests/test_character_discovery.py +++ b/tests/test_character_discovery.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from umbraaudio.analysis.character_discovery import ( diff --git a/tests/test_clarity.py b/tests/test_clarity.py index 46083c0..db3520a 100644 --- a/tests/test_clarity.py +++ b/tests/test_clarity.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from umbraaudio.analysis.clarity import ( @@ -296,4 +299,4 @@ class TestAssessUtteranceClarity: ] out = assess_utterance_clarity(utts, 6, ALIAS_MAP, PROFILES) assert "needs_review" not in out[2] - assert out[2]["type"] == "scene_break" \ No newline at end of file + assert out[2]["type"] == "scene_break" diff --git a/tests/test_delete_speaker.py b/tests/test_delete_speaker.py index 16c8e2a..c8a7556 100644 --- a/tests/test_delete_speaker.py +++ b/tests/test_delete_speaker.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for speaker deletion. The speakers page has offered a Delete button for a long time. The endpoint diff --git a/tests/test_designation_scan.py b/tests/test_designation_scan.py index ea2ec12..c9eadf8 100644 --- a/tests/test_designation_scan.py +++ b/tests/test_designation_scan.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from umbraaudio.analysis.designation_scan import ( @@ -110,4 +113,4 @@ class TestBookScan: ] out = scan_book_designations(chapters) assert len(out) == 1 - assert out["the guard"].chapter_id == 1 \ No newline at end of file + assert out["the guard"].chapter_id == 1 diff --git a/tests/test_discovery_prompt_rules.py b/tests/test_discovery_prompt_rules.py index 5252bba..f3c2650 100644 --- a/tests/test_discovery_prompt_rules.py +++ b/tests/test_discovery_prompt_rules.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Guard tests for the character-discovery prompt's over-detection rules. These rules exist because discovery was missing obvious speakers (characters diff --git a/tests/test_export_m4b_spec.py b/tests/test_export_m4b_spec.py index 156989d..539995a 100644 --- a/tests/test_export_m4b_spec.py +++ b/tests/test_export_m4b_spec.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """The m4b must ship the same audio spec as the AR MP3 package. Previously the m4b path had no sample-rate flag, no channel layout, and no @@ -119,4 +122,4 @@ def test_concat_resamples_to_the_delivery_rate(tmp_path: Path) -> None: out = tmp_path / "concat.wav" exporter._concat_wavs_with_silence(files, out, gap_ms=100) info = sf.info(str(out)) - assert info.samplerate == TARGET_SAMPLE_RATE \ No newline at end of file + assert info.samplerate == TARGET_SAMPLE_RATE diff --git a/tests/test_generation/test_audio_effects.py b/tests/test_generation/test_audio_effects.py index f96e576..34a8653 100644 --- a/tests/test_generation/test_audio_effects.py +++ b/tests/test_generation/test_audio_effects.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for umbraaudio.generation.audio_effects.""" from __future__ import annotations diff --git a/tests/test_generation/test_language_wiring.py b/tests/test_generation/test_language_wiring.py index 65d14ed..4a2a453 100644 --- a/tests/test_generation/test_language_wiring.py +++ b/tests/test_generation/test_language_wiring.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """The per-utterance language tag must reach the TTS engine and the marker. Spec 31's source axis: an utterance tagged with the language it is *written in* diff --git a/tests/test_generation/test_staleness.py b/tests/test_generation/test_staleness.py index abf67de..37ce82f 100644 --- a/tests/test_generation/test_staleness.py +++ b/tests/test_generation/test_staleness.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/tests/test_languages.py b/tests/test_languages.py index 16858ff..72cb01b 100644 --- a/tests/test_languages.py +++ b/tests/test_languages.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for the language registry (spec 31 section 5). The registry is the single source of truth for what this system can speak, so diff --git a/tests/test_library.py b/tests/test_library.py index 8f982ac..09e0793 100644 --- a/tests/test_library.py +++ b/tests/test_library.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from pathlib import Path diff --git a/tests/test_llm_attributor.py b/tests/test_llm_attributor.py index da871b2..c8097a8 100644 --- a/tests/test_llm_attributor.py +++ b/tests/test_llm_attributor.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from umbraaudio.analysis.llm_attributor import LLMAttributor diff --git a/tests/test_multi_project.py b/tests/test_multi_project.py index fde0493..cebf4b7 100644 --- a/tests/test_multi_project.py +++ b/tests/test_multi_project.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for multi-project readiness (Phase C2 of MULTI_PROJECT_PLAN.md). Covers: diff --git a/tests/test_multipass_attribution.py b/tests/test_multipass_attribution.py index 4381b19..68c7042 100644 --- a/tests/test_multipass_attribution.py +++ b/tests/test_multipass_attribution.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for the multi-pass speaker-attribution pipeline. Covers the mechanical narration-evidence builder, speaker normalization for diff --git a/tests/test_name_tokens.py b/tests/test_name_tokens.py index 0c4ee93..7e0a2e3 100644 --- a/tests/test_name_tokens.py +++ b/tests/test_name_tokens.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import sqlite3 diff --git a/tests/test_orphan_resolution.py b/tests/test_orphan_resolution.py index 1186b57..fe5aad4 100644 --- a/tests/test_orphan_resolution.py +++ b/tests/test_orphan_resolution.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/tests/test_pronunciation.py b/tests/test_pronunciation.py index 59f488c..ee37f27 100644 --- a/tests/test_pronunciation.py +++ b/tests/test_pronunciation.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/tests/test_qa_acceptance.py b/tests/test_qa_acceptance.py index d669449..108abf7 100644 --- a/tests/test_qa_acceptance.py +++ b/tests/test_qa_acceptance.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Per-utterance QA box: issue detection, recheck/fix loop, and accept state. These cover the helpers behind ``/api/utterance/{id}/recheck`` and diff --git a/tests/test_release.py b/tests/test_release.py index f5e6974..7400473 100644 --- a/tests/test_release.py +++ b/tests/test_release.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for the release/publish mechanism (spec 22). The mechanism exists because Deal Hunter shipped audio that differed from what was diff --git a/tests/test_release_comments.py b/tests/test_release_comments.py index 7658ccc..8a969d0 100644 --- a/tests/test_release_comments.py +++ b/tests/test_release_comments.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for release comments - the explicit step in a release (spec 22). The comment is a gate, and its designator has to make two releases on the same day diff --git a/tests/test_resegment_merge.py b/tests/test_resegment_merge.py index 3a84f90..a64c913 100644 --- a/tests/test_resegment_merge.py +++ b/tests/test_resegment_merge.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Regression tests for resegment_merge.py.""" from __future__ import annotations diff --git a/tests/test_scene_break.py b/tests/test_scene_break.py index a7639c3..943d1a8 100644 --- a/tests/test_scene_break.py +++ b/tests/test_scene_break.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import numpy as np diff --git a/tests/test_segmenter.py b/tests/test_segmenter.py index 809445d..12670f9 100644 --- a/tests/test_segmenter.py +++ b/tests/test_segmenter.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from umbraaudio.mapping.segmenter import Segmenter diff --git a/tests/test_segmenter_fixes.py b/tests/test_segmenter_fixes.py index 58787eb..69c0a5c 100644 --- a/tests/test_segmenter_fixes.py +++ b/tests/test_segmenter_fixes.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Quick verification of segmenter fixes.""" from __future__ import annotations diff --git a/tests/test_source_unit_keys.py b/tests/test_source_unit_keys.py index d2cb64b..9b87763 100644 --- a/tests/test_source_unit_keys.py +++ b/tests/test_source_unit_keys.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for content-addressed source-unit identity (``source_unit_key``). The contract under test is the one the controller depends on (spec 21 §9.1 M4-04): diff --git a/tests/test_speaker_confidence.py b/tests/test_speaker_confidence.py index b65a7c8..73e33ef 100644 --- a/tests/test_speaker_confidence.py +++ b/tests/test_speaker_confidence.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from umbraaudio.analysis.speaker_confidence import ( diff --git a/tests/test_speaker_confidence_approval.py b/tests/test_speaker_confidence_approval.py index e0a741c..71b25ca 100644 --- a/tests/test_speaker_confidence_approval.py +++ b/tests/test_speaker_confidence_approval.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for the reviewer-facing behaviour of speaker identification confidence. The specific regression: a reviewer pressed Approve on a speaker, the badge diff --git a/tests/test_speaker_dedup.py b/tests/test_speaker_dedup.py index 4ea8103..78384a9 100644 --- a/tests/test_speaker_dedup.py +++ b/tests/test_speaker_dedup.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for duplicate-speaker detection and approval-safe merging. The rules that matter here are the ones that REFUSE to merge. A missed duplicate is a small @@ -331,4 +334,3 @@ def test_degenerate_names_do_not_crash(name: str) -> None: assert normalize_name(name) == "" assert is_designation(name) is False assert similarity(facts, _f("Hallr"))[0] == 0.0 - diff --git a/tests/test_speaker_edit_submit.py b/tests/test_speaker_edit_submit.py index 0e6e977..aa6b2fa 100644 --- a/tests/test_speaker_edit_submit.py +++ b/tests/test_speaker_edit_submit.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Guards on the speaker edit form's submit behaviour. Regression: the voice-queue work emptied ``queueVoiceRegenOnSave`` but left diff --git a/tests/test_speaker_review_audit.py b/tests/test_speaker_review_audit.py index 77c36ab..d85647f 100644 --- a/tests/test_speaker_review_audit.py +++ b/tests/test_speaker_review_audit.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for the speaker-review audit. The audit is the gate between "the reviewer finished" and "the data goes to diff --git a/tests/test_speech_evidence.py b/tests/test_speech_evidence.py index 5b58ab9..a2b99f8 100644 --- a/tests/test_speech_evidence.py +++ b/tests/test_speech_evidence.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for the mechanical speech-evidence gate. The fixtures are the real defect shapes found in the Last Dwarf chapter 6 and chapter 9 diff --git a/tests/test_storage_lifecycle.py b/tests/test_storage_lifecycle.py index dc5635b..9ed5e72 100644 --- a/tests/test_storage_lifecycle.py +++ b/tests/test_storage_lifecycle.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for local-first storage with NAS fallback (umbraaudio.storage) and the prune planner in scripts/nas_lifecycle.""" diff --git a/tests/test_translation_resolution.py b/tests/test_translation_resolution.py index 8ec8e62..d5956e6 100644 --- a/tests/test_translation_resolution.py +++ b/tests/test_translation_resolution.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for resolving a translation from the DB and the on-disk sample files. The behaviours pinned here are the ones that made the review UI lie: a valid diff --git a/tests/test_translations.py b/tests/test_translations.py index c909be1..972b861 100644 --- a/tests/test_translations.py +++ b/tests/test_translations.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for source-language tagging and per-language translations (spec 31). The behaviours pinned here are the ones that would silently corrupt audio or diff --git a/tests/test_tts_language.py b/tests/test_tts_language.py index d3fb5f3..3fa619d 100644 --- a/tests/test_tts_language.py +++ b/tests/test_tts_language.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Per-utterance language in the TTS call (spec 31 section 4.3 / section 9). Two guarantees are pinned here: diff --git a/tests/test_variations.py b/tests/test_variations.py index 43f68a3..9257147 100644 --- a/tests/test_variations.py +++ b/tests/test_variations.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import io diff --git a/tests/test_vocals_project.py b/tests/test_vocals_project.py index 6edadf0..4dad5fb 100644 --- a/tests/test_vocals_project.py +++ b/tests/test_vocals_project.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import sys diff --git a/tests/test_voice_analysis.py b/tests/test_voice_analysis.py index 78b1a16..a1d609e 100644 --- a/tests/test_voice_analysis.py +++ b/tests/test_voice_analysis.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/tests/test_voice_maintenance.py b/tests/test_voice_maintenance.py index 43e3c31..f0eceb8 100644 --- a/tests/test_voice_maintenance.py +++ b/tests/test_voice_maintenance.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for the web-UI voice-maintenance banner marker. The marker is a small JSON file whose ``pid`` field gates the banner: a diff --git a/tests/test_voice_queue.py b/tests/test_voice_queue.py index a15674f..20cc019 100644 --- a/tests/test_voice_queue.py +++ b/tests/test_voice_queue.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Tests for the voice-regeneration queue. The queue exists because regenerating a voice used to be one-at-a-time: the diff --git a/tests/test_voice_queue_lookup.py b/tests/test_voice_queue_lookup.py index cda2b0e..6c4a803 100644 --- a/tests/test_voice_queue_lookup.py +++ b/tests/test_voice_queue_lookup.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Regression tests for voice-queue speaker lookup. Every queued item in a real project's voice_queue.json had failed with diff --git a/tests/test_voices/test_edge_tts.py b/tests/test_voices/test_edge_tts.py index 166fb23..2e919e6 100644 --- a/tests/test_voices/test_edge_tts.py +++ b/tests/test_voices/test_edge_tts.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import pytest diff --git a/tests/test_voices/test_model_coordinator.py b/tests/test_voices/test_model_coordinator.py index becfdfb..38e160a 100644 --- a/tests/test_voices/test_model_coordinator.py +++ b/tests/test_voices/test_model_coordinator.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import pytest diff --git a/tests/test_voices/test_registry.py b/tests/test_voices/test_registry.py index f47070c..09226a1 100644 --- a/tests/test_voices/test_registry.py +++ b/tests/test_voices/test_registry.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from pathlib import Path diff --git a/tests/test_voices/test_voice_profile_manager.py b/tests/test_voices/test_voice_profile_manager.py index d99df1f..e8117b4 100644 --- a/tests/test_voices/test_voice_profile_manager.py +++ b/tests/test_voices/test_voice_profile_manager.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from pathlib import Path diff --git a/tests/test_web_proper_names.py b/tests/test_web_proper_names.py index 2021d64..2d69a9a 100644 --- a/tests/test_web_proper_names.py +++ b/tests/test_web_proper_names.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from umbraaudio.web.routes import ( diff --git a/tts_server/install_server.sh b/tts_server/install_server.sh index 7c41594..8b3b382 100755 --- a/tts_server/install_server.sh +++ b/tts_server/install_server.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # Install the UmbraAudio Qwen3-TTS server on a Linux/CUDA GPU machine. # # Usage: diff --git a/tts_server/qwen_tts_server.py b/tts_server/qwen_tts_server.py index 560199a..2de618e 100644 --- a/tts_server/qwen_tts_server.py +++ b/tts_server/qwen_tts_server.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Qwen3-TTS FastAPI Server for UmbraAudio. Provides REST endpoints for voice design and voice cloning. diff --git a/tts_server/run_server.sh b/tts_server/run_server.sh index ceeb19a..13d00a6 100755 --- a/tts_server/run_server.sh +++ b/tts_server/run_server.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # Launch the UmbraAudio Qwen3-TTS server (CUDA/GPU). # # Config via env vars (override as needed): diff --git a/tts_server/sync_voice_data.sh b/tts_server/sync_voice_data.sh index 40ff88a..b16d100 100755 --- a/tts_server/sync_voice_data.sh +++ b/tts_server/sync_voice_data.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # Package the voice reference wavs + cached ICL voice prompts (.pt) so they can # be copied to the target TTS server machine (GPU). The remote ChapterBuilder / # server uses these to generate every utterance with each speaker's identical diff --git a/umbra_package/setup_env.sh b/umbra_package/setup_env.sh index 81e5a35..436ef89 100755 --- a/umbra_package/setup_env.sh +++ b/umbra_package/setup_env.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + # UmbraAudio Environment Setup Script # This script sets up the Python environment, installs dependencies, # and configures paths for the UmbraAudio audiobook generation system. diff --git a/umbraaudio/__init__.py b/umbraaudio/__init__.py index 34242c7..7ac7962 100644 --- a/umbraaudio/__init__.py +++ b/umbraaudio/__init__.py @@ -1 +1,4 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """UmbraAudio — Quality-first multi-pass audiobook generation from manuscripts.""" diff --git a/umbraaudio/analysis/__init__.py b/umbraaudio/analysis/__init__.py index b8b940b..f8633f3 100644 --- a/umbraaudio/analysis/__init__.py +++ b/umbraaudio/analysis/__init__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from dataclasses import dataclass, field diff --git a/umbraaudio/analysis/ambiguity.py b/umbraaudio/analysis/ambiguity.py index 56591a2..8e45f33 100644 --- a/umbraaudio/analysis/ambiguity.py +++ b/umbraaudio/analysis/ambiguity.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/analysis/attribution_qa.py b/umbraaudio/analysis/attribution_qa.py index 361828c..fe5586f 100644 --- a/umbraaudio/analysis/attribution_qa.py +++ b/umbraaudio/analysis/attribution_qa.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Mechanical cross-check of speaker attribution against speech tags. Runs after LLM attribution as a cheap, deterministic verification pass. It does diff --git a/umbraaudio/analysis/booknlp_engine.py b/umbraaudio/analysis/booknlp_engine.py index 7812be3..e3768fa 100644 --- a/umbraaudio/analysis/booknlp_engine.py +++ b/umbraaudio/analysis/booknlp_engine.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/analysis/character_discovery.py b/umbraaudio/analysis/character_discovery.py index 8186de7..654eea8 100644 --- a/umbraaudio/analysis/character_discovery.py +++ b/umbraaudio/analysis/character_discovery.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/analysis/character_profiler.py b/umbraaudio/analysis/character_profiler.py index 8bd383b..a1a6384 100644 --- a/umbraaudio/analysis/character_profiler.py +++ b/umbraaudio/analysis/character_profiler.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/analysis/clarity.py b/umbraaudio/analysis/clarity.py index 0dc3ad4..6eba9e8 100644 --- a/umbraaudio/analysis/clarity.py +++ b/umbraaudio/analysis/clarity.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Deterministic utterance-clarity classification for speaker attributions. Runs after LLM attribution as a cheap, repeatable post-pass. It annotates every diff --git a/umbraaudio/analysis/context_analyzer.py b/umbraaudio/analysis/context_analyzer.py index acd811e..ebcd10b 100644 --- a/umbraaudio/analysis/context_analyzer.py +++ b/umbraaudio/analysis/context_analyzer.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging @@ -511,4 +514,4 @@ class ContextAnalyzer: def analyze_manuscript_context(chapters: list[dict[str, Any]]) -> dict[str, Any]: """Main entry point for multi-pass context analysis.""" analyzer = ContextAnalyzer() - return analyzer.analyze_manuscript(chapters) \ No newline at end of file + return analyzer.analyze_manuscript(chapters) diff --git a/umbraaudio/analysis/designation_scan.py b/umbraaudio/analysis/designation_scan.py index 5bc25c7..7a765d4 100644 --- a/umbraaudio/analysis/designation_scan.py +++ b/umbraaudio/analysis/designation_scan.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Deterministic backstop: every designation that speaks becomes a speaker. Character discovery is LLM-driven, so it will always miss *some* characters — on diff --git a/umbraaudio/analysis/llm_attributor.py b/umbraaudio/analysis/llm_attributor.py index 4c47206..34eef19 100644 --- a/umbraaudio/analysis/llm_attributor.py +++ b/umbraaudio/analysis/llm_attributor.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/analysis/llm_segmenter.py b/umbraaudio/analysis/llm_segmenter.py index 547bd27..0f2c9e2 100644 --- a/umbraaudio/analysis/llm_segmenter.py +++ b/umbraaudio/analysis/llm_segmenter.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/analysis/name_tokens.py b/umbraaudio/analysis/name_tokens.py index 85f23dc..f154e2f 100644 --- a/umbraaudio/analysis/name_tokens.py +++ b/umbraaudio/analysis/name_tokens.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Orphan name-token scanner. Finds proper-noun name tokens used as *speaker evidence* in the manuscript that diff --git a/umbraaudio/analysis/orphan_resolution.py b/umbraaudio/analysis/orphan_resolution.py index d8bcf3a..b7110ab 100644 --- a/umbraaudio/analysis/orphan_resolution.py +++ b/umbraaudio/analysis/orphan_resolution.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Resolution actions for orphan name tokens (assign / create / dismiss / merge). These are the durable, side-effecting operations behind the review UI and the diff --git a/umbraaudio/analysis/pronunciation.py b/umbraaudio/analysis/pronunciation.py index 6c7835a..e6207f1 100644 --- a/umbraaudio/analysis/pronunciation.py +++ b/umbraaudio/analysis/pronunciation.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import re diff --git a/umbraaudio/analysis/speaker_confidence.py b/umbraaudio/analysis/speaker_confidence.py index 87aa5ef..de48635 100644 --- a/umbraaudio/analysis/speaker_confidence.py +++ b/umbraaudio/analysis/speaker_confidence.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Speaker identification confidence (spec 17 §3.1, axis A). Answers "how sure are we that this speaker exists, and that we have them diff --git a/umbraaudio/analysis/speaker_dedup.py b/umbraaudio/analysis/speaker_dedup.py index bc57a3e..dc18aa9 100644 --- a/umbraaudio/analysis/speaker_dedup.py +++ b/umbraaudio/analysis/speaker_dedup.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Duplicate-speaker detection that will not eat an approved voice. The problem diff --git a/umbraaudio/analysis/speech_evidence.py b/umbraaudio/analysis/speech_evidence.py index cfaf146..b3206b3 100644 --- a/umbraaudio/analysis/speech_evidence.py +++ b/umbraaudio/analysis/speech_evidence.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Mechanical, model-free evidence for who is speaking a dialogue line. Every defect found in the Last Dwarf review of chapter 6 and chapter 9 had the same diff --git a/umbraaudio/analysis/tone_analyzer.py b/umbraaudio/analysis/tone_analyzer.py index 75f8e88..fefa29d 100644 --- a/umbraaudio/analysis/tone_analyzer.py +++ b/umbraaudio/analysis/tone_analyzer.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging @@ -368,4 +371,4 @@ class ToneAnalyzer: def analyze_scene_emotions(chapter: dict[str, Any], scene_contexts: list[Any] | None = None) -> dict[int, SceneEmotionalProfile]: """Main entry point for scene emotion analysis.""" analyzer = ToneAnalyzer() - return analyzer.analyze_chapter_emotions(chapter, scene_contexts) \ No newline at end of file + return analyzer.analyze_chapter_emotions(chapter, scene_contexts) diff --git a/umbraaudio/analysis/voice_analysis.py b/umbraaudio/analysis/voice_analysis.py index e19e19e..1a44d09 100644 --- a/umbraaudio/analysis/voice_analysis.py +++ b/umbraaudio/analysis/voice_analysis.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/assembly/__init__.py b/umbraaudio/assembly/__init__.py index d79b294..54b29ff 100644 --- a/umbraaudio/assembly/__init__.py +++ b/umbraaudio/assembly/__init__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/assembly/ar_export.py b/umbraaudio/assembly/ar_export.py index 367a015..95a28aa 100644 --- a/umbraaudio/assembly/ar_export.py +++ b/umbraaudio/assembly/ar_export.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/assembly/export.py b/umbraaudio/assembly/export.py index 9cc04da..a5be6a2 100644 --- a/umbraaudio/assembly/export.py +++ b/umbraaudio/assembly/export.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/assembly/metadata.py b/umbraaudio/assembly/metadata.py index 3db962d..4401d6d 100644 --- a/umbraaudio/assembly/metadata.py +++ b/umbraaudio/assembly/metadata.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/assembly/normalize.py b/umbraaudio/assembly/normalize.py index cd445d3..c2659fd 100644 --- a/umbraaudio/assembly/normalize.py +++ b/umbraaudio/assembly/normalize.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/audiobook_meta.py b/umbraaudio/audiobook_meta.py index 988fc70..336fae3 100644 --- a/umbraaudio/audiobook_meta.py +++ b/umbraaudio/audiobook_meta.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Audiobook (m4b) metadata capture & validation. Stores the publishing metadata that gets embedded into an .m4b file (title, diff --git a/umbraaudio/auth.py b/umbraaudio/auth.py index a74acc8..3e1ac11 100644 --- a/umbraaudio/auth.py +++ b/umbraaudio/auth.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Single-user authentication for the review UI. Why this exists diff --git a/umbraaudio/cli.py b/umbraaudio/cli.py index 21583b3..8779ec8 100644 --- a/umbraaudio/cli.py +++ b/umbraaudio/cli.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import asyncio diff --git a/umbraaudio/cluster/__init__.py b/umbraaudio/cluster/__init__.py index 663eede..f2e40b6 100644 --- a/umbraaudio/cluster/__init__.py +++ b/umbraaudio/cluster/__init__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """UmbraTrans cluster integration for UmbraAudio. Provides PostgreSQL connection, compute node registration, job queue, diff --git a/umbraaudio/cluster/artifacts.py b/umbraaudio/cluster/artifacts.py index 7178b10..496d20f 100644 --- a/umbraaudio/cluster/artifacts.py +++ b/umbraaudio/cluster/artifacts.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Artifact protocol (content-addressed storage) for UmbraAudio ↔ UmbraTrans.""" from __future__ import annotations diff --git a/umbraaudio/cluster/config.py b/umbraaudio/cluster/config.py index 996ccf2..eae71ab 100644 --- a/umbraaudio/cluster/config.py +++ b/umbraaudio/cluster/config.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Cluster configuration for UmbraAudio ↔ UmbraTrans integration.""" from __future__ import annotations diff --git a/umbraaudio/cluster/database.py b/umbraaudio/cluster/database.py index c1daad5..b21dcaa 100644 --- a/umbraaudio/cluster/database.py +++ b/umbraaudio/cluster/database.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """PostgreSQL database operations for UmbraTrans cluster integration.""" from __future__ import annotations diff --git a/umbraaudio/cluster/jobs.py b/umbraaudio/cluster/jobs.py index 55d801e..cc6c64d 100644 --- a/umbraaudio/cluster/jobs.py +++ b/umbraaudio/cluster/jobs.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Job queue operations for UmbraAudio worker.""" from __future__ import annotations diff --git a/umbraaudio/cluster/nfs.py b/umbraaudio/cluster/nfs.py index b5ec4bb..4aa0630 100644 --- a/umbraaudio/cluster/nfs.py +++ b/umbraaudio/cluster/nfs.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """NFS mount management for UmbraAudio cluster integration.""" from __future__ import annotations diff --git a/umbraaudio/cluster/node.py b/umbraaudio/cluster/node.py index fdb0eca..d91b8ae 100644 --- a/umbraaudio/cluster/node.py +++ b/umbraaudio/cluster/node.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Compute node registration and heartbeat for UmbraAudio worker.""" from __future__ import annotations diff --git a/umbraaudio/config.py b/umbraaudio/config.py index 2cf93f3..8186b6c 100644 --- a/umbraaudio/config.py +++ b/umbraaudio/config.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import re diff --git a/umbraaudio/database.py b/umbraaudio/database.py index 41e044f..c640cfb 100644 --- a/umbraaudio/database.py +++ b/umbraaudio/database.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/definitions.py b/umbraaudio/definitions.py index 9e6f9c3..0082bab 100644 --- a/umbraaudio/definitions.py +++ b/umbraaudio/definitions.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Published vocabulary sets for the Umbra system (controller §5.4). The controller's rule, from ``manifest.md`` §14.2, is that anything a stored row depends on diff --git a/umbraaudio/generation/__init__.py b/umbraaudio/generation/__init__.py index c06dfa0..b4d6d14 100644 --- a/umbraaudio/generation/__init__.py +++ b/umbraaudio/generation/__init__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/generation/audio_effects.py b/umbraaudio/generation/audio_effects.py index b6a4a98..7d8f9a9 100644 --- a/umbraaudio/generation/audio_effects.py +++ b/umbraaudio/generation/audio_effects.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Post-processing audio effects keyed off speaker vocal_traits. Applies signal-processing effects (bitcrushing, gating, filtering, noise diff --git a/umbraaudio/generation/cache.py b/umbraaudio/generation/cache.py index c98e8b0..0d4f111 100644 --- a/umbraaudio/generation/cache.py +++ b/umbraaudio/generation/cache.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import hashlib diff --git a/umbraaudio/generation/chapter.py b/umbraaudio/generation/chapter.py index 4913ab5..5865264 100644 --- a/umbraaudio/generation/chapter.py +++ b/umbraaudio/generation/chapter.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import hashlib diff --git a/umbraaudio/generation/chapter_builder.py b/umbraaudio/generation/chapter_builder.py index bb6b43b..d973be6 100644 --- a/umbraaudio/generation/chapter_builder.py +++ b/umbraaudio/generation/chapter_builder.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Self-healing chapter audio builder pipeline. When triggered, runs a 6-phase pipeline: diff --git a/umbraaudio/generation/retry.py b/umbraaudio/generation/retry.py index 46522aa..bffbfcc 100644 --- a/umbraaudio/generation/retry.py +++ b/umbraaudio/generation/retry.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/generation/scene_break.py b/umbraaudio/generation/scene_break.py index 9427c4d..efb2690 100644 --- a/umbraaudio/generation/scene_break.py +++ b/umbraaudio/generation/scene_break.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Scene-break (``<<<>>>``) audio handling. A scene break is not spoken text; it marks a change of location, time, or diff --git a/umbraaudio/generation/staleness.py b/umbraaudio/generation/staleness.py index c215dc2..747cf77 100644 --- a/umbraaudio/generation/staleness.py +++ b/umbraaudio/generation/staleness.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Utterance-audio staleness guard. Per-utterance audio is keyed by index (utt_XXXX.wav). Indexes stay stable diff --git a/umbraaudio/languages.py b/umbraaudio/languages.py index 26342b3..5a2a94c 100644 --- a/umbraaudio/languages.py +++ b/umbraaudio/languages.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """The set of languages this system knows about, in one place. Two groups, and the split is a hard capability boundary, not a preference: diff --git a/umbraaudio/library.py b/umbraaudio/library.py index 2b14248..7047fc7 100644 --- a/umbraaudio/library.py +++ b/umbraaudio/library.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Cross-project voice/name library. The Library stores speakers (with their voice reference audio), confirmed diff --git a/umbraaudio/mapping/__init__.py b/umbraaudio/mapping/__init__.py index e0ca8d6..ea62ea6 100644 --- a/umbraaudio/mapping/__init__.py +++ b/umbraaudio/mapping/__init__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import re diff --git a/umbraaudio/mapping/context.py b/umbraaudio/mapping/context.py index 08ca00f..e44876b 100644 --- a/umbraaudio/mapping/context.py +++ b/umbraaudio/mapping/context.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations diff --git a/umbraaudio/mapping/emotion.py b/umbraaudio/mapping/emotion.py index daeb834..108f103 100644 --- a/umbraaudio/mapping/emotion.py +++ b/umbraaudio/mapping/emotion.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/mapping/manifest.py b/umbraaudio/mapping/manifest.py index f5b8075..2fd3c17 100644 --- a/umbraaudio/mapping/manifest.py +++ b/umbraaudio/mapping/manifest.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/mapping/segmenter.py b/umbraaudio/mapping/segmenter.py index 03acb59..15d8a83 100644 --- a/umbraaudio/mapping/segmenter.py +++ b/umbraaudio/mapping/segmenter.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import re diff --git a/umbraaudio/orchestrator.py b/umbraaudio/orchestrator.py index 144c653..b671b13 100644 --- a/umbraaudio/orchestrator.py +++ b/umbraaudio/orchestrator.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import gc diff --git a/umbraaudio/parsers/__init__.py b/umbraaudio/parsers/__init__.py index 3bbc098..809b6c5 100644 --- a/umbraaudio/parsers/__init__.py +++ b/umbraaudio/parsers/__init__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import re diff --git a/umbraaudio/parsers/epub.py b/umbraaudio/parsers/epub.py index 9d48db4..232d864 100644 --- a/umbraaudio/parsers/epub.py +++ b/umbraaudio/parsers/epub.py @@ -1 +1,4 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations diff --git a/umbraaudio/parsers/md.py b/umbraaudio/parsers/md.py index 9d48db4..232d864 100644 --- a/umbraaudio/parsers/md.py +++ b/umbraaudio/parsers/md.py @@ -1 +1,4 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations diff --git a/umbraaudio/parsers/pdf.py b/umbraaudio/parsers/pdf.py index 9d48db4..232d864 100644 --- a/umbraaudio/parsers/pdf.py +++ b/umbraaudio/parsers/pdf.py @@ -1 +1,4 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations diff --git a/umbraaudio/parsers/txt.py b/umbraaudio/parsers/txt.py index 9d48db4..232d864 100644 --- a/umbraaudio/parsers/txt.py +++ b/umbraaudio/parsers/txt.py @@ -1 +1,4 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations diff --git a/umbraaudio/pipeline_manager.py b/umbraaudio/pipeline_manager.py index f08372a..496dec9 100644 --- a/umbraaudio/pipeline_manager.py +++ b/umbraaudio/pipeline_manager.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import asyncio diff --git a/umbraaudio/project_bootstrap.py b/umbraaudio/project_bootstrap.py index ef453f4..92abd7d 100644 --- a/umbraaudio/project_bootstrap.py +++ b/umbraaudio/project_bootstrap.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Reusable library entry point for creating a new, isolated project. Extracted from the ``umbraaudio init`` CLI path so the web UI can bootstrap a diff --git a/umbraaudio/pronunciation.py b/umbraaudio/pronunciation.py index 8e1bab0..c67fb52 100644 --- a/umbraaudio/pronunciation.py +++ b/umbraaudio/pronunciation.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/quality/__init__.py b/umbraaudio/quality/__init__.py index bbc92a9..1a2bad5 100644 --- a/umbraaudio/quality/__init__.py +++ b/umbraaudio/quality/__init__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/quality/consistency.py b/umbraaudio/quality/consistency.py index eae48a9..b86a900 100644 --- a/umbraaudio/quality/consistency.py +++ b/umbraaudio/quality/consistency.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/quality/report.py b/umbraaudio/quality/report.py index 2e3df36..c5397dd 100644 --- a/umbraaudio/quality/report.py +++ b/umbraaudio/quality/report.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/release.py b/umbraaudio/release.py index 9fc5cc9..81bd037 100644 --- a/umbraaudio/release.py +++ b/umbraaudio/release.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Releases: a pinned, immutable record of what was actually published. Why this module exists diff --git a/umbraaudio/release_comments.py b/umbraaudio/release_comments.py index bf6da19..c3d1176 100644 --- a/umbraaudio/release_comments.py +++ b/umbraaudio/release_comments.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Release comments: the explicit step between "ready" and "published". A release comment is the human-authored note that accompanies a publish, in the spirit of a diff --git a/umbraaudio/source_units.py b/umbraaudio/source_units.py index 4a7424a..785d47f 100644 --- a/umbraaudio/source_units.py +++ b/umbraaudio/source_units.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Content-addressed source-unit identity (``source_unit_key``). Why this exists diff --git a/umbraaudio/storage.py b/umbraaudio/storage.py index 758654e..786d9b2 100644 --- a/umbraaudio/storage.py +++ b/umbraaudio/storage.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Local-first storage with transparent NAS fallback. Primary store is the local SSD; the NAS mirror is secondary. When a file diff --git a/umbraaudio/translations.py b/umbraaudio/translations.py index c43342a..6b6ad69 100644 --- a/umbraaudio/translations.py +++ b/umbraaudio/translations.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Ingest and query the source-language tag and per-language translations. Spec 31. Two axes, deliberately separate: diff --git a/umbraaudio/voice_maintenance.py b/umbraaudio/voice_maintenance.py index b96834b..a732931 100644 --- a/umbraaudio/voice_maintenance.py +++ b/umbraaudio/voice_maintenance.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Web-UI maintenance banner state for long-running offline phases. During the LLM speaker re-attribution run the Mac's Qwen3-TTS models must diff --git a/umbraaudio/voices/__init__.py b/umbraaudio/voices/__init__.py index 080746b..ee4d09f 100644 --- a/umbraaudio/voices/__init__.py +++ b/umbraaudio/voices/__init__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations from abc import ABC, abstractmethod diff --git a/umbraaudio/voices/chatterbox.py b/umbraaudio/voices/chatterbox.py index b1c389c..567a2ea 100644 --- a/umbraaudio/voices/chatterbox.py +++ b/umbraaudio/voices/chatterbox.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import hashlib diff --git a/umbraaudio/voices/edge_tts.py b/umbraaudio/voices/edge_tts.py index 23676eb..ee269a2 100644 --- a/umbraaudio/voices/edge_tts.py +++ b/umbraaudio/voices/edge_tts.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import asyncio diff --git a/umbraaudio/voices/embeddings.py b/umbraaudio/voices/embeddings.py index f45c3fd..1bdacbe 100644 --- a/umbraaudio/voices/embeddings.py +++ b/umbraaudio/voices/embeddings.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/voices/generation_manager.py b/umbraaudio/voices/generation_manager.py index 64a569b..7ad80f5 100644 --- a/umbraaudio/voices/generation_manager.py +++ b/umbraaudio/voices/generation_manager.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/voices/lmstudio_gate.py b/umbraaudio/voices/lmstudio_gate.py index 8f8ca9c..a82e601 100644 --- a/umbraaudio/voices/lmstudio_gate.py +++ b/umbraaudio/voices/lmstudio_gate.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Queueing gate for LM Studio LLM requests. LM Studio on this Mac can only serve one LLM at a time and the model @@ -183,4 +186,4 @@ def queued_chat_completion( if _is_local_lmstudio(base_url): with _GATE.acquire(base_url, model): return client.chat.completions.create(model=model, messages=messages, **kwargs) - return client.chat.completions.create(model=model, messages=messages, **kwargs) \ No newline at end of file + return client.chat.completions.create(model=model, messages=messages, **kwargs) diff --git a/umbraaudio/voices/lmstudio_lifecycle.py b/umbraaudio/voices/lmstudio_lifecycle.py index 1c8490c..d66861b 100644 --- a/umbraaudio/voices/lmstudio_lifecycle.py +++ b/umbraaudio/voices/lmstudio_lifecycle.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/voices/model_coordinator.py b/umbraaudio/voices/model_coordinator.py index 0bf226b..422dad4 100644 --- a/umbraaudio/voices/model_coordinator.py +++ b/umbraaudio/voices/model_coordinator.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Model coordinator: ensures only the models required for the current pipeline stage are resident in memory. diff --git a/umbraaudio/voices/model_manager.py b/umbraaudio/voices/model_manager.py index 9c2ff8e..d5a4934 100644 --- a/umbraaudio/voices/model_manager.py +++ b/umbraaudio/voices/model_manager.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/voices/qwen_embeddings.py b/umbraaudio/voices/qwen_embeddings.py index 631ecc1..525eafb 100644 --- a/umbraaudio/voices/qwen_embeddings.py +++ b/umbraaudio/voices/qwen_embeddings.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/voices/qwen_tts.py b/umbraaudio/voices/qwen_tts.py index 5199c5b..376ab65 100644 --- a/umbraaudio/voices/qwen_tts.py +++ b/umbraaudio/voices/qwen_tts.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/voices/registry.py b/umbraaudio/voices/registry.py index dea06f4..ab4e8d3 100644 --- a/umbraaudio/voices/registry.py +++ b/umbraaudio/voices/registry.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/voices/unified_model_manager.py b/umbraaudio/voices/unified_model_manager.py index 0b72647..a4cc98b 100644 --- a/umbraaudio/voices/unified_model_manager.py +++ b/umbraaudio/voices/unified_model_manager.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/voices/voice_designer.py b/umbraaudio/voices/voice_designer.py index 543c81d..f3c2ccc 100644 --- a/umbraaudio/voices/voice_designer.py +++ b/umbraaudio/voices/voice_designer.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import hashlib diff --git a/umbraaudio/voices/voice_profile_manager.py b/umbraaudio/voices/voice_profile_manager.py index c820935..fd9648f 100644 --- a/umbraaudio/voices/voice_profile_manager.py +++ b/umbraaudio/voices/voice_profile_manager.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import json diff --git a/umbraaudio/voices/voice_queue.py b/umbraaudio/voices/voice_queue.py index 1ceafe2..9ee2b40 100644 --- a/umbraaudio/voices/voice_queue.py +++ b/umbraaudio/voices/voice_queue.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Serial task queue for voice regeneration, with per-item state. Why diff --git a/umbraaudio/web/__init__.py b/umbraaudio/web/__init__.py index 8a6e20e..26b88b1 100644 --- a/umbraaudio/web/__init__.py +++ b/umbraaudio/web/__init__.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import logging diff --git a/umbraaudio/web/auth_routes.py b/umbraaudio/web/auth_routes.py index b57eb3a..38a528b 100644 --- a/umbraaudio/web/auth_routes.py +++ b/umbraaudio/web/auth_routes.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Login page, logout, and password-change endpoints. Kept in its own module for the same reason as ``name_token_routes``: the main diff --git a/umbraaudio/web/name_token_routes.py b/umbraaudio/web/name_token_routes.py index 6f58bc7..66bf4f1 100644 --- a/umbraaudio/web/name_token_routes.py +++ b/umbraaudio/web/name_token_routes.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Web routes for the orphan name-token review queue (spec 17 Phase 3). Deliberately a SEPARATE router module so the name-token UI never has to be diff --git a/umbraaudio/web/routes.py b/umbraaudio/web/routes.py index 932e406..a72af48 100644 --- a/umbraaudio/web/routes.py +++ b/umbraaudio/web/routes.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + from __future__ import annotations import contextlib diff --git a/umbraaudio/web/voice_queue_routes.py b/umbraaudio/web/voice_queue_routes.py index 918d134..d2a363c 100644 --- a/umbraaudio/web/voice_queue_routes.py +++ b/umbraaudio/web/voice_queue_routes.py @@ -1,3 +1,6 @@ +# Copyright 2026 Umbra Tools (umbratools.com) +# SPDX-License-Identifier: Apache-2.0 + """Voice-regeneration queue endpoints. Separate from ``routes.py`` for the same reason as ``name_token_routes``: the