From b38da7d53fcbd3c56061361f91c824981ce90753 Mon Sep 17 00:00:00 2001
From: 44r0n7 <44r0n7+gitea@pm.me>
Date: Sat, 18 Jul 2026 18:20:34 -0400
Subject: [PATCH] chore: establish phase 0 baseline
---
.github/workflows/ci.yml | 22 +
.gitignore | 6 +
AGENTS.md | 64 ++
CHANGELOG.md | 18 +
Cargo.lock | 15 +
Cargo.toml | 18 +
LICENSE | 661 ++++++++++++++++++
Makefile | 20 +
README.md | 28 +
SECURITY.md | 25 +
crates/kiln-cli/Cargo.toml | 17 +
crates/kiln-cli/src/main.rs | 36 +
crates/kiln-core/Cargo.toml | 11 +
crates/kiln-core/src/lib.rs | 107 +++
deny.toml | 29 +
docs/adr/0001-private-kiln-workspace.md | 19 +
docs/handoff/phase-1-codex-cli.md | 42 ++
docs/phase-0/checklist.md | 23 +
docs/phase-0/evidence-2026-07-18-work-mode.md | 66 ++
docs/phase-0/fixture-policy.md | 26 +
docs/phase-0/release-version-policy.md | 30 +
docs/phase-0/rename-manifest.md | 15 +
docs/phase-0/source-inventory.toml | 21 +
docs/phase-0/status.md | 43 ++
docs/phase-0/supported-platforms.md | 10 +
docs/phase-0/test-evidence-template.md | 16 +
docs/phase-0/threat-model.md | 17 +
docs/phase-0/traceability.csv | 31 +
docs/spec/00_SPEC_INDEX.md | 36 +
docs/spec/01_PROJECT_FOUNDATION.md | 138 ++++
docs/spec/02_ARCHITECTURE_AND_BACKEND.md | 176 +++++
docs/spec/03_PROVIDERS_SESSIONS_AND_INPUT.md | 121 ++++
docs/spec/04_BASE_PERFORMANCE_RELIABILITY.md | 86 +++
.../spec/05_FRONTENDS_AND_SESSION_POLICIES.md | 67 ++
.../06_DEVELOPMENT_ROADMAP_AND_ACCEPTANCE.md | 107 +++
docs/spec/07_RISKS_DECISIONS_AND_HISTORY.md | 172 +++++
rust-toolchain.toml | 5 +
rustfmt.toml | 4 +
scripts/audit_workspace.py | 65 ++
scripts/scan_placeholders.py | 47 ++
scripts/verify_repo.py | 116 +++
scripts/verify_rust_toolchain.py | 42 ++
42 files changed, 2618 insertions(+)
create mode 100644 .github/workflows/ci.yml
create mode 100644 .gitignore
create mode 100644 AGENTS.md
create mode 100644 CHANGELOG.md
create mode 100644 Cargo.lock
create mode 100644 Cargo.toml
create mode 100644 LICENSE
create mode 100644 Makefile
create mode 100644 README.md
create mode 100644 SECURITY.md
create mode 100644 crates/kiln-cli/Cargo.toml
create mode 100644 crates/kiln-cli/src/main.rs
create mode 100644 crates/kiln-core/Cargo.toml
create mode 100644 crates/kiln-core/src/lib.rs
create mode 100644 deny.toml
create mode 100644 docs/adr/0001-private-kiln-workspace.md
create mode 100644 docs/handoff/phase-1-codex-cli.md
create mode 100644 docs/phase-0/checklist.md
create mode 100644 docs/phase-0/evidence-2026-07-18-work-mode.md
create mode 100644 docs/phase-0/fixture-policy.md
create mode 100644 docs/phase-0/release-version-policy.md
create mode 100644 docs/phase-0/rename-manifest.md
create mode 100644 docs/phase-0/source-inventory.toml
create mode 100644 docs/phase-0/status.md
create mode 100644 docs/phase-0/supported-platforms.md
create mode 100644 docs/phase-0/test-evidence-template.md
create mode 100644 docs/phase-0/threat-model.md
create mode 100644 docs/phase-0/traceability.csv
create mode 100644 docs/spec/00_SPEC_INDEX.md
create mode 100644 docs/spec/01_PROJECT_FOUNDATION.md
create mode 100644 docs/spec/02_ARCHITECTURE_AND_BACKEND.md
create mode 100644 docs/spec/03_PROVIDERS_SESSIONS_AND_INPUT.md
create mode 100644 docs/spec/04_BASE_PERFORMANCE_RELIABILITY.md
create mode 100644 docs/spec/05_FRONTENDS_AND_SESSION_POLICIES.md
create mode 100644 docs/spec/06_DEVELOPMENT_ROADMAP_AND_ACCEPTANCE.md
create mode 100644 docs/spec/07_RISKS_DECISIONS_AND_HISTORY.md
create mode 100644 rust-toolchain.toml
create mode 100644 rustfmt.toml
create mode 100755 scripts/audit_workspace.py
create mode 100755 scripts/scan_placeholders.py
create mode 100755 scripts/verify_repo.py
create mode 100755 scripts/verify_rust_toolchain.py
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..bf08130
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,22 @@
+name: baseline
+
+on:
+ push:
+ pull_request:
+
+permissions:
+ contents: read
+
+jobs:
+ verify:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+ - name: Install pinned Rust toolchain
+ run: rustup toolchain install 1.97.1 --profile minimal --component clippy,rustfmt
+ - name: Verify repository
+ run: make verify
+ - name: Install pinned dependency auditor
+ run: cargo install --locked cargo-deny --version 0.20.2
+ - name: Audit advisories, dependencies, licenses, and sources
+ run: make audit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c9334e6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+/target/
+__pycache__/
+*.py[cod]
+*.log
+.idea/
+.vscode/
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..8f8d826
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,64 @@
+# Codex instructions
+
+## Authority and scope
+
+- Start with `docs/spec/00_SPEC_INDEX.md`. The numbered files under `docs/spec/` are the
+ complete active specification; `99_FULL_SPEC_ARCHIVE.md` is historical and is not in
+ this repository.
+- Required and Confirmed items are binding. Proposed, Deferred, Open, Optional, and
+ Post-v1 items must not silently become implementation requirements.
+- Before changing scope, architecture, compatibility, release timing, schemas, commands,
+ or user-visible behavior, read `docs/spec/01_PROJECT_FOUNDATION.md` and
+ `docs/spec/07_RISKS_DECISIONS_AND_HISTORY.md` and apply the cross-spec integrity rules.
+- Ask the project owner when multiple plausible resolutions materially differ. Do not
+ invent a decision merely to keep moving.
+
+## Current state
+
+- Phase 0 is complete. Phase 1 contracts are next.
+- `Project Kiln`, `kiln`, and every `kiln-*` name are private placeholders. Do not publish,
+ globally install, register, or expose them as stable compatibility promises.
+- The workspace is private, AGPL-3.0-or-later, Rust 2024, MSRV 1.85, with the reviewed
+ development toolchain pinned to Rust 1.97.1.
+- No real provider implementation starts until the relevant Phase 1 contracts and mock
+ adapter tests pass.
+
+## Required workflow
+
+1. Define one narrow task with exclusions, affected components, acceptance criteria, and
+ exact verification commands.
+2. Implement one vertical capability at a time. Do not spread incomplete work across
+ providers or system layers.
+3. Treat provider files, manifests, artwork, frontend descriptors, paths, and strings as
+ hostile input. Never interpolate them into a shell command.
+4. Keep ordinary discovery and launch unprivileged. Preserve per-user XDG state and do
+ not hard-code usernames, UIDs, home directories, mounts, or the reference hardware.
+5. Use exact versions for local path dependencies as well as their paths. Update and
+ commit `Cargo.lock` for every dependency change.
+6. Add dependency licenses only after review; do not broaden `deny.toml` speculatively.
+7. Update ADRs, evidence, traceability, source inventory, changelog, and active spec files
+ whenever a change materially affects them.
+
+## Verification
+
+Run before handing work back:
+
+```sh
+make verify
+make audit
+```
+
+Also run focused tests for the changed capability. Do not report a gate as passed unless
+it actually ran. Record blocked hardware/VM/provider checks explicitly for later local
+execution rather than fabricating evidence.
+
+## Repository map
+
+- `crates/kiln-core/`: provider-independent contracts and logic
+- `crates/kiln-cli/`: the single human and machine-facing CLI
+- `docs/spec/`: active specification
+- `docs/adr/`: architecture decisions
+- `docs/phase-0/`: completed baseline policies and evidence
+- `docs/handoff/`: bounded Codex CLI task briefs
+- `scripts/`: repository, toolchain, licensing, and placeholder gates
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..41f0fb6
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Changelog
+
+This project follows Semantic Versioning after its first public release. Before 1.0,
+contract-breaking changes are allowed only when they are explicit in this file and the
+relevant schema version is advanced.
+
+## Unreleased
+
+### Added
+
+- Private Project Kiln Phase 0 workspace and evidence baseline.
+- Dependency-free core identity contract and `kiln doctor` smoke CLI.
+
+### Corrected
+
+- Separated the Rust 1.85 MSRV from the exact Rust 1.97.1 development toolchain pin.
+- Enforced the active compiler pin instead of assuming distro Cargo honors Rustup files.
+
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..f8d6e27
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,15 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "kiln-cli"
+version = "0.0.1"
+dependencies = [
+ "kiln-core",
+]
+
+[[package]]
+name = "kiln-core"
+version = "0.0.1"
+
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..dc22f71
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,18 @@
+[workspace]
+members = ["crates/kiln-core", "crates/kiln-cli"]
+resolver = "2"
+
+[workspace.package]
+version = "0.0.1"
+edition = "2024"
+rust-version = "1.85"
+license = "AGPL-3.0-or-later"
+publish = false
+
+[workspace.lints.rust]
+unsafe_code = "forbid"
+missing_docs = "warn"
+
+[workspace.lints.clippy]
+all = { level = "deny", priority = -1 }
+pedantic = { level = "warn", priority = -1 }
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..be3f7b2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,661 @@
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU Affero General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3494c54
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,20 @@
+.PHONY: verify static rust audit ci
+
+verify: static rust
+
+static:
+ python3 scripts/verify_repo.py
+ python3 scripts/audit_workspace.py
+ python3 scripts/scan_placeholders.py
+
+rust:
+ python3 scripts/verify_rust_toolchain.py
+ cargo fmt --all --check
+ cargo check --workspace --all-targets --locked
+ cargo test --workspace --all-targets --locked
+ cargo clippy --workspace --all-targets --locked -- -D warnings
+
+audit:
+ cargo deny check advisories bans licenses sources
+
+ci: verify audit
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e602d3c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,28 @@
+# Project Kiln
+
+Private Phase 0 scaffold for the CLI-first Arch gaming OS. `Kiln` and every
+`kiln-*` identifier are temporary repository-local names, not public compatibility
+promises.
+
+## Current proof
+
+The workspace contains a dependency-free Rust core and CLI smoke path. Rust 1.85 is
+the minimum supported compiler because it introduced Edition 2024; development and CI
+remain pinned to the reviewed Rust 1.97.1 toolchain:
+
+```text
+kiln version
+kiln doctor
+kiln doctor --json
+```
+
+Run deterministic repository and Rust gates with `make verify`. Run only the
+environment-independent repository checks with `make static`. Run the separately
+versioned, network-backed dependency advisory/license/source audit with `make audit`.
+Rust 1.97.1 is pinned.
+
+The active specification is under `docs/spec/`. Start with
+`docs/spec/00_SPEC_INDEX.md`; the archived monolith is intentionally excluded.
+
+Local Codex CLI work starts with `AGENTS.md`. The initial bounded Phase 1 brief is
+`docs/handoff/phase-1-codex-cli.md`.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..8bf2c44
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,25 @@
+# Security policy
+
+## Reporting
+
+Do not open a public issue for an unpatched vulnerability, leaked credential, unsafe
+provider parser, privilege-boundary failure, or command-execution flaw. Until a private
+security contact is configured for the eventual repository host, retain the report
+locally and contact the project owner through an already established private channel.
+
+No public security-response address is published during private development. A tested
+private reporting route and disclosure policy are mandatory before public release.
+
+## Supported versions
+
+There are no public supported releases. The private main branch receives security fixes.
+
+## Handling rules
+
+- Never attach live provider tokens, personal library dumps, save files, or proprietary
+ launcher state to an issue or fixture.
+- Provide the smallest sanitized reproducer that demonstrates the boundary failure.
+- Record affected revision, platform, exact command, expected/observed behavior, and
+ whether exploitation requires local access, provider-controlled data, or privilege.
+- Rotate any disclosed secret immediately; redaction after publication is not recovery.
+
diff --git a/crates/kiln-cli/Cargo.toml b/crates/kiln-cli/Cargo.toml
new file mode 100644
index 0000000..db65858
--- /dev/null
+++ b/crates/kiln-cli/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "kiln-cli"
+version.workspace = true
+edition.workspace = true
+rust-version.workspace = true
+license.workspace = true
+publish.workspace = true
+
+[[bin]]
+name = "kiln"
+path = "src/main.rs"
+
+[dependencies]
+kiln-core = { version = "=0.0.1", path = "../kiln-core" }
+
+[lints]
+workspace = true
diff --git a/crates/kiln-cli/src/main.rs b/crates/kiln-cli/src/main.rs
new file mode 100644
index 0000000..bb1e054
--- /dev/null
+++ b/crates/kiln-cli/src/main.rs
@@ -0,0 +1,36 @@
+//! Private smoke CLI for the Project Kiln workspace.
+
+use std::env;
+use std::process::ExitCode;
+
+use kiln_core::CONTRACT_SCHEMA_VERSION;
+
+const HELP: &str = "Project Kiln private scaffold\n\nUSAGE:\n kiln \n\nCOMMANDS:\n version Print the private build version\n doctor [--json] Check the scaffold contract\n help Print this help\n";
+
+fn main() -> ExitCode {
+ let mut arguments = env::args().skip(1);
+ match (arguments.next().as_deref(), arguments.next().as_deref()) {
+ (None | Some("help" | "--help" | "-h"), None) => {
+ print!("{HELP}");
+ ExitCode::SUCCESS
+ }
+ (Some("version" | "--version" | "-V"), None) => {
+ println!("kiln {} (private placeholder)", env!("CARGO_PKG_VERSION"));
+ ExitCode::SUCCESS
+ }
+ (Some("doctor"), None) => {
+ println!("ok: core contract schema {CONTRACT_SCHEMA_VERSION}");
+ ExitCode::SUCCESS
+ }
+ (Some("doctor"), Some("--json")) => {
+ println!(
+ "{{\"schema_version\":{CONTRACT_SCHEMA_VERSION},\"status\":\"ok\",\"private_placeholder\":true}}"
+ );
+ ExitCode::SUCCESS
+ }
+ _ => {
+ eprintln!("error: unsupported arguments\n\n{HELP}");
+ ExitCode::from(2)
+ }
+ }
+}
diff --git a/crates/kiln-core/Cargo.toml b/crates/kiln-core/Cargo.toml
new file mode 100644
index 0000000..16a8d77
--- /dev/null
+++ b/crates/kiln-core/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "kiln-core"
+version.workspace = true
+edition.workspace = true
+rust-version.workspace = true
+license.workspace = true
+publish.workspace = true
+
+[lints]
+workspace = true
+
diff --git a/crates/kiln-core/src/lib.rs b/crates/kiln-core/src/lib.rs
new file mode 100644
index 0000000..e306152
--- /dev/null
+++ b/crates/kiln-core/src/lib.rs
@@ -0,0 +1,107 @@
+//! Shared, provider-independent contracts for Project Kiln.
+
+use std::fmt;
+use std::str::FromStr;
+
+/// Schema version emitted by the initial private machine-readable smoke path.
+pub const CONTRACT_SCHEMA_VERSION: u32 = 1;
+
+/// A store-qualified game identity such as `steam:620` or `native:supertuxkart`.
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct GameId {
+ namespace: String,
+ value: String,
+}
+
+impl GameId {
+ /// Returns the provider/store namespace.
+ #[must_use]
+ pub fn namespace(&self) -> &str {
+ &self.namespace
+ }
+
+ /// Returns the provider-owned identity value.
+ #[must_use]
+ pub fn value(&self) -> &str {
+ &self.value
+ }
+}
+
+impl fmt::Display for GameId {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(formatter, "{}:{}", self.namespace, self.value)
+ }
+}
+
+/// Why a game identity could not be parsed.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum GameIdError {
+ /// The `namespace:value` separator is absent.
+ MissingSeparator,
+ /// The namespace is empty or contains unsupported characters.
+ InvalidNamespace,
+ /// The provider-owned value is empty or contains control characters.
+ InvalidValue,
+}
+
+impl fmt::Display for GameIdError {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let message = match self {
+ Self::MissingSeparator => "game ID must contain a ':' separator",
+ Self::InvalidNamespace => "game ID namespace must be lowercase ASCII",
+ Self::InvalidValue => {
+ "game ID value must be non-empty and contain no control characters"
+ }
+ };
+ formatter.write_str(message)
+ }
+}
+
+impl std::error::Error for GameIdError {}
+
+impl FromStr for GameId {
+ type Err = GameIdError;
+
+ fn from_str(raw: &str) -> Result {
+ let (namespace, value) = raw.split_once(':').ok_or(GameIdError::MissingSeparator)?;
+ if namespace.is_empty()
+ || !namespace
+ .bytes()
+ .all(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit() || byte == b'-')
+ {
+ return Err(GameIdError::InvalidNamespace);
+ }
+ if value.is_empty() || value.chars().any(char::is_control) {
+ return Err(GameIdError::InvalidValue);
+ }
+ Ok(Self {
+ namespace: namespace.to_owned(),
+ value: value.to_owned(),
+ })
+ }
+}
+#[cfg(test)]
+mod tests {
+ use super::{GameId, GameIdError};
+
+ #[test]
+ fn accepts_store_qualified_identity() {
+ let id: GameId = "steam:620".parse().expect("valid ID");
+ assert_eq!(id.namespace(), "steam");
+ assert_eq!(id.value(), "620");
+ assert_eq!(id.to_string(), "steam:620");
+ }
+
+ #[test]
+ fn rejects_unqualified_identity() {
+ assert_eq!("620".parse::(), Err(GameIdError::MissingSeparator));
+ }
+
+ #[test]
+ fn rejects_shell_hostile_namespace() {
+ assert_eq!(
+ "steam;touch:620".parse::(),
+ Err(GameIdError::InvalidNamespace)
+ );
+ }
+}
diff --git a/deny.toml b/deny.toml
new file mode 100644
index 0000000..92adc3b
--- /dev/null
+++ b/deny.toml
@@ -0,0 +1,29 @@
+[graph]
+all-features = true
+
+[advisories]
+version = 2
+yanked = "deny"
+ignore = []
+
+[licenses]
+version = 2
+confidence-threshold = 0.8
+allow = [
+ "AGPL-3.0-or-later",
+]
+exceptions = []
+
+[bans]
+multiple-versions = "deny"
+wildcards = "deny"
+highlight = "all"
+deny = []
+skip = []
+skip-tree = []
+
+[sources]
+unknown-registry = "deny"
+unknown-git = "deny"
+allow-registry = ["https://github.com/rust-lang/crates.io-index"]
+allow-git = []
diff --git a/docs/adr/0001-private-kiln-workspace.md b/docs/adr/0001-private-kiln-workspace.md
new file mode 100644
index 0000000..ca31cc9
--- /dev/null
+++ b/docs/adr/0001-private-kiln-workspace.md
@@ -0,0 +1,19 @@
+# ADR 0001: Private Kiln workspace baseline
+
+- Status: accepted
+- Date: 2026-07-18
+- Decisions: D-022 through D-026, D-050, D-065, D-066
+
+## Decision
+
+Begin with one Rust workspace containing a reusable `kiln-core` library and one
+`kiln` binary package. Keep the initial proof dependency-free so contracts can be
+tested offline and dependency review begins from zero. Temporary Kiln names remain
+private and unpublishable.
+
+## Consequences
+
+Provider crates can be added independently after phase 1 contracts stabilize. No
+package has a publishable registry identity, and no global installation procedure is
+provided. The first CLI proof validates wiring only; it is not provider functionality.
+
diff --git a/docs/handoff/phase-1-codex-cli.md b/docs/handoff/phase-1-codex-cli.md
new file mode 100644
index 0000000..8533efc
--- /dev/null
+++ b/docs/handoff/phase-1-codex-cli.md
@@ -0,0 +1,42 @@
+# Phase 1 Codex CLI handoff
+
+## Objective
+
+Implement and aggressively test provider-independent versioned contracts before any real
+Steam, native, Heroic, Lutris, or UMU integration begins.
+
+## Required contract areas
+
+- game identity and installation-instance identity;
+- durable installation registry and move aliases;
+- store, adapter, configuration owner, execution backend, and runtime separation;
+- provider and runtime capability interfaces;
+- versioned JSON records and machine output;
+- argument-safe launch plans and dry-run representation;
+- lifecycle confidence and its allowed policy effects;
+- structured errors, including ambiguous-name candidates and unsupported versions;
+- versioned TOML configuration precedence and provenance;
+- a deterministic mock adapter covering success, absence, ambiguity, malformed input,
+ unsupported capability, moved installation, and launch-planning failure.
+
+## Exclusions
+
+- No real provider parsing or process launching.
+- No daemon, IPC transport, cache, SQLite discovery index, GUI, session supervisor, or
+ installation management.
+- No public API stability claim.
+- No final public naming work.
+
+## Required gates
+
+- Unit tests for value objects, parsing, validation, precedence, and errors.
+- Contract tests for serialization, schema rejection, capability behavior, and launch
+ plans.
+- Isolated integration tests using only synthetic temporary state and the mock adapter.
+- Adversarial tests required by R-024 and the threat model where Phase 1 code accepts
+ strings, paths, manifests, environment values, or serialized data.
+- `make verify` and `make audit` both pass.
+
+Before coding, split this phase into narrow tasks and present any contract choice that
+would materially constrain future adapters to the project owner.
+
diff --git a/docs/phase-0/checklist.md b/docs/phase-0/checklist.md
new file mode 100644
index 0000000..f76161b
--- /dev/null
+++ b/docs/phase-0/checklist.md
@@ -0,0 +1,23 @@
+# Phase 0 exit checklist
+
+| Exit criterion | Evidence | State |
+| --- | --- | --- |
+| Rust workspace and component boundaries | root and crate manifests; ADR 0001 | Passed |
+| Temporary naming and rename path | rename manifest; placeholder scanner | Passed for private development |
+| Toolchain and lockfile | Rust 1.97.1 checker; desktop evidence; committed lockfile | Passed |
+| Formatting, linting, tests | `make verify`; desktop evidence | Passed |
+| CI | pinned workflow invoking `make verify` and `make audit` | Configured; first hosted run pending |
+| Dependency/license/security audits | workspace auditor; `deny.toml`; cargo-deny 0.20.2 | Passed |
+| Release/version policy | release policy and changelog | Passed |
+| ADRs | `docs/adr/` | Passed |
+| Fixture rules | fixture policy | Passed |
+| Threat model | initial threat model | Passed |
+| Package/source inventory | schema-versioned TOML inventory | Passed for current components |
+| Test evidence format | template plus desktop evidence | Passed |
+| Requirement traceability | 29 IDs mapped to phases and evidence classes | Passed structurally |
+| Supported-platform decision | supported-platform record | Passed |
+| Canonical project license | root GNU AGPL v3 text; hash checked | Passed |
+
+Phase 0 is closed. The first hosted CI run is operational evidence rather than a blocker
+to beginning private Phase 1 contract design, but it must pass before accepting external
+changes or treating CI as enforced.
diff --git a/docs/phase-0/evidence-2026-07-18-work-mode.md b/docs/phase-0/evidence-2026-07-18-work-mode.md
new file mode 100644
index 0000000..f62ea0e
--- /dev/null
+++ b/docs/phase-0/evidence-2026-07-18-work-mode.md
@@ -0,0 +1,66 @@
+# Test evidence: Work Mode baseline
+
+- Date/time (UTC): 2026-07-18
+- Repository revision: uncommitted initial scaffold
+- Requirement IDs: R-001 through R-029 (structural traceability only)
+- Phase/gate: phase 0 / lightweight static baseline
+- Runtime: ChatGPT Work Mode container; Python 3.12; Git 2.51.1
+- Exact commands: `make static`, `python3 -m py_compile scripts/verify_repo.py`, `git diff --check`
+- Expected result: manifests/spec parse, identifiers are unique, every requirement is traced,
+ temporary naming is recorded, Python verifier compiles, and whitespace checks pass
+- Observed result: `PASS: Phase 0 static baseline (29 requirements traced)`; remaining checks passed silently
+- Logs/artifacts: none required; command output contains no credentials or personal provider data
+- Cleanup performed: generated Python bytecode ignored; no provider or user state accessed
+- Result: pass, with Rust compilation explicitly blocked because Rust is unavailable here
+
+## First desktop attempt
+
+The first local run correctly exposed two scaffold defects before compilation: source
+files were not in canonical Rustfmt form, and the workspace treated the 1.97.1 toolchain
+pin as its minimum supported compiler. The source was formatted and the MSRV was corrected
+to Rust 1.85 (the Edition 2024 baseline) while retaining 1.97.1 as the exact development
+and CI toolchain pin.
+
+The corrected workspace then passed Rustfmt, `cargo check`, all three core unit tests,
+Clippy with `-D warnings`, `kiln doctor`, and JSON doctor output on the user's
+EndeavourOS desktop. The output revealed that the active distro compiler was Rust 1.97.0,
+not the declared 1.97.1 pin. The result is retained as valid functional evidence, but it
+does not complete the reproducible-toolchain gate. `make verify` now checks the active
+compiler version before running Rust quality gates.
+
+## Final desktop rerun
+
+- Platform: EndeavourOS / Arch Linux package `rust 1:1.97.1-1`
+- Compiler: `rustc 1.97.1 (8bab26f4f 2026-07-14)`
+- Commands: `make verify`; preceding corrected run also executed both `kiln doctor` forms
+- Result: static baseline passed; exact compiler pin passed; Rustfmt passed; workspace and
+ all-target check passed; three of three core unit tests passed; Clippy passed with
+ warnings denied; doctor returned schema 1 and JSON status `ok`
+- Gate status: passed
+
+## Completed repository-policy baseline
+
+The subsequent Phase 0 audit added and verified the canonical 34,523-byte GNU AGPL v3
+license text, release/version policy, changelog, fixture policy, security-reporting
+policy, cargo-deny configuration, pinned audit-tool inventory, real placeholder scan,
+workspace/license/source audit, and local Markdown-link validation. The dependency-free
+workspace contains no external packages in `Cargo.lock`. `make static` passes all three
+dependency-free audit programs. The network-backed `make audit` gate remains pending.
+
+The first cargo-deny 0.20.2 execution rejected the local `kiln-core` path dependency as
+wildcarded because it lacked a version constraint. It also reported unused allowances in
+the speculative broad license list. The internal dependency now requires exact version
+`=0.0.1` while retaining its workspace path, and the license allowlist now contains only
+AGPL-3.0-or-later. Future dependency licenses require an explicit reviewed addition. A
+fresh `make verify` and `make audit` result is required.
+
+## Final Phase 0 audit rerun
+
+- Commands: `make verify`; `make audit`
+- Static baseline: passed, 29 requirement IDs traced
+- Workspace/license/source audit: passed
+- Temporary-name scan: passed, 29 private occurrences inventoried
+- Compiler: exact Rust 1.97.1 pin passed
+- Rustfmt, workspace/all-target check, three unit tests, and Clippy `-D warnings`: passed
+- cargo-deny 0.20.2: advisories, bans, licenses, and sources all passed
+- Phase 0 result: complete
diff --git a/docs/phase-0/fixture-policy.md b/docs/phase-0/fixture-policy.md
new file mode 100644
index 0000000..c588818
--- /dev/null
+++ b/docs/phase-0/fixture-policy.md
@@ -0,0 +1,26 @@
+# Fixture policy
+
+## Allowed
+
+- Small, synthetic, deterministic files created specifically for tests.
+- Sanitized fragments whose provenance and redistribution permission are recorded.
+- Malformed, missing-field, duplicate, moved, unmounted, unusual-path, invalid-encoding,
+ oversized-boundary, symlink, traversal, and shell-metacharacter cases.
+- Temporary integration state created under a test-owned directory and removed afterward.
+
+## Forbidden
+
+- Live tokens, cookies, account identifiers, device identifiers, personal paths, save
+ files, complete personal libraries, crash dumps with private data, or proprietary
+ launcher databases copied wholesale.
+- Network access in unit or contract tests.
+- Fixtures whose expected result depends on the developer's username, UID, home path,
+ locale, clock, network, mount layout, or installed games.
+
+## Review and storage
+
+Every fixture directory contains a README stating its origin, license/permission,
+sanitization, parser behavior being tested, and whether it may be redistributed. Binary
+fixtures require a size justification and checksum. Secrets scanners and adversarial
+tests treat fixtures as hostile input, not trusted code or shell text.
+
diff --git a/docs/phase-0/release-version-policy.md b/docs/phase-0/release-version-policy.md
new file mode 100644
index 0000000..426197d
--- /dev/null
+++ b/docs/phase-0/release-version-policy.md
@@ -0,0 +1,30 @@
+# Release and version policy
+
+## Private development
+
+- Workspace packages share one `0.0.x` version while contracts are private.
+- Every user-visible or contract-affecting change is recorded under `Unreleased`.
+- Machine-readable contracts carry their own positive integer schema version.
+- Breaking schema changes increment that schema version and include rejection tests for
+ unsupported versions; consumers never guess.
+- Temporary Kiln identifiers are never published, globally installed, or treated as
+ compatibility promises.
+
+## Public releases
+
+- Select and collision-check the final related naming system before the first public
+ package, crate, executable, configuration namespace, or IPC endpoint.
+- Use Semantic Versioning for project packages; pre-1.0 compatibility remains explicit
+ rather than implied stable.
+- A release derives from an annotated signed tag and clean repository state.
+- Release records include source revision, toolchain, lockfile, package/source inventory,
+ hashes, SBOM, signatures, license notices, supported-platform matrix, and test evidence.
+- Bit-for-bit reproducibility is claimed only after independent reproduction.
+- No release resolves live AUR state or downloads unpinned executable installer plugins.
+
+## Version ownership
+
+The workspace version is changed once at the root and inherited by every project crate.
+Provider protocol/schema versions remain independent when their compatibility boundaries
+require it. Release tooling must reject mismatched workspace package versions.
+
diff --git a/docs/phase-0/rename-manifest.md b/docs/phase-0/rename-manifest.md
new file mode 100644
index 0000000..1af2edf
--- /dev/null
+++ b/docs/phase-0/rename-manifest.md
@@ -0,0 +1,15 @@
+# Temporary-name manifest
+
+All entries are private placeholders and must be replaced before publishing,
+packaging, or global installation.
+
+| Placeholder | Current use | Replacement gate |
+| --- | --- | --- |
+| `Project Kiln` | prose-only project codename | final related naming system approved |
+| `kiln` | repository-local binary target and examples | executable collision screen complete |
+| `kiln-*` | workspace package/component family | package and crate collision screen complete |
+| `KILN_*` | reserved future environment prefix; not yet used | environment/config namespace approved |
+
+The static verifier scans structure and requires this manifest. A later release gate
+must scan filenames and file contents for every placeholder and fail on remnants.
+
diff --git a/docs/phase-0/source-inventory.toml b/docs/phase-0/source-inventory.toml
new file mode 100644
index 0000000..9b2f8bf
--- /dev/null
+++ b/docs/phase-0/source-inventory.toml
@@ -0,0 +1,21 @@
+schema_version = 1
+
+[[components]]
+name = "rust"
+kind = "toolchain"
+source = "https://static.rust-lang.org"
+version = "1.97.1"
+license = "Apache-2.0 OR MIT"
+owner = "project maintainers"
+update_policy = "explicit pull request after release and security review"
+release_profile = false
+
+[[components]]
+name = "cargo-deny"
+kind = "development-audit-tool"
+source = "https://crates.io/crates/cargo-deny"
+version = "0.20.2"
+license = "Apache-2.0 OR MIT"
+owner = "project maintainers"
+update_policy = "explicit pull request after release, changelog, and config review"
+release_profile = false
diff --git a/docs/phase-0/status.md b/docs/phase-0/status.md
new file mode 100644
index 0000000..8c1ea30
--- /dev/null
+++ b/docs/phase-0/status.md
@@ -0,0 +1,43 @@
+# Phase 0 status — complete
+
+## Verified in Work Mode
+
+- Active numbered specification imported; archive intentionally excluded.
+- Workspace manifests and pinned-toolchain configuration parse successfully.
+- All 29 requirement IDs are unique and represented in the traceability matrix.
+- Decision IDs are unique; active spec version marker is `0.16`.
+- Temporary naming is documented and structurally constrained.
+- Python verifier compiles and the repository has no whitespace errors.
+
+## Local execution result — passed
+
+The initial desktop execution exposed and corrected formatting and toolchain-enforcement
+defects. The final execution passed under Arch Linux Rust 1.97.1:
+
+- static repository/specification verification;
+- exact-toolchain verification;
+- Rustfmt;
+- workspace and all-target compilation;
+- all three core unit tests;
+- Clippy for the workspace and all targets with warnings denied;
+- human and JSON `kiln doctor` smoke paths (verified in the preceding run).
+
+Reproduce the gate with:
+
+```sh
+make verify
+cargo run --locked -p kiln-cli -- doctor
+cargo run --locked -p kiln-cli -- doctor --json | jq -e \
+ '.schema_version == 1 and .status == "ok" and .private_placeholder == true'
+```
+
+The exact-toolchain gate, canonical AGPL license, dependency-free static audits, and
+cargo-deny 0.20.2 advisory/bans/licenses/sources audit all pass. Phase 0 is closed.
+A first hosted CI run remains required before accepting external changes or claiming
+enforced CI, but does not block private Phase 1 contract design.
+
+`rust-version = "1.85"` records the minimum supported compiler for Edition 2024. The
+exact reviewed development and CI toolchain remains pinned separately to Rust 1.97.1 in
+`rust-toolchain.toml`; these controls must not be conflated. `make verify` explicitly
+checks the active `rustc` version because distro-provided Rust binaries may ignore the
+Rustup override file.
diff --git a/docs/phase-0/supported-platforms.md b/docs/phase-0/supported-platforms.md
new file mode 100644
index 0000000..95e989d
--- /dev/null
+++ b/docs/phase-0/supported-platforms.md
@@ -0,0 +1,10 @@
+# Supported-platform decision record
+
+Version 1 targets x86_64 UEFI and one local gaming user. AMD and NVIDIA are
+release-blocking GPU families; Intel remains best-effort until representative coverage
+exists. The initial bare-metal reference is Ryzen 9 7900X3D plus RTX 5070 installed to
+a dedicated external USB drive. Xbox-family and PlayStation-family controllers require
+USB and Bluetooth coverage; exact revisions are recorded before phase 6 execution.
+
+Legacy BIOS, non-x86 architectures, and multi-user isolation are outside v1.
+
diff --git a/docs/phase-0/test-evidence-template.md b/docs/phase-0/test-evidence-template.md
new file mode 100644
index 0000000..c90bdaf
--- /dev/null
+++ b/docs/phase-0/test-evidence-template.md
@@ -0,0 +1,16 @@
+# Test evidence
+
+- Date/time (UTC):
+- Repository revision:
+- Requirement IDs:
+- Phase/gate:
+- Hardware, firmware, kernel, driver:
+- Package/tool versions:
+- Fixture or dedicated test account:
+- Exact commands:
+- Expected result:
+- Observed result:
+- Logs/artifacts (sanitized):
+- Cleanup performed:
+- Result: pass / fail / blocked
+
diff --git a/docs/phase-0/threat-model.md b/docs/phase-0/threat-model.md
new file mode 100644
index 0000000..30c5e8b
--- /dev/null
+++ b/docs/phase-0/threat-model.md
@@ -0,0 +1,17 @@
+# Initial threat model
+
+## Assets and boundaries
+
+- Provider manifests, custom launch definitions, artwork, and frontend descriptors are untrusted.
+- Discovery and launch parsing run as the gaming user, never root.
+- Provider credentials remain owned by their provider/configuration owner.
+- Project state is per-user under XDG paths and must use atomic replacement.
+- Future IPC is local, owner-only, size-limited, authenticated by OS credentials, and optional.
+
+## Mandatory controls before provider work
+
+Use argument arrays rather than interpolated shells; reject traversal, control
+characters, oversized inputs, unsafe symlinks, and unexpected encodings; redact tokens
+and personal paths from evidence; constrain reads to documented roots; and keep fixtures
+free of proprietary library dumps and live credentials.
+
diff --git a/docs/phase-0/traceability.csv b/docs/phase-0/traceability.csv
new file mode 100644
index 0000000..438242d
--- /dev/null
+++ b/docs/phase-0/traceability.csv
@@ -0,0 +1,31 @@
+requirement_id,owner_phase,initial_evidence,status
+R-001,10,package reconstruction record,planned
+R-002,8,session acceptance test,planned
+R-003,9,performance benchmark record,planned
+R-004,6,controller compatibility matrix,planned
+R-005,7,provider contract and acceptance tests,planned
+R-006,2,CLI integration tests,planned
+R-007,8,gaming-tool integration tests,planned
+R-008,8,session lifecycle acceptance test,planned
+R-009,1,core contract tests,planned
+R-010,5,TTY recovery acceptance test,planned
+R-011,0,development workflow record,active
+R-012,1,shared-backend architecture tests,planned
+R-013,8,profile policy acceptance tests,planned
+R-014,12,Pegasus adapter tests,post-v1
+R-015,8,Lean and Ready policy tests,planned
+R-016,7,adapter capability contract tests,planned
+R-017,8,window-switching acceptance tests,planned
+R-018,4,lifecycle confidence tests,planned
+R-019,15,vendor launcher tests,post-v1
+R-020,6,Bluetooth CLI and TUI tests,planned
+R-021,11,installer destructive VM tests,planned
+R-022,10,optional recovery profile tests,optional
+R-023,14,OpenGamepadUI evaluation,post-v1
+R-024,1,adversarial contract tests,planned
+R-025,0,source inventory and release review,active
+R-026,0,supported-platform record,active
+R-027,0,path and identity architecture review,active
+R-028,8,release GPU matrix,planned
+R-029,1,TOML and JSON contract tests,planned
+
diff --git a/docs/spec/00_SPEC_INDEX.md b/docs/spec/00_SPEC_INDEX.md
new file mode 100644
index 0000000..d8ecdf3
--- /dev/null
+++ b/docs/spec/00_SPEC_INDEX.md
@@ -0,0 +1,36 @@
+# CLI-First Arch Gaming OS — Specification Index
+
+This directory is the starting point for project planning and later implementation.
+
+## Source-of-truth rules
+
+- The numbered topic files collectively contain the complete specification.
+- They began as a structural split of the original specification and have since evolved through later numbered revisions recorded in the change log.
+- `99_FULL_SPEC_ARCHIVE.md` remains the preserved monolithic v0.4 reference and historical source. It is not updated in lockstep with later numbered revisions.
+- When updating the project, edit the relevant topic file and keep this index current. Avoid adding a second statement of the same decision elsewhere.
+- Open questions must remain explicitly marked as open; proposals are not confirmed requirements.
+- Before saving any planning change, apply the mandatory cross-spec integrity procedure in `01_PROJECT_FOUNDATION.md`. Do not guess when a conflict would change scope, release boundaries, architecture, or user-visible behavior; ask the project owner for clarification first.
+
+## Quick navigation
+
+| File | Use it for |
+| --- | --- |
+| [01_PROJECT_FOUNDATION.md](01_PROJECT_FOUNDATION.md) | Document usage, vision, goals, non-goals, principles, and confirmed requirements |
+| [02_ARCHITECTURE_AND_BACKEND.md](02_ARCHITECTURE_AND_BACKEND.md) | System layers, components, process model, unified launcher API/CLI, records, launch plans, and external-client contract |
+| [03_PROVIDERS_SESSIONS_AND_INPUT.md](03_PROVIDERS_SESSIONS_AND_INPUT.md) | Steam/Heroic/Lutris/provider strategy, graphical session behavior, runtime profiles, launcher lifecycle, fallbacks, and controllers |
+| [04_BASE_PERFORMANCE_RELIABILITY.md](04_BASE_PERFORMANCE_RELIABILITY.md) | Arch base system, performance policy and benchmarking, recovery, privacy, and security |
+| [05_FRONTENDS_AND_SESSION_POLICIES.md](05_FRONTENDS_AND_SESSION_POLICIES.md) | Graphical policies, Pegasus integration, fork/custom-frontend policy, and provider-interface behavior |
+| [06_DEVELOPMENT_ROADMAP_AND_ACCEPTANCE.md](06_DEVELOPMENT_ROADMAP_AND_ACCEPTANCE.md) | Development environments, validation, delivery phases, and version 1 acceptance criteria |
+| [07_RISKS_DECISIONS_AND_HISTORY.md](07_RISKS_DECISIONS_AND_HISTORY.md) | Risks, open questions, decision log, change log, and reference notes |
+
+## Suggested agent reading order
+
+1. Read this index.
+2. Read `01_PROJECT_FOUNDATION.md` for scope and confirmed constraints.
+3. Read only the topic files relevant to the current task.
+4. Before changing architecture or scope, also read `07_RISKS_DECISIONS_AND_HISTORY.md` to avoid reviving rejected or deferred ideas.
+5. Use the monolithic reference only for integrity checks or when cross-topic context is genuinely needed.
+
+## Integrity note
+
+The numbered topic files are the current v0.15 source of truth. `99_FULL_SPEC_ARCHIVE.md` preserves the complete monolithic v0.4 specification for historical and integrity checks, so it no longer matches the evolving numbered files byte-for-byte.
diff --git a/docs/spec/01_PROJECT_FOUNDATION.md b/docs/spec/01_PROJECT_FOUNDATION.md
new file mode 100644
index 0000000..2285abd
--- /dev/null
+++ b/docs/spec/01_PROJECT_FOUNDATION.md
@@ -0,0 +1,138 @@
+# CLI-First Arch Gaming OS
+
+> Performance-first Linux gaming appliance with a unified launcher backend
+
+| **Status** | Implementation — phase 0 complete; phase 1 ready |
+|--------------------|----------------------------------------------------|
+| **Version** | 0.18 |
+| **Created** | July 17, 2026 |
+| **Document type** | Living project specification |
+| **Current target** | Purpose-built, performance-focused gaming distribution |
+
+**Purpose:** Preserve project context, distinguish requirements from proposals, record decisions, and provide a controlled place to update the plan as it evolves.
+
+## How to use this document
+
+- Treat items marked Required or Confirmed as current project constraints.
+- Treat Proposed items as design candidates that still require validation.
+- Record significant changes in both the Decision Log and Change Log.
+- Do not silently convert an open question into a requirement.
+
+### Mandatory spec-change integrity procedure
+
+Every planning addition, removal, or change must be checked against the complete current numbered specification before it is saved. This applies equally to new features, small wording changes, changed priorities, deferred work, and release-scope changes.
+
+For each change:
+
+1. Identify the affected requirement IDs, decisions, open questions, roadmap phases, acceptance criteria, risks, architecture contracts, and cross-file references.
+2. Search all numbered topic files for the affected terms and concepts; do not rely only on the file being edited.
+3. Verify that status language is consistent: Required, Confirmed, Proposed, Deferred, Post-v1, and Open must not describe the same item incompatibly.
+4. Verify release boundaries and dependency order. A deferred or post-v1 capability must not remain a version 1 acceptance criterion or be required by an earlier roadmap phase.
+5. Verify that examples, commands, schemas, and component descriptions do not promise capabilities excluded elsewhere.
+6. Update the requirement table, decision log, open questions, roadmap, acceptance criteria, risks, change log, version markers, and index wherever the change materially affects them.
+7. Run structural checks for duplicate requirement or decision IDs, stale version markers, and broken internal links.
+8. If the intended resolution is already established by a confirmed decision, correct all affected statements consistently. If two or more plausible resolutions would change project scope, architecture, release timing, compatibility, or user-visible behavior, stop and ask the project owner for clarification before recording a choice.
+
+The historical archive is evidence, not a second source of truth. Do not rewrite it to make old versions appear current.
+
+## 1. Executive summary
+
+The project, currently using the temporary internal codename **Project Kiln**, will explore and eventually prototype a purpose-built Arch Linux–based gaming distribution optimized exclusively for gaming. It presents a fullscreen terminal as its default shell, omits a conventional desktop environment, and launches Linux and Windows games through a simple unified command. The normal gaming mode will run inside a persistent, minimal graphical session so launchers, dialogs, frontends, and games can open without constructing and destroying a display environment for every operation. A true TTY-only target remains available for recovery and deliberate headless use.
+
+Performance, predictable behavior, recovery, and clear diagnostics take priority over visual polish. USB and Bluetooth controller support are core requirements. Version 1 remains CLI-first and DE-free, but not display-server-free: the graphical foundation stays available while heavyweight provider interfaces remain lazy by default. After version 1, Pegasus Frontend will be the first reference frontend for a controller-driven interface. It will initially be integrated without a fork by generating metadata whose launch commands call the shared backend CLI.
+
+> **Recommended delivery strategy:** Build and validate a reproducible gaming layer on minimal Arch first. Create a custom installation ISO only after the execution model, controllers, provider adapters, and recovery path work reliably.
+
+### 1.1 Codename and future naming
+
+- **Project Kiln** is a temporary development codename, not the intended public product name.
+- User-facing branding must be centralized in a small, documented set of metadata or configuration files rather than duplicated throughout source code.
+- Internal crate, module, protocol, schema, and configuration identifiers should use stable functional names where practical. They must not embed the codename merely for decoration.
+- The final names of the distribution, launcher CLI, reusable core, packages, configuration namespace, and IPC endpoints should be selected as one related naming system. Technical naming is intentionally deferred until the public project name is chosen.
+- Until then, repository-local development uses the temporary Kiln family: `kiln` for the single CLI command and functional component labels such as `kiln-core`, `kiln-cli`, `kiln-session`, and `kiln-adapter-*`. These names inherit the codename's temporary status.
+- Development may proceed with clearly marked, repository-local functional labels. Temporary labels must not be installed globally, published as packages or crates, or exposed as stable compatibility promises.
+- Places that require a project-specific identifier must be documented in a rename checklist and covered by an automated repository scan.
+- Selecting the final name will trigger one deliberate, mechanical rename before stable public compatibility commitments. The source is not required to retain the Kiln codename permanently.
+
+## 2. Vision and problem statement
+
+### 2.1 Vision
+
+Provide a gaming-focused Linux appliance that feels closer to the directness of a console or old text-first gaming system than a general-purpose desktop, while retaining Arch Linux transparency, package access, and user control.
+
+### 2.2 Problem
+
+Linux gaming is fragmented across launchers, compatibility runtimes, prefixes, compositors, overlays, and provider-specific metadata. Existing gaming distributions reduce setup work but generally center a graphical shell, bundle more software, or conceal launch details. A minimal system can provide a smaller and more predictable operating environment, but only if it avoids replacing desktop complexity with brittle shell-script complexity.
+
+### 2.3 Product hypothesis
+
+A unified backend and CLI can make a CLI-presented gaming system practical while a minimal compositor supplies the graphical plumbing modern games and launchers expect. The same backend can support terminal, controller, desktop, web, or third-party frontends without coupling game management to one interface.
+
+## 3. Goals, non-goals, and principles
+
+### 3.1 Goals
+
+- Enter a minimal graphical gaming session whose default visible shell is a fullscreen terminal, with no conventional desktop environment required.
+- Launch installed games by human-readable name through a consistent command.
+- Support Steam, Lutris, Heroic-managed Epic, GOG, and Amazon libraries, native games, and custom Windows games using appropriate Wine/Proton runtimes, including UMU where suitable. Third-party vendor launchers are post-v1.
+- Provide reliable USB and Bluetooth controller operation, hotplugging, reconnection, and diagnostics.
+- Keep a minimal graphical foundation available for launchers and games while retaining a true TTY recovery path.
+- Optimize for frametime consistency, latency, stability, and low background overhead.
+- Keep launch behavior inspectable, reproducible, and recoverable.
+- Preserve a clean path to future lightweight desktop and controller-driven frontends.
+
+### 3.2 Non-goals for version 1
+
+- Building a general-purpose desktop distribution.
+- Matching every Steam Deck or SteamOS user-interface feature.
+- Supporting every launcher operation through the unified API on day one.
+- Bypassing unsupported anti-cheat, DRM, platform restrictions, or Windows-only kernel components.
+- Guaranteeing higher average FPS than every conventional Arch installation.
+- Supporting handheld hardware, touch-first controls, or immutable system images initially.
+
+### 3.3 Guiding principles
+
+| **Principle** | **Meaning** |
+|-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------|
+| Measure, do not mythologize | A tuning change belongs only when benchmarking or reliability evidence supports it. |
+| CLI is the interface, not the graphics implementation | The default shell may look like a console while running inside a persistent minimal Wayland/Xwayland or Xorg session. |
+| Adapters own provider details | The core consumes normalized capabilities rather than embedding every launcher's internals. |
+| Safe fallback beats clever failure | Every optimized path needs a simpler recovery or diagnostic path. |
+| Minimal does not mean incomplete | Fonts, portals, 32-bit libraries, udev rules, audio, and authentication dependencies are included when required. |
+| Modularity over monoliths | Install profiles and packages should allow components to be added or removed cleanly. |
+| Project frontends are replaceable clients | No project-integrated catalogue frontend owns provider discovery, normalized identity, launch logic, or session policy; provider-native clients retain their own native behavior. |
+| Upstream before forks | Integrate and contribute upstream before accepting permanent maintenance of a project-specific frontend fork. |
+
+## 4. Confirmed requirements
+
+| **ID** | **Status** | **Area** | **Requirement** |
+|--------|------------|----------------|----------------------------------------------------------------------------------------------------------------------------|
+| R-001 | Required | Base system | Arch Linux–based and reconstructable from recorded repository state, package versions, project configuration, and build inputs; bit-for-bit reproducibility is a later hardening goal. |
+| R-002 | Required | User interface | Normal gaming mode presents a fullscreen terminal inside a persistent minimal graphical session; no conventional DE is required. |
+| R-003 | Required | Performance | Performance and frametime consistency are primary design priorities. |
+| R-004 | Required | Controllers | USB and Bluetooth controllers are supported as core functionality. |
+| R-005 | Required | Providers | Version 1 supports Steam, Lutris, Heroic-managed Epic, GOG, and Amazon libraries, native games, and custom Windows games; each store is a separate adapter/capability target, and UMU is an execution runtime rather than a library provider. |
+| R-006 | Required | Launch UX | A game can be launched by typing its name or selecting it from a searchable CLI/TUI list. |
+| R-007 | Required | Gaming tools | GameMode, Gamescope, MangoHud/MangoApp, Proton/Wine tooling, and relevant diagnostics are included. |
+| R-008 | Required | Lifecycle | Closing a game, launcher, or frontend returns to the existing session shell without rebuilding the graphical environment. |
+| R-009 | Required | Extensibility | The unified backend must not depend on a future desktop frontend. |
+| R-010 | Required | Recovery | A true TTY-only mode remains available for recovery, diagnostics, and explicit user choice. |
+| R-011 | Required | Development | Use libvirt/QEMU for routine development and disposable testing; validate hardware behavior and performance on bare metal. |
+| R-012 | Required | Architecture | The CLI and all project-integrated catalogue frontends consume the same normalized backend behavior rather than implementing provider launch logic independently. Provider-native interfaces such as Steam Big Picture may retain their native library and launch behavior when opened explicitly. |
+| R-013 | Required | Frontend | The initial visible shell may be the terminal, Steam Big Picture, another configured frontend, or a custom command, and this policy is changeable after installation. Pegasus becomes a supported reference option after version 1. |
+| R-014 | Post-v1 | Pegasus | After version 1, support upstream Pegasus as the first reference controller frontend without requiring a fork. |
+| R-015 | Required | Profiles | Lean is the default runtime profile; users may instead keep selected launchers resident or autostart a frontend. |
+| R-016 | Required | Providers | Provider adapters use the lightest reliable supported path and advertise actual capabilities instead of assuming every provider is symmetrical. |
+| R-017 | Required | Windowing | Users can quickly focus or switch among the terminal, resident launchers, frontends, and a running game. |
+| R-018 | Required | Lifecycle | The system tracks game lifetime as reliably as each provider permits so temporary performance, sleep-inhibition, logging, and cleanup policy can follow the game; ordinary operation does not automatically close provider clients after play. |
+| R-019 | Post-v1 | Providers | Third-party vendor launchers such as Battle.net, EA App, Ubisoft Connect, and Rockstar are added after version 1 through tested managed-prefix integrations. |
+| R-020 | Required | Input tooling | Use Bluetui as the standard interactive Bluetooth TUI; retain structured project-owned diagnostics and automation, and offer Blueman as the optional desktop Bluetooth GUI. |
+| R-021 | Required | Installation | Build the eventual guided installer on archinstall using a maintained project profile/configuration and, only where necessary, a pinned local plugin or custom script; do not reimplement partitioning, encryption, account creation, or base Arch installation. |
+| R-022 | Optional | Recovery | Offer a Btrfs installation profile using Snapper and pacman transaction hooks; do not require Btrfs for the default or filesystem-neutral installation path. |
+| R-023 | Post-v1 | Frontends | Evaluate OpenGamepadUI after version 1 as an additional replaceable controller frontend without transferring backend authority to its internal catalog. |
+| R-024 | Required | Security | Provider data, custom manifests, artwork, and frontend descriptors are untrusted input; ordinary discovery and launch remain unprivileged, argument-safe, path-confined, and covered by adversarial tests. |
+| R-025 | Required | Packaging | Every shipped non-Arch component has an explicit source, pinned build or release input, license/provenance record, update owner, and removal or fallback plan before it enters a release profile. |
+| R-026 | Required | Platform | Version 1 supports x86_64 UEFI systems; legacy BIOS and non-x86 architectures are outside the v1 support boundary. |
+| R-027 | Required | Users | Version 1 is a single-local-gaming-user appliance. Per-user state, services, paths, identities, and permissions must preserve a clean path to post-v1 multi-user libraries, saves, credentials, and profiles. |
+| R-028 | Required | Graphics | AMD and NVIDIA are release-blocking v1 GPU/driver families; Intel graphics are tested where practical and labeled best-effort until representative hardware coverage exists. |
+| R-029 | Required | Configuration | User-editable project configuration uses versioned TOML with generated commented defaults and equivalent CLI operations; JSON remains the machine-output and contract encoding. |
diff --git a/docs/spec/02_ARCHITECTURE_AND_BACKEND.md b/docs/spec/02_ARCHITECTURE_AND_BACKEND.md
new file mode 100644
index 0000000..ce53fae
--- /dev/null
+++ b/docs/spec/02_ARCHITECTURE_AND_BACKEND.md
@@ -0,0 +1,176 @@
+## 5. Proposed system architecture
+
+### 5.0 Repository and implementation policy
+
+- Rust is the confirmed implementation language for project-owned backend, CLI, and provider-adapter software.
+- Development begins in one Git repository organized as a Rust workspace and clearly separated system directories.
+- The backend, system integration, distribution tooling, and each provider adapter are distinct internal components with explicit boundaries, even while they share one repository.
+- Provider adapters are separate crates so they can be tested independently and later extracted for reuse when their contracts and release cadence are stable.
+- Do not split components into separate Git repositories during early development. Avoid submodules and multi-repository coordination while interfaces are still changing.
+- A component may later move to its own repository with history preserved when it has a stable public contract, independent tests, clear external value, and a genuinely independent release lifecycle.
+- The repository and task documentation must allow one Codex CLI session started at the repository root to work across the complete project without manual context handoffs.
+- Bootstrap the repository before feature work with a pinned Rust toolchain, committed dependency lockfile, formatting and lint policy, deny-by-default CI checks, license/security auditing, fixture conventions, changelog/version policy, and an architecture-decision-record directory. The first vertical slice must not invent these piecemeal.
+
+### 5.1 Layer model
+
+| **Interface** | `kiln` CLI, Pegasus adapter, future TUI/desktop/controller frontends |
+|------------------------|---------------------------------------------------------------------------|
+| **Unified core** | Normalized library, identity, capabilities, profiles, optional index, launch plans |
+| **Provider adapters** | Steam, Lutris, Epic, GOG, Amazon, native, and custom manifests |
+| **Execution services** | Session supervisor, Wine/Proton/UMU runtimes, profile engine, lifecycle tracking, logging, diagnostics |
+| **Platform** | Arch, systemd, graphics drivers, PipeWire, BlueZ, input/udev, filesystems |
+
+### 5.2 Core components
+
+The component and executable names below form the temporary Kiln development family, not approved install names. They may be used only in prose, tests, and repository-local development scaffolding. They must not become global executables, published packages/crates, configuration directories, D-Bus names, socket names, or stable compatibility surfaces. The final distribution name and its related technical namespace will be selected together, collision-checked, and applied through the documented rename procedure before the first public or installable artifact.
+
+**kiln-core:** Proposed reusable core/library that normalizes games and provider capabilities.
+
+**kiln:** The single human-facing, administrative, and machine-readable CLI. Subcommands provide fuzzy search and safe defaults as well as JSON output, automation, and diagnostics; no separate convenience executable is required.
+
+Name resolution never guesses through ambiguity. An exact stable ID wins; a unique normalized name or alias may launch directly; multiple matches produce an interactive numbered/TUI choice only on an attached terminal and a structured `ambiguous-game` error otherwise. The error includes stable IDs, provider/store, and installation labels so scripts can retry deterministically.
+
+**Provider adapters:** Separate Rust crates that discover and launch games through each provider. They remain in the shared repository initially but must not leak provider-specific parsing or policy into the core.
+
+**Session shell/supervisor:** Starts and monitors the persistent minimal compositor, fullscreen terminal, selected initial frontend, and configured resident applications.
+
+**Profile engine:** Combines global, hardware, provider, and per-game settings into a launch plan.
+
+**Runtime backends:** Execute native, Wine, Proton, or UMU launch plans. UMU does not own or discover a game library; a game retains its store or custom-manifest identity while selecting UMU as its runtime when appropriate.
+
+**Lifecycle tracker:** Observes game start and exit using the strongest method available for each provider: an owned process or systemd scope, provider-reported state, or conservative process correlation. It reports `tracked`, `provider-reported`, `probable`, or `unknown` rather than pretending every launch is equally observable.
+
+**Input subsystem:** Controller discovery, pairing helpers, permissions, testing, and health checks.
+
+**Diagnostics:** Collects provider, runtime, graphics, audio, controller, and session evidence.
+
+**Frontend adapters:** Export or translate the normalized catalogue into formats accepted by third-party frontends while routing launches back through `kiln`.
+
+### 5.3 Process model
+
+The normalized backend begins as a reusable Rust library consumed directly by a one-shot CLI. Initial discovery is on demand and uses no persistent database. A disposable cache or local SQLite database may be introduced only when measured scan latency or a proven live-state requirement justifies it; provider files remain authoritative and `kiln scan --no-cache` must remain available. The graphical session itself requires a small user-level supervisor, but this must not force provider discovery and launch logic into a permanently resident monolithic daemon. A later local service may expose D-Bus or a Unix socket when live frontend state, events, background refresh, or download status justify it.
+
+The one-shot CLI, future local service, and graphical clients must share one core implementation and versioned data contracts. The CLI must not become a parallel backend. If a resident service is introduced, the preferred first transport is a local Unix-domain socket with structured, versioned messages; a network HTTP API is deferred until a real remote-control use case exists.
+
+> **Performance constraint:** Lean starts heavyweight provider GUIs lazily. Ready may keep user-selected launchers resident for instant access. The project must measure idle CPU, GPU, memory, I/O, and game frametimes rather than treating process count or allocated RAM as performance proof.
+
+## 6. Unified launcher backend specification
+
+### 6.1 Identity model
+
+Every game must have a stable store/source-qualified identifier. Display names are searchable labels, not database keys. Game identity, installation instance, configuration owner, execution backend, and compatibility runtime are separate concepts.
+
+```text
+steam:1716740
+lutris:star-citizen
+epic:Salt
+gog:1207658693
+amazon:amzn1.adg.product.example
+native:openmw
+custom:star-citizen
+```
+
+Each installed copy receives a persistent installation UUID. An adapter-native stable installation identifier may seed it; otherwise a small schema-versioned installation registry in project-owned XDG state records the UUID, provider fingerprint, current location, and prior aliases. This registry is durable identity state, not a discovery cache or provider database. Writes are atomic and locked; rebuilding it must not change IDs for installations that can still be matched unambiguously. Store identity is independent of the management client: a game managed by Heroic is still `epic:`, `gog:`, or `amazon:`, while `configuration_owner` may be `heroic`. Adapters preserve aliases for changed local identifiers where possible and report duplicate, moved, and temporarily unavailable installations instead of silently merging them. Steam App IDs may be canonical directly; Lutris numeric database IDs are local implementation details, while Lutris slugs, desktop entries, and custom manifests require adapter-specific stability and migration rules.
+
+In machine-readable contracts, `store` is the canonical identity namespace, `adapter` identifies the discovery/launch implementation, `configuration_owner` identifies who owns mutable settings, and `execution_backend` identifies the invoked client/runtime path. Human-facing text may use "provider" generically, but schemas must not overload that word across these roles.
+
+### 6.2 Initial commands
+
+```text
+kiln list [--json]
+kiln search [--json]
+kiln info [--json]
+kiln scan [--provider ] [--no-cache]
+kiln launch [--dry-run] [--safe] [--x11]
+kiln launch --last | --favorites | --list | --logs
+kiln providers
+kiln provider open [--mode desktop|controller]
+kiln provider start [--hidden]
+kiln provider show
+kiln session profile lean|ready|frontend|custom
+kiln session shell terminal|steam|custom
+kiln session status
+kiln doctor
+```
+
+Frontend-adapter commands, including Pegasus configure/sync/start/autostart operations, are post-v1 commands added with phase 12. Pre-v1 builds must return a structured `unsupported-capability` error if asked for an unavailable frontend rather than exposing inert command stubs.
+
+### 6.3 Provider capability contract
+
+| **Capability** | **Version 1** | **Meaning** |
+|----------------|---------------|-------------------------------------------------------------------|
+| discover | Required | Enumerate installed games and core metadata. |
+| launch | Required | Produce or execute a normalized launch plan. |
+| info | Required | Return provider ID, install state, path, and runtime information. |
+| manage | Recommended | Open the provider GUI in a maintenance session. |
+| ui-optional | Informational | Games can launch without the provider's graphical interface. |
+| client-required| Informational | A provider client must run for normal launch or platform services.|
+| lifecycle-state| Informational | Adapter can report game-running state; confidence and method are returned explicitly. |
+| client-exit | Optional | Adapter can safely request provider-client exit when no managed work is active; never assumed or automatic. |
+| install | Deferred | Install a title through the provider. |
+| update | Deferred | Update a title or report update state. |
+| verify | Deferred | Request provider integrity verification. |
+| authenticate | Deferred | Perform or initiate provider login. |
+| uninstall | Deferred | Remove a title through the provider. |
+
+### 6.4 Normalized game record
+
+```yaml
+schema_version: 1
+id: steam:1716740
+name: Starfield
+store: steam
+adapter: steam
+installation_id: 7aa62d69-8f8e-4cab-8514-275ce1f87748
+configuration_owner: steam
+execution_backend: steam
+installed: true
+install_path: /games/steam/steamapps/common/Starfield
+compatibility:
+ type: proton
+ version: GE-Proton10-8
+capabilities: [discover, launch, client-required]
+client_required: true
+runtime: steam-proton
+```
+
+The YAML above is illustrative; JSON is the required v1 machine-output encoding. Machine-readable records, launch plans, capabilities, and errors are schema-versioned from phase 1. Breaking changes are allowed before the public 1.0 contract, but consumers must reject unsupported versions clearly rather than guessing.
+
+### 6.5 Launch plan
+
+The backend should resolve and display a launch plan before execution. A dry run must expose provider, installation/configuration owner, runtime, session backend, resolution, refresh rate, controller state, environment, wrappers, lifecycle-tracking strategy, and final command without starting the game.
+
+Provider launch commands may hand execution to an already-running client and then exit. The backend must not equate the invoking process with the game. Lifecycle tracking exists to time sleep inhibition, optional background-work suppression, logging, state reporting, and restoration of temporary settings. GameMode uses a real client/wrapper request bound to game execution and must not be toggled solely from heuristic lifecycle confidence. Failure to obtain exact lifecycle state must degrade to an explicit lower-confidence state and safe cleanup behavior. Automatic shutdown of Steam, Heroic, Lutris, or another provider client after play is not required.
+
+### 6.6 External client contract
+
+The backend should expose a documented, versioned contract that is useful without Pegasus or any first-party GUI. Initial machine-readable operations should map to the CLI's JSON output; a later local service may expose equivalent methods such as:
+
+```text
+games.list
+games.get
+games.launch
+providers.list
+providers.open
+sessions.status
+events.subscribe
+```
+
+Compatibility policy, JSON schemas, stable provider-qualified IDs, structured errors, authentication/authorization rules for the local transport, and at least one small example client are required before describing this interface as a public API. Operations such as force-stop are absent unless separately designed and capability-gated. Frontends must not parse Steam manifests, Heroic configuration, Lutris data, Wine prefixes, or emulator collections when the corresponding adapter already owns that work.
+
+### 6.7 Configuration ownership and precedence
+
+Launch configuration resolves from lowest to highest priority: built-in safe defaults, hardware profile, global user profile, provider/runtime defaults, per-game profile, and explicit one-launch CLI overrides. Dry runs retain the source of every resolved value and whether it replaced, merged with, appended to, or removed an earlier value.
+
+User-editable project configuration is versioned TOML. The CLI can generate fully commented defaults, validate without mutation, explain resolved values, and perform common edits without requiring manual file editing. JSON is reserved for machine-readable records, schemas, errors, and IPC contracts rather than being a second user-configuration syntax.
+
+Environment deletion, wrapper ordering, list merging, invalid values, schema migration, and concurrent external edits require explicit behavior and contract tests. Provider-owned credentials, prefixes, and settings remain provider-owned unless the user explicitly imports them; read-only discovery must not silently write to Heroic, Lutris, or Steam configuration.
+
+### 6.8 Trust boundaries and filesystem safety
+
+- Use XDG base directories for project configuration, state, cache, runtime sockets, and logs; document every exception.
+- Never bake the initial account name, UID, home path, or a system-wide mutable game catalogue into schemas or package defaults. V1 runs one gaming user at a time, but state and credentials remain per-user so a later multi-user session selector can isolate libraries, saves, prefixes, runtime choices, and authentication.
+- Open provider and custom-manifest files defensively: bound file sizes and recursion, reject invalid encodings where required, detect symlink/path traversal, and never follow a discovered path into privileged or unrelated user data implicitly.
+- Construct child processes with typed executable/argument arrays and a minimal documented environment. Shell evaluation is forbidden in provider metadata, custom manifests, artwork paths, and frontend descriptors.
+- Redact credentials, authorization headers, tokens, machine identifiers, and personally identifying paths from default diagnostics. A user-requested support bundle must preview its contents before export.
+- Mutating operations use atomic writes, restrictive permissions, locking or compare-and-swap behavior, and recoverable backups where the project owns the file. Read-only adapters never repair provider state silently.
diff --git a/docs/spec/03_PROVIDERS_SESSIONS_AND_INPUT.md b/docs/spec/03_PROVIDERS_SESSIONS_AND_INPUT.md
new file mode 100644
index 0000000..ce6c2d2
--- /dev/null
+++ b/docs/spec/03_PROVIDERS_SESSIONS_AND_INPUT.md
@@ -0,0 +1,121 @@
+## 7. Provider strategy
+
+Provider work is incremental. Discovery and parsing, normalization, launch-plan generation, and real execution are separate milestones for each provider. Completing a parser does not authorize beginning execution support, and beginning one provider does not authorize broad parallel implementation of the others.
+
+Each provider adapter must have fixture-based parser tests, normalized-contract tests, isolated integration tests, and explicit real-system acceptance checks. Initial fixtures must include malformed, missing, duplicate, moved, unmounted, and unusual-path cases where relevant. Provider discovery must be read-only unless a separately approved management operation explicitly requires mutation.
+
+**Steam.** Parse app manifests and library folders; launch by App ID. Preserve Steam's management of Proton and runtime containers. Assume the Steam client is required for ordinary Steamworks/DRM titles and start it silently when needed. Direct executable launch is allowed only for confirmed DRM-free cases and must not silently discard Steamworks, cloud, multiplayer, overlay, or controller behavior. Steam has no supported lightweight service-only client, so unsupported browser-process surgery is not a project dependency.
+
+**Lutris.** Use its documented `--list-games --json` discovery output and `lutris:rungame/` or `lutris:rungameid/` launch URIs, validated against the packaged version. Treat Lutris as owner of runner and prefix configuration. Its numeric IDs are machine-local discovery handles, not stable public game identities; store the adapter's persistent installation UUID and re-resolve the current local ID before launch. The optional `--output-script` path may aid diagnostics but must not become the default because it can bypass client-owned accounting or lifecycle behavior.
+
+**Heroic and its providers.** Treat Heroic as an optional graphical management interface rather than the mandatory execution backend. Version 1 treats Epic, GOG, and Amazon as separate capability targets, corresponding upstream to Legendary, GOGDL, and Nile respectively. Heroic currently uses its own Legendary fork, so compatibility with standalone upstream Legendary or Heroic-owned state must be demonstrated rather than assumed. Where reliable, provider adapters may call a validated helper without starting Heroic's Electron UI. Each adapter must preserve store-qualified identities, advertise its actual capabilities, and respect ownership of credentials, Wine prefixes, per-game options, cloud saves, and configuration. Sharing Heroic state or reproducing Heroic launch behavior requires prototype validation; direct parsing of unstable Heroic internals remains provisional and isolated. Heroic and helper packaging is resolved through the phase 0 source inventory because Heroic is not an official Arch repository package; release profiles may use only reviewed, pinned, project-built packages or verified upstream artifacts, never an arbitrary live AUR install.
+
+**UMU runtime.** Provide a first-class Proton execution path outside Steam and for custom Windows games. UMU is a runtime backend, not a provider adapter: it does not supply authoritative library discovery, and its use must not replace the game's store-qualified or custom-manifest identity. Launch plans record the resolved `GAMEID`, `STORE`, prefix, Proton selection, executable, and arguments. Because UMU can automatically download its Proton/runtime payloads, packaging must define managed cache locations, authenticated or checksum-verified acquisition where upstream supports it, explicit prefetch/update operations, and an offline failure mode; an ordinary game launch must never disguise a large first-run download as a hung game.
+
+**Native.** Discover explicitly approved desktop entries and user manifests; do not blindly ingest every `Exec=` entry on the system. Parse Desktop Entry field codes without a shell, retain provenance, and launch executables with typed arguments.
+
+**Vendor launchers — post-v1.** After version 1, add Battle.net, EA App, Ubisoft Connect, Rockstar, and similar clients through individually tested Lutris or managed UMU/Wine-prefix integrations. The shared managed-prefix architecture may be designed earlier, but vendor compatibility does not block version 1.
+
+## 8. Graphics and session model
+
+### 8.1 Persistent session shell
+
+- Normal gaming mode starts one persistent minimal stacking compositor with Wayland/Xwayland support; Xorg remains a compatibility fallback.
+- The default visible application is a fullscreen terminal, making the system appear and behave CLI-first without repeatedly creating graphical environments.
+- The compositor supplies only required window management: focus, maximize/fullscreen, application switching, dialogs, multi-monitor placement, and optional dedicated workspaces.
+- A general stacking compositor is preferred for the session shell because Steam, Heroic, dialogs, terminals, frontends, and authentication windows must coexist. Labwc is the leading prototype candidate because it provides lightweight Wayland stacking and Xwayland support without a desktop environment; it remains replaceable until Steam, Heroic, Lutris, NVIDIA, portals, multi-monitor behavior, and nested Gamescope pass prototype testing.
+- Gamescope remains available as a per-game or nested optimization layer where it is beneficial; it is not assumed to be the general multi-window desktop shell.
+- ChimeraOS `gamescope-session` is reference material and a possible reusable base for dedicated Steam-like or controller-frontend sessions. It is not the Lean or Ready multi-window shell because arbitrary multi-window clients in embedded Gamescope require Steam-specific window-property behavior.
+
+### 8.2 Initial application and return behavior
+
+- The session may initially show the fullscreen terminal, Steam Big Picture, another configured frontend, or a user-supplied command. Pegasus becomes the reference configured frontend after version 1.
+- When a launcher or frontend exits, configurable behavior may return to the terminal, restart the selected frontend, or end the session.
+- Closing a game normally reveals the previous launcher, frontend, or terminal rather than tearing down the graphical foundation.
+- Required plumbing may include PipeWire/WirePlumber, D-Bus, XDG portals, Polkit agent, file picker, fonts, controller services, Bluetooth, and Xwayland. Traditional desktop furniture is excluded unless explicitly installed.
+
+### 8.3 Session ownership and login
+
+- The graphical-session prototype defines logind seat/TTY ownership, user D-Bus startup, compositor environment propagation, and a project systemd user target in the per-user manager. Session services declare `PartOf=graphical-session.target`; the login/session launcher owns the compositor process and stops the target when that compositor session ends.
+- Graphical services stop with the graphical session instead of surviving accidentally in the user manager. Tests cover logout, compositor crash, failed initial shell, repeated restart, and switching to the TTY recovery target.
+- Recovery mode bypasses graphical autostart and avoids restart loops when the compositor or initial application fails.
+- The exact display manager, greetd/autologin mechanism, or direct-login design remains open, but its contract is resolved during the session proof rather than postponed to ISO construction.
+
+### 8.4 Runtime profiles
+
+| **Profile** | **Default behavior** |
+|-------------|----------------------|
+| Lean | Start the graphical foundation and fullscreen terminal; launch provider clients and GUIs only when required. This is the default. |
+| Ready | Start the same foundation and keep user-selected launchers such as Steam or Heroic resident, usually hidden or on dedicated workspaces. |
+| Frontend | Start Steam Big Picture or another selected frontend as the initial shell; retain terminal access through a shortcut or controller action. Pegasus becomes the reference option after version 1. |
+| Custom | Apply individually selected initial application, autostart, residency, hiding, and exit policies. |
+| TTY | Start no graphical session; provide recovery, diagnostics, and deliberate console-only operation. |
+
+Profile selection and per-launcher residency are runtime configuration, not installation-only choices. Installer questions and presentation are intentionally deferred for a later design discussion.
+
+### 8.5 Launcher lifecycle and switching
+
+- `kiln provider show ` starts the launcher when absent. Focusing an existing Wayland window is exposed only when the selected compositor/session-control adapter provides a tested mechanism; Labwc deliberately has no D-Bus or custom IPC, so the command must return a structured `focus-unsupported` result rather than pretending success. Compositor keybindings remain the baseline switching path.
+- Users can switch among the terminal, provider interfaces, configured frontends, and the running game using compositor shortcuts, a controller-accessible session action, supported CLI focus commands, or frontend actions. The session proof must choose and test the controller path; candidates are Steam Input desktop mappings, a narrowly scoped project input service, or InputPlumber if prototype evidence makes it necessary.
+- Steam and Heroic may autostart and remain resident in Ready or Custom profiles.
+- Lean may start Steam silently on the first Steam launch and retain it afterward. Provider clients are not automatically stopped after play; explicit safe exit or a later optional idle policy may be added only where the provider exposes reliable behavior.
+- Heroic-backed games should use supported CLI backends without the Heroic GUI where validated; opening Heroic remains available for browsing, installation, authentication, and configuration.
+- Post-v1 vendor launchers stay lazy by default unless required by a running title or explicitly configured as resident.
+- Minimizing or hiding a launcher is preferred to risky process manipulation. Game scopes may receive higher CPU and I/O priority, but process-priority and resource-control policies require measurement and compatibility testing.
+
+### 8.6 Game lifecycle tracking
+
+- Track the game rather than assuming the provider-launch command remains attached to it.
+- Prefer an owned process or systemd scope; otherwise use provider-reported state or conservative process correlation.
+- Report lifecycle confidence as `tracked`, `provider-reported`, `probable`, or `unknown`.
+- Use lifecycle state for sleep inhibition, optional background-work suppression, running status, logging, and restoration of temporary settings. GameMode activation is related but separate: the request must be held by a real GameMode client or injected wrapper for the lifetime of the game, not inferred solely from tracker confidence. Direct launches may use `gamemoderun`; Steam/provider launches require tested provider launch options, native integration, or an explicit backend-held client registration.
+- When exact tracking is unavailable, degrade safely without leaving permanent performance overrides active.
+- A force-stop command is not a version 1 requirement. It may be added later when the existing tracking mechanism makes it safe and simple.
+
+### 8.7 Fallbacks
+
+- Xorg fallback for games, launchers, or driver combinations that fail under the preferred Wayland compositor or Gamescope.
+- Safe mode that disables optional overlays, tuning, and nonessential environment overrides.
+- Direct provider launch for diagnosing failures in the unified backend.
+- TTY-only target for recovery when the graphical shell cannot start.
+
+## 9. Controller and input requirements
+
+USB and Bluetooth controllers are release-blocking functionality. The input design must cover kernel recognition, user permissions, SDL visibility, Steam Input, hotplugging, reconnection, and device-specific features where supported.
+
+### 9.1 Required device classes
+
+- Xbox and XInput-compatible controllers
+- DualShock and DualSense controllers
+- Nintendo/Switch-compatible controllers
+- Generic USB HID gamepads
+- Steam Input–managed devices
+
+### 9.2 Controller tooling
+
+```text
+kiln controller list
+kiln controller scan
+kiln controller pair
+kiln controller connect
+kiln controller forget
+kiln controller test
+kiln controller battery
+kiln controller manage
+```
+
+- `kiln controller manage` opens Bluetui as the standard interactive BlueZ TUI for discovery, pairing, trust, connection, and removal. Project-owned commands remain responsible for stable machine-readable output, automation, controller-specific tests, battery reporting, and diagnostics rather than duplicating Bluetui's interactive interface.
+- Blueman is the optional desktop-neutral GTK Bluetooth manager for a future or user-installed desktop experience. GNOME and KDE Bluetooth panels may be supplied by their respective desktop profiles but are not base dependencies.
+- InputPlumber is a post-v1-leaning optional prototype for controller-driven shell control, advanced remapping, virtual-device presentation, and overlay input. It is not a version 1 baseline dependency unless testing proves a release-blocking need. Evaluation must specifically test duplicate physical/virtual devices and interaction with Steam Input.
+- Bluetui is an interactive manager, not a stable automation API. Automated pairing diagnostics and state changes use BlueZ D-Bus interfaces through project-owned typed code; `bluetoothctl` may remain a recovery/diagnostic fallback.
+
+### 9.3 Acceptance checks
+
+- A paired Bluetooth controller reconnects after reboot without opening a desktop settings panel.
+- A USB controller can be connected before or during a game session.
+- A controller can invoke the documented recovery/session-switch action without depending on a running game or a provider overlay; the keyboard equivalent remains available.
+- SDL and Steam recognize expected buttons and axes under both Gamescope and fallback sessions.
+- Controller permissions do not require running games or launchers as root.
+- Battery level, rumble, gyro, touchpad, LEDs, and advanced functions are reported or supported when the relevant driver exposes them.
+
+Controller diagnostics distinguish `supported`, `unsupported`, `unavailable`, `permission-denied`, `managed-by-steam-input`, and `unknown`. Pairing design covers Bluetooth agents and passkey/PIN prompts without a desktop settings panel, multiple-controller assignment, duplicate raw/virtual devices, and a keyboard/controller recovery action when a frontend captures input.
diff --git a/docs/spec/04_BASE_PERFORMANCE_RELIABILITY.md b/docs/spec/04_BASE_PERFORMANCE_RELIABILITY.md
new file mode 100644
index 0000000..4cb1880
--- /dev/null
+++ b/docs/spec/04_BASE_PERFORMANCE_RELIABILITY.md
@@ -0,0 +1,86 @@
+## 10. Base operating system
+
+Version 1 targets x86_64 systems booted through UEFI. Legacy BIOS and other CPU architectures are not release-tested. AMD and NVIDIA graphics profiles are release-blocking; Intel graphics remains best-effort until representative hardware is available for the same session, game, update, and recovery matrix.
+
+| **Core** | Arch base, systemd, CPU microcode, zsh, NetworkManager, synchronized time/keyring initialization, and official `multilib`; bootloader and firmware support boundary remain to be selected |
+|-----------------|------------------------------------------------------------------------------------------------|
+| **Kernel** | Regular Arch `linux` is the reference kernel; `linux-lts` may be retained as a recovery fallback |
+| **Audio** | PipeWire, WirePlumber, ALSA compatibility, Bluetooth audio components where needed |
+| **Graphics** | Vulkan stack, 32-bit libraries, vendor-specific AMD/NVIDIA/Intel profile |
+| **Gaming** | Steam, Wine, Winetricks, UMU, Proton management, Lutris, Heroic, Gamescope, GameMode, MangoHud, MangoApp support for Gamescope, and optional ProtonPlus maintenance GUI |
+| **Input** | BlueZ, Bluetui, udev rules, SDL tools, kernel HID drivers, optional Blueman GUI, optional device-specific drivers, and post-v1-leaning InputPlumber evaluation |
+| **GUI support** | Minimal compositor, Xwayland, portals, Polkit agent, fonts, file picker |
+| **Operations** | Logging, diagnostics, package transaction history, recovery entries |
+
+Reproducibility initially means recorded repository state, exact package versions and hashes, project versions, configuration, and build inputs can reconstruct an equivalent system. ISO and package builds record their toolchain and archiso inputs. Bit-for-bit reproducible artifacts and independent rebuild verification are later hardening goals and are not claimed until tested.
+
+## 11. Performance strategy
+
+### 11.1 Definition of performance
+
+Performance means consistent frametimes, low latency, stable clocks, reliable input, and minimal interference. Average FPS alone is not an adequate success metric.
+
+### 11.2 Dynamic optimization
+
+- Activate GameMode only through a request whose lifetime is tied to actual game execution; do not toggle it from an uncertain process heuristic.
+- Use MangoApp for the Gamescope HUD path; upstream does not support ordinary MangoHud inside Gamescope. Use MangoHud directly only for non-Gamescope Vulkan/OpenGL launches where validated.
+- Select an appropriate CPU power profile during play and restore it afterward only through a tested existing interface such as GameMode or power-profiles-daemon. Any privileged integration is a narrow static system service/policy that accepts typed bounded requests and never parses provider or game metadata as root.
+- Apply GPU- and game-specific environment settings through explicit profiles.
+- Inhibit sleep and disruptive scheduled work while a game is active.
+- Avoid permanent maximum-performance settings unless measurement justifies them.
+
+### 11.3 Benchmarking
+
+| **Average FPS** | Throughput; never used alone |
+|----------------------------|-----------------------------------------------|
+| **1% and 0.1% lows** | Short and severe stalls |
+| **Frametime distribution** | Smoothness and pacing |
+| **Input latency** | Responsiveness where measurable |
+| **CPU/GPU utilization** | Bottleneck and scheduling evidence |
+| **RAM/VRAM** | Capacity pressure and background overhead |
+| **Power and clocks** | Thermal or power-management behavior |
+| **Launch time** | Provider cold-start cost, session-shell overhead, and lazy-launch latency |
+
+## 12. Reliability, recovery, privacy, and security
+
+- Retain at least two bootable kernels.
+- Preserve or recover a known-good NVIDIA driver/kernel pairing where practical.
+- Keep game libraries separate from replaceable system state where possible.
+- The initial bare-metal reference is the project's Ryzen 9 7900X3D and RTX 5070 desktop, with the project OS installed to a dedicated external USB drive. Storage-sensitive results must identify the USB enclosure, interface, and drive and must not be generalized as CPU/GPU or distro overhead when external storage is the bottleneck.
+- Provide package transaction logs and an optional Btrfs recovery profile using Snapper plus pacman pre/post transaction hooks; retain a filesystem-neutral path.
+- Collect per-launch logs without capturing authentication secrets or unnecessary personal data.
+- Store launcher tokens only through their provider's normal mechanism; do not duplicate credentials in the unified cache.
+- Require no telemetry from project-owned components.
+- Provide direct provider and safe-mode paths when abstraction fails.
+
+### 12.1 Update policy
+
+- Use the normal signed Arch repositories and ordinary complete `pacman -Syu` upgrades; do not maintain a delayed or separately tested Arch package channel.
+- Partial upgrades are unsupported and must not be presented as a recovery or compatibility strategy.
+- Keep project-owned packages independently updateable through the project's signed package repository so integration fixes can be delivered without replacing Arch's update model.
+- Minimize reliance on undocumented provider internals and test against current upstream packages during development, but do not claim that the project can prevent every upstream regression.
+- Detect and warn about known incompatible package, driver, kernel, or project-version combinations where practical.
+- Retain recovery entries, package transaction history, and straightforward downgrade guidance. Snapshots remain optional; for the Btrfs recovery profile, use Snapper and pacman transaction hooks rather than project-owned snapshot machinery. Boot-menu integration is selected only after the bootloader is chosen and must be tested independently from snapshot creation.
+- A future distributable ISO is an installation convenience built from the proven base-Arch configuration, not the initial development target or a separate frozen distribution branch.
+
+### 12.2 Supply-chain and privilege policy
+
+- Sign project repositories and public release artifacts and publish verification instructions.
+- Track package source, version, checksum/signature, license, and required notices; generate an SBOM for public releases.
+- Pin security and license audit tools in the development source inventory as well as configuring their policies. Exact-toolchain verification must inspect the active compiler because distro-provided Rust binaries may not honor `rust-toolchain.toml`.
+- Keep dependency-license allowlists limited to licenses actually present and reviewed. New dependencies require an explicit license-policy change; speculative broad allowlists are not accepted.
+- Prefer official Arch packages. Project-supplied AUR/community packages require pinned build recipes, review, isolated builds, and project-signed binaries; arbitrary user-installed AUR packages remain outside project guarantees.
+- Validate provenance and checksums/signatures for externally downloaded Proton, UMU runtime payloads, and provider helpers where upstream provides them. Prefetchable runtime assets must have explicit cache, update, offline, and failure behavior.
+- Offer ProtonPlus as an optional graphical maintenance tool for user-managed Proton, Wine, DXVK, and VKD3D variants. The backend may detect compatible tools it installs, but ProtonPlus does not replace project-owned runtime resolution, validation, pinning, cache provenance, prefetch, or offline contracts.
+- Ordinary discovery and launches run unprivileged. Installer/system-integration privileges are isolated from parsers, frontends, provider clients, artwork handling, and games.
+- Project-owned v1 components open no TCP/UDP listening sockets. Any later local service defaults to a per-user Unix socket under `XDG_RUNTIME_DIR` with owner-only permissions, peer-credential checks, request limits, and no network bridge unless remote control becomes a separately approved feature.
+- Treat manifests, custom launch definitions, artwork paths, and generated frontend commands as untrusted input. Validate size and paths and use argument-safe process execution rather than interpolated shell commands.
+- Maintain a machine-readable package/source inventory before packaging begins. It records official-repository packages, reviewed project builds, verified upstream binaries, transient build dependencies, bundled helper versions, signatures/hashes, licenses, and the responsible update path. Live AUR resolution is never part of an installation or update transaction.
+- Define a small threat model before phase 2 covering malicious provider metadata, hostile game directories, symlink/path traversal, command and environment injection, local socket impersonation, credential leakage in logs, unsafe support bundles, and privilege-boundary mistakes.
+
+### 12.3 Project licensing
+
+- Project-owned software is licensed under **GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later)**.
+- Commercial use and sale remain permitted. Conveying covered binaries requires the corresponding source under the AGPL, and a modified version that supports remote network interaction must offer its corresponding source to users interacting with it over the network. Running an unmodified copy as a network service does not by itself create a new modification-specific source obligation.
+- Third-party components retain their own licenses. Packaging, integration, and distribution work must track license compatibility and required notices rather than assuming the project license overrides dependencies.
+- Documentation and non-software assets may receive appropriate compatible licenses later; their licensing must be explicit before public release.
diff --git a/docs/spec/05_FRONTENDS_AND_SESSION_POLICIES.md b/docs/spec/05_FRONTENDS_AND_SESSION_POLICIES.md
new file mode 100644
index 0000000..af43675
--- /dev/null
+++ b/docs/spec/05_FRONTENDS_AND_SESSION_POLICIES.md
@@ -0,0 +1,67 @@
+## 13. Graphical session policies and frontends
+
+A minimal graphical session is the normal runtime foundation, while its default visible interface remains the fullscreen terminal. Graphical frontends are optional clients of the same unified backend. Users must be able to select the initial shell, profile, autostart behavior, and launcher residency after installation through simple CLI commands and eventually through graphical settings.
+
+Here, "frontend" means a project-integrated catalogue client such as Pegasus or a future first-party UI. Steam Big Picture, Heroic, and Lutris are provider-native interfaces: users may open them and use their native launch behavior, but they are not allowed to become the authoritative implementation behind `kiln` or other project frontends.
+
+Likely session policies are:
+
+| **Policy** | **Behavior** |
+|------------|--------------|
+| Terminal | Start the minimal graphical session and show the fullscreen terminal. |
+| Manual | Start the terminal shell and open the selected frontend only when requested. |
+| Automatic | Start the selected graphical frontend as the initial application through a systemd user target. |
+| Last used | Optional later policy that restores the previous session choice. |
+| TTY | Start no graphical session; use the real console recovery path. |
+
+These policies should be implemented with ordinary systemd user services or targets rather than a second project-specific startup system.
+
+### 13.1 Pegasus reference integration
+
+> **Release scope:** This integration is the first planned frontend milestone after version 1 and does not block the version 1 release.
+
+Pegasus Frontend is the preferred first reference frontend because it is FOSS, controller-aware, themeable, cross-platform, and already supports metadata-defined launch commands. Initial integration should use unmodified upstream Pegasus:
+
+```text
+Pegasus -> kiln launch -> unified core -> provider adapter
+CLI -> kiln launch -> unified core -> provider adapter
+```
+
+`kiln frontend configure pegasus` should create the necessary integration, while `kiln frontend sync pegasus` should export normalized library metadata and artwork references. Generated Pegasus entries must call `kiln launch ` rather than embedding provider-specific Steam, Heroic, Lutris, Wine, or emulator commands.
+
+Because Pegasus expects launchable file entries, the adapter generates inert per-installation descriptor files. Pegasus passes the selected descriptor to a dedicated `kiln frontend launch-descriptor` operation, which validates and resolves it to the stable installation identity. Titles and provider metadata are never interpolated into `sh -c`. Sync behavior must define whether Pegasus reloads metadata safely or requires a controlled frontend restart.
+
+Pegasus may continue to support direct launch commands for advanced use and diagnostics, but bypassing the backend is not the project default.
+
+### 13.2 OpenGamepadUI evaluation
+
+After version 1, evaluate OpenGamepadUI as an additional controller-native frontend and overlay candidate alongside Pegasus. Its active development, plugin architecture, multiple game sources, and InputPlumber integration are relevant, but its upstream early-development warning prevents making it a version 1 dependency or replacing Pegasus before prototype evidence exists.
+
+An OpenGamepadUI integration must consume the same stable backend identities and launch behavior as other clients. Its internal catalog, provider plugins, input daemon, or artwork state must not become authoritative for discovery, configuration ownership, or launch policy. Evaluation should determine whether its plugin or D-Bus boundaries can call the backend cleanly and whether its overlay/input features justify optional InputPlumber integration.
+
+### 13.3 Fork and custom-frontend policy
+
+Do not fork Pegasus or build a first-party graphical frontend during the initial implementation. Use the upstream application to expose concrete integration limitations before accepting either maintenance burden.
+
+The preferred escalation order is:
+
+1. External adapter using upstream Pegasus behavior.
+2. Propose a generic data-source, plugin, or structured-launch integration upstream.
+3. Contribute broadly useful changes to Pegasus upstream.
+4. Maintain a small downstream patch set if the required changes are narrow and project-specific.
+5. Fork Pegasus only when deep necessary changes cannot reasonably be accepted or isolated.
+6. Build a first-party frontend when the project needs a native OS control surface rather than only a game-library browser.
+
+A future first-party frontend may be justified for live provider state, install/update controls, launch progress, structured errors, OS settings, compatibility profiles, Gamescope/GameMode/MangoHud/MangoApp controls, and seamless desktop/controller layouts. It must remain another client of the shared backend.
+
+### 13.4 Provider-interface behavior
+
+- Steam may be optionally resident for faster launches and gamepad UI integration; Ready and Custom profiles support autostarting it hidden or visible.
+- When explicitly opened for a controller-oriented session, Steam should start in Big Picture Mode; desktop sessions should use the normal Steam interface.
+- Do not infer controller mode merely because Pegasus is running; the caller or selected session profile should state the intended mode.
+- Heroic and Lutris default to lazy startup in Lean but may remain resident in Ready or Custom.
+- Post-v1 vendor launchers should not remain resident by default.
+- The unified library should remain usable without any provider GUI open.
+- Window-focus requests are capability-based. Session-wide compositor keybindings are the v1 baseline; a frontend or CLI must not assume Labwc exposes programmatic focus control, because upstream intentionally provides no D-Bus or custom IPC.
+
+> **Deferred decision:** The final compositor selection, display-manager/login mechanism, installer questions and presets, Pegasus theme, downstream patch set, OpenGamepadUI integration method, and any first-party frontend toolkit remain unselected. Labwc is the leading compositor prototype, not yet a locked dependency.
diff --git a/docs/spec/06_DEVELOPMENT_ROADMAP_AND_ACCEPTANCE.md b/docs/spec/06_DEVELOPMENT_ROADMAP_AND_ACCEPTANCE.md
new file mode 100644
index 0000000..c1a177d
--- /dev/null
+++ b/docs/spec/06_DEVELOPMENT_ROADMAP_AND_ACCEPTANCE.md
@@ -0,0 +1,107 @@
+## 14. Development and validation strategy
+
+Development will use a layered workflow: fast, repeatable testing in virtual machines, followed by targeted bare-metal validation for behavior that virtualization cannot represent accurately. This keeps iteration safe without pretending a virtual GPU can prove gaming performance.
+
+### 14.1 Primary development environment
+
+- QEMU/KVM managed through libvirt is the primary environment for boot, installer, service, networking, package, and recovery testing.
+- A powered-off libvirt guest consumes no guest RAM or CPU; only negligible host management services remain active.
+- ISO and root-filesystem builds may run directly on the host, in a container, or in a dedicated build VM, provided the process remains reproducible.
+- VirtualBox is not a primary project dependency. It may be used for an additional compatibility check, but it offers no useful substitute for bare-metal graphics testing.
+- GPU passthrough is optional and must not become a prerequisite for development or release validation.
+
+### 14.2 Validation stages
+
+| **Stage** | **Environment** | **Purpose** |
+|-------------|-------------------------------------|------------------------------------------------------------------------------------------------------|
+| Build | Host, container, or build VM | Produce the package set, root filesystem, and ISO reproducibly. |
+| Fast boot | Disposable libvirt VM | Validate the bootloader, initramfs, installer flow, networking, services, and TTY behavior. |
+| Destructive | Snapshot-backed libvirt VM | Exercise failed upgrades, rollback, recovery, repartitioning, and installer edge cases safely. |
+| Hardware | Dedicated spare SSD or test machine | Validate GPU drivers, Bluetooth, controllers, audio, displays, suspend, and real device permissions. |
+| Performance | Bare metal | Measure frame pacing, latency, Gamescope, GameMode, Proton behavior, thermals, and system overhead. |
+
+### 14.3 Bare-metal isolation and safety
+
+- Do not use the primary EndeavourOS installation as the distro install target during routine development.
+- Prefer a dedicated physical SSD for test installations and select it through UEFI, keeping production and test bootloaders isolated.
+- The first reference install uses a dedicated external USB drive on the Ryzen 9 7900X3D/RTX 5070 desktop. Installer tests must resolve that exact device by stable identity and display model, capacity, transport, and destructive target confirmation; never select it through changing `/dev/sdX` order alone.
+- Run early installer tests only against disposable virtual disks or physical disks whose contents may be destroyed.
+- Keep game libraries separate from replaceable system state where practical so repeated installs do not require repeated downloads.
+- Automate VM creation and smoke tests as the project matures; a clean guest should be reproducible from source rather than maintained as a precious snowflake.
+
+### 14.4 Incremental development and test gates
+
+- Implement one vertical capability at a time and verify it before starting the next dependent capability.
+- Avoid broad simultaneous implementation across providers or system layers; narrow failures are easier to diagnose and revert.
+- Every task must state its scope, exclusions, affected components, acceptance criteria, and exact verification commands before implementation begins.
+- A capability advances through four gates: unit tests for pure logic and parsers; contract tests for schemas and adapter behavior; isolated integration tests using fixtures or temporary state; and real-system or VM acceptance tests where applicable.
+- Work may proceed in parallel only when tasks are demonstrably independent and do not edit the same files or depend on unsettled contracts.
+- Failures at any gate block the next dependent phase. Exceptions require an explicit documented decision rather than silent scope expansion.
+- Treat the workspace MSRV and the reviewed development toolchain as separate controls: the MSRV describes compatible source, while local and CI gates verify the exact active compiler selected for reproducible development.
+- Every internal path dependency declares an exact compatible version as well as its path. Dependency changes update the lockfile, source inventory where applicable, license policy, and advisory/license/source audit evidence in the same task.
+- Do not preapprove dependency licenses that are not present. Add a license to the allowlist only with the reviewed dependency that requires it.
+- Each real-system gate records the exact package versions, hardware/driver/kernel tuple, fixture or test account, commands, expected result, observed result, logs, and cleanup. "Launch one game" without a reproducible evidence record is not an acceptance test.
+- Networked-provider tests use dedicated non-primary test accounts where provider terms and practical setup permit. Fixtures contain no live tokens, personal library dumps, or redistributable proprietary content.
+
+### 14.5 Work Mode and local execution split
+
+- ChatGPT Work Mode is used for specification maintenance, architecture, schemas, fixtures, task definitions, lightweight scaffolding, reviews, and handoff preparation.
+- Compilation, dependency downloads, full Rust test suites, Clippy, Arch package builds, VM execution, launcher inspection, game launching, graphical-session tests, controller tests, Archiso generation, and performance benchmarks run locally through Codex CLI unless a later lightweight check is clearly cheaper here.
+- Work Mode tasks must avoid unnecessary CPU, RAM, disk, and dependency use. Resource-heavy validation belongs on the user's desktop or disposable VM, where failures and resource pressure are observable.
+- Phase 0 completion is the default handoff point for implementation to local Codex CLI. Keep Work Mode involved for specification maintenance, architecture and schema review, decision clarification, and evidence-backed corrections; use the repository-root `AGENTS.md` and bounded handoff briefs to preserve those constraints locally.
+
+## 15. Delivery roadmap
+
+| **Phase** | **Focus** | **Exit condition** |
+|-----------|-----------------|------------------------------------------------------------------------------------------------|
+| 0 | Repository and evidence baseline | Create the Rust workspace and component boundaries using the approved temporary, repository-local Kiln family; establish a rename manifest and automated placeholder scan; pin the toolchain and lockfile; configure formatting, linting, tests, CI, dependency/license/security audits, release/version policy, ADRs, fixture rules, threat model, package/source inventory, test-evidence template, requirement-to-test traceability matrix, and supported-platform decision record. Final collision-checked project/package/crate/executable/configuration/IPC namespaces are required before any public, published, or globally installed artifact, but do not block private implementation. No provider implementation begins before the remaining baseline passes. |
+| 1 | Contracts | Define and aggressively test versioned game/installation identity, the durable installation registry, store/adapter/configuration-owner/execution-backend separation, provider and runtime interfaces, JSON records, launch plans, lifecycle confidence, structured errors, and configuration precedence/provenance using a mock adapter. |
+| 2 | Native vertical slice | Complete native discovery, normalization, search, dry-run planning, launch execution, logging, and failure handling before beginning Steam execution. |
+| 3 | Steam discovery | Parse Steam installation and library state through read-only, fixture-driven tests; normalize installed games without launching them. |
+| 4 | Steam execution | Generate and verify Steam launch plans, then launch representative native and Proton titles through the common contract. |
+| 5 | Minimal session proof | Choose the prototype terminal and login/session mechanism; define logind seat/TTY ownership, D-Bus and systemd-user behavior; start Labwc and Xwayland, launch native and Steam/Proton games, return cleanly, and prove compositor/initial-shell failures cannot trap the user in a graphical restart loop. This proves architecture, not the complete session product. |
+| 6 | Controllers | Validate at least one Xbox-family and one PlayStation-family controller over both USB and Bluetooth, including hotplugging, reboot reconnection, structured diagnostics, BlueZ automation, and the Bluetui management path; verify optional Blueman separately and prove a controller-accessible session/recovery action without relying on a running game. Record the exact tested controller revisions before execution. |
+| 7 | Additional providers and runtimes | Add Lutris, then separate Epic/Legendary, GOG/GOGDL, and Amazon/Nile capability adapters, followed by custom Windows manifests and the UMU runtime, one at a time; each must pass its own four test gates before the next begins. Whether an adapter reuses Heroic state or owns independent helper configuration is decided by its prototype evidence, not assumed globally. |
+| 8 | Session hardening | Harden the proven compositor architecture into Lean, Ready, Frontend, Custom, and TTY policies; complete launcher switching, controller session actions, Gamescope nesting, Xorg/TTY fallbacks, audio, portals, multi-monitor behavior, permissions, cleanup, and crash recovery. Reference or reuse ChimeraOS gamescope-session only for dedicated frontend-session paths where validated. |
+| 9 | Performance | Benchmark tuning changes against minimal Arch and a conventional Arch desktop. |
+| 10 | Packaging | Create modular Arch packages and hardware profiles, including optional ProtonPlus/Blueman desktop tools and an optional Btrfs Snapper recovery profile with pacman hooks. |
+| 11 | Installer | After the base-Arch package set and configuration are stable, create an Archiso profile and an archinstall-based guided path using a maintained project profile/configuration plus a pinned local plugin or custom script only where required. Do not reimplement archinstall's storage, encryption, account, or base-install functions, and never fetch executable installer plugins from an unpinned URL. |
+| | **Version 1 release boundary** | Version 1 may ship when phases 0–11 and the version 1 acceptance criteria pass; phases 12–15 are post-v1 work. |
+| 12 | Frontend adapter | Integrate unmodified upstream Pegasus through generated metadata and backend-owned launch commands, using the session policies completed for version 1. |
+| 13 | Public API | Stabilize schemas, structured errors, compatibility policy, local IPC, events, and an example external client if real frontend needs justify a service. |
+| 14 | Future UI and input | Evaluate OpenGamepadUI, optional InputPlumber integration, upstream contributions, a small Pegasus patch set or fork, or a first-party OS frontend using evidence from the reference integrations. |
+| 15 | Vendor launchers | Add Battle.net, EA App, Ubisoft Connect, Rockstar, and similar clients individually through the managed-prefix architecture; publish tested/experimental/unsupported status rather than promising universal compatibility. |
+
+## 16. Version 1 acceptance criteria
+
+- Normal gaming mode starts a minimal graphical shell whose default visible interface is a fullscreen terminal, without starting a conventional DE.
+- Lean, Ready, Frontend, Custom, and TTY selections can be changed after installation; each starts only its declared components and survives logout/reboot according to its documented persistence policy.
+- A true TTY-only recovery target works independently of the graphical shell.
+- An installed game can be found and launched by name.
+- Steam, Lutris, native, Epic, GOG, and Amazon provider paths each discover and launch at least one representative installed title, or a store is explicitly downgraded from v1 through a recorded scope decision before release. Passing one Heroic-managed store does not stand in for the other two.
+- At least one custom Windows game launches through the UMU runtime while retaining its custom or store identity.
+- Representative USB and Bluetooth controllers work in Gamescope and fallback sessions; Bluetui can pair, trust, connect, disconnect, and forget a representative Bluetooth controller without a desktop settings panel.
+- The published controller matrix names exact representative devices and records kernel/driver, USB/Bluetooth mode, hotplug, reboot reconnection, SDL mapping, Steam Input interaction, session/recovery action, and supported advanced features; unsupported features are reported honestly.
+- The system returns to the functioning session shell after successful launch, game exit, and common launch failures without reconstructing the graphical environment.
+- Lean starts heavyweight provider interfaces only when needed; Ready can autostart and rapidly switch among at least Steam, Heroic, and the terminal.
+- Keyboard switching works on every supported compositor path. A controller can reach the terminal or recovery action even when a frontend or game captures ordinary navigation input. Programmatic focus commands return an explicit unsupported result on compositors without a tested focus API.
+- Each v1 Epic, GOG, and Amazon path demonstrates whether it can launch through a validated helper without Heroic's Electron interface; any path that still requires Heroic must report `client-required` honestly and preserve configuration ownership.
+- UMU runtime assets can be prefetched, a warm cached launch succeeds without network access, and an uncached offline launch fails promptly with a clear actionable error.
+- GameMode remains requested for the actual game lifetime in representative direct, Steam, and non-Steam provider launches; lower-confidence lifecycle tracking alone must not hold or release the request.
+- Gamescope launches use MangoApp for their supported HUD path, while fallback/non-Gamescope launches validate MangoHud separately.
+- Safe mode can bypass Gamescope overlays and optional tuning.
+- A dry-run launch plan provides enough information to reproduce and diagnose the launch.
+- Performance tests use a frozen workload, hardware/driver/kernel tuple, warm-up policy, repeated samples, variance reporting, and predeclared regression budgets. Statistically meaningful regressions beyond those budgets block the affected tuning/profile unless an explicit tradeoff decision records the benefit.
+- A clean supported installation completes an ordinary full `pacman -Syu` plus a project-package update and still boots, enters the session, discovers games, and launches the smoke-test titles. A deliberately incompatible VM transaction produces actionable diagnostics and follows the documented downgrade or optional snapshot-recovery path.
+- Supported audio and networking paths are tested from a clean install, including PipeWire/WirePlumber startup, one declared game-audio output path, NetworkManager reconnect after reboot, and offline launch behavior for cached and uncached provider/runtime cases.
+- No project component requires telemetry or root execution for ordinary game launches.
+- A clean-install listener inventory contains no undocumented project-owned TCP/UDP service; any local IPC socket has owner-only access and rejects unauthorized peers and oversized/malformed requests.
+- Game-lifetime tracking drives temporary performance settings, sleep inhibition, status, logging, and cleanup at the strongest confidence each provider permits; provider clients are not automatically closed after play.
+- Public build records identify repository state, exact package/project versions, hashes, and build inputs sufficiently to reconstruct an equivalent installation; bit-for-bit reproducibility is claimed only after independent verification.
+- Project packages and releases are signed, include source/license provenance and an SBOM, and do not execute untrusted metadata through interpolated shell commands.
+- Adversarial tests cover malformed/oversized manifests, invalid encodings, shell metacharacters, Desktop Entry field codes, environment injection, symlink/path traversal, concurrent file changes, hostile artwork paths, log redaction, and local IPC permissions where applicable.
+- The release matrix states the supported CPU architecture, firmware/boot mode, GPU/driver families, display arrangements, audio path, controller classes, and filesystem profiles. Untested combinations are labeled untested rather than implied supported.
+- The v1 matrix is explicitly x86_64/UEFI and single-local-user. AMD and NVIDIA rows are release-blocking; Intel rows are best-effort. Multi-user isolation is a documented post-v1 capability and v1 tests ensure no project state depends on a fixed username, UID, or hard-coded home directory.
+- Every Required requirement ID maps to an owning roadmap phase and at least one automated or manual evidence record; release review fails if a required item is orphaned, deferred, or covered only by prose.
+- The archinstall-based guided path installs a bootable system onto a disposable virtual disk, records its selected profile, handles a failed installation without corrupting unrelated disks, and produces the same project package/configuration state as the documented base-Arch path.
+- If the optional Btrfs recovery profile is offered at v1, its Snapper and pacman-hook snapshots, retention behavior, rollback instructions, and selected boot integration pass destructive VM tests; failure of that optional profile blocks advertising it, not the filesystem-neutral installation path.
diff --git a/docs/spec/07_RISKS_DECISIONS_AND_HISTORY.md b/docs/spec/07_RISKS_DECISIONS_AND_HISTORY.md
new file mode 100644
index 0000000..4ed5116
--- /dev/null
+++ b/docs/spec/07_RISKS_DECISIONS_AND_HISTORY.md
@@ -0,0 +1,172 @@
+## 17. Risks and mitigations
+
+| **Risk** | **Mitigation** |
+|--------------------------------------------------------|---------------------------------------------------------------------------------------------|
+| Wayland compositor or Gamescope instability, especially on NVIDIA | Maintain Xorg, TTY, and safe-mode fallbacks; test pinned driver/kernel combinations. |
+| Provider configuration changes | Keep adapters isolated, capability-based, version-tested, and replaceable. |
+| Heroic lacks a stable comprehensive CLI API | Use supported launch mechanisms where possible and treat internal parsing as provisional. |
+| Heroic store support is treated as one uniform backend | Test Epic/Legendary, GOG/GOGDL, and Amazon/Nile independently; Heroic's Legendary fork and shared state are not assumed compatible with standalone helpers. |
+| UMU performs an unexpected first-launch download | Provide explicit prefetch/update commands, managed caches, verified acquisition where available, offline tests, progress reporting, and prompt failure when uncached offline. |
+| GameMode is tied to an unreliable launch or tracking PID | Keep a real GameMode client/wrapper request alive for the game; test Steam and provider handoffs instead of toggling from heuristic state. |
+| MangoHud is injected into Gamescope as though it were supported | Use MangoApp with Gamescope and reserve ordinary MangoHud for validated non-Gamescope launches. |
+| CLI backend diverges from Heroic per-game configuration | Define ownership boundaries, compare generated launch plans, and require provider-specific integration tests. |
+| Resident launchers consume resources without benefit | Keep Lean as default, hide inactive UIs, pause downloads during play where supported, and benchmark actual frametime impact. |
+| Optimization folklore causes regressions | Require benchmarks and remove changes that lack measurable value. |
+| Arch rolling updates break the appliance | Use normal complete Arch upgrades without a separate delayed channel; minimize fragile integration, publish project fixes, detect known incompatibilities, and retain recovery entries, logs, downgrade guidance, and optional snapshots. |
+| Scope expands into a universal store manager | Limit version 1 to discovery, information, launch, scan, and diagnostics. |
+| Minimal GUI omits hidden dependencies | Test authentication, file pickers, portals, fonts, Polkit, audio, and multiarch explicitly. |
+| Pegasus integration becomes project-specific glue | Generate its metadata through a dedicated adapter and keep all provider logic in the shared core. |
+| Premature frontend work delays the backend | Keep Pegasus, OpenGamepadUI integration, forks, and a first-party GUI outside version 1 implementation scope. |
+| Public API freezes weak early assumptions | Version contracts explicitly; stabilize only operations proven by the CLI and reference frontend. |
+| Premature repository splitting creates coordination overhead | Keep explicit crate and component boundaries in one repository; extract only independently useful, stable components with preserved history. |
+| Broad implementation makes failures difficult to isolate | Enforce narrow vertical tasks and four test gates before dependent work begins. |
+| Temporary codename leaks into public compatibility surfaces | Centralize branding, prefer functional internal identifiers, maintain a rename checklist, and scan before stable release. |
+| Work Mode resource limits obscure failures or waste usage | Reserve compilation, large tests, VM work, dependency downloads, and performance validation for local Codex CLI. |
+| Provider launch commands detach from the actual game | Track owned scopes when possible; otherwise use provider state or conservative correlation and report confidence explicitly. |
+| Store identity, installation manager, and runtime are conflated | Model game identity, installation UUID, configuration owner, execution backend, and Wine/Proton/UMU runtime separately. |
+| Untrusted provider or frontend metadata becomes a shell command | Use typed arguments and validated descriptor files; never interpolate titles or metadata into `sh -c`. |
+| Upstream and community packages expand supply-chain risk | Prefer official packages; pin, review, isolate, sign, inventory, and publish provenance for project-supplied community builds. |
+| Optional reused tools become accidental core dependencies | Keep Blueman, ProtonPlus, InputPlumber, snapshot recovery, and post-v1 frontends behind explicit profiles or capability checks; preserve direct diagnostic and filesystem-neutral paths. |
+| Labwc cannot satisfy programmatic window-focus assumptions | Treat focus as a session-adapter capability, keep compositor keybindings as the baseline, and report unsupported focus requests explicitly; upstream intentionally exposes no D-Bus or custom IPC. |
+| AUR or bundled launcher packages silently bypass release controls | Maintain a reviewed package/source inventory, build and sign pinned artifacts in isolation, and never resolve live AUR content during installation or update. |
+| Malicious or corrupted provider data crosses a privilege boundary | Apply file-size/path/symlink limits, argument-safe execution, XDG confinement, redaction, atomic writes, and adversarial fixtures; keep parsers and games unprivileged. |
+| Real provider tests leak personal accounts or proprietary data into fixtures | Use dedicated test accounts where practical, sanitize evidence, forbid live tokens and personal library dumps in the repository, and document provider-specific test constraints. |
+| Temporary Kiln names collide with existing software, leak into stable surfaces, or drift away from the final project brand | Keep `kiln`, `kiln-core`, and related labels repository-local; maintain a rename manifest and automated scan; select the related product and technical naming system before anything is published or globally installed. |
+
+## 18. Open questions
+
+- What final public project name and related technical naming system should replace Project Kiln and the temporary `kiln`/`kiln-*` family? This is intentionally deferred and does not block private implementation, but must be resolved and collision-checked before any package, crate, global executable, configuration namespace, or IPC name is published or installed.
+- Does Labwc pass the session prototype on AMD, Intel, and NVIDIA with Steam, Heroic, Lutris, portals, multi-monitor layouts, and nested Gamescope; which failures trigger Xorg fallback or a different compositor?
+- Which representative controllers must pass the first compatibility matrix?
+- Which bootloader and boot-menu integration should accompany the optional Btrfs/Snapper recovery profile?
+- Which vendor launcher should be the first post-v1 managed-prefix integration: Battle.net, EA App, Ubisoft Connect, Rockstar, or another?
+- Which terminal emulator should be the phase 5 reference after measuring startup, Wayland behavior, controller/font needs, and maintenance status?
+- What concrete frontend or live-state requirement, if any, will justify a resident backend service beyond the small session supervisor?
+- Which Pegasus limitations appear during real integration, and should they be solved externally, upstream, through a small patch set, or in a first-party frontend?
+- Which Heroic settings and credentials can supported CLI backends safely reuse, and which require an explicit import or independent configuration model?
+- Post-v1 only: after profiling, should Lean offer an explicit opt-in Steam idle-exit policy? Version 1 does not close provider clients automatically.
+- What questions and presets should the eventual installer present? This is intentionally deferred to a later discussion.
+
+## 19. Decision log
+
+| **ID** | **Date** | **State** | **Decision** |
+|--------|------------|-----------|-----------------------------------------------------------------------------------------------------------|
+| D-001 | 2026-07-17 | Confirmed | Arch Linux is the base. |
+| D-002 | 2026-07-17 | Confirmed | Version 1 is CLI-first and has no conventional persistent DE. |
+| D-003 | 2026-07-17 | Confirmed | USB and Bluetooth controller support is required. |
+| D-004 | 2026-07-17 | Confirmed | Performance is the primary optimization target. |
+| D-005 | 2026-07-17 | Confirmed | The design includes a unified launcher backend suitable for future frontends. |
+| D-006 | 2026-07-17 | Confirmed | Build and validate the desired system as a base Arch package/configuration project before producing a distributable ISO as an installation convenience. |
+| D-007 | 2026-07-17 | Deferred | A persistent lightweight desktop may become an optional profile. |
+| D-008 | 2026-07-18 | Confirmed | Use QEMU/KVM through libvirt as the primary development and disposable test environment. |
+| D-009 | 2026-07-18 | Confirmed | Use dedicated spare-SSD or test-machine bare metal for hardware compatibility and performance validation. |
+| D-010 | 2026-07-18 | Confirmed | No project-integrated catalogue frontend owns discovery or normalized launch logic; the CLI and project graphical interfaces are replaceable clients of the shared backend, while provider-native clients retain native behavior. |
+| D-011 | 2026-07-18 | Confirmed | Use unmodified upstream Pegasus as the first reference controller frontend through generated metadata that calls the shared project CLI, temporarily `kiln`. |
+| D-012 | 2026-07-18 | Confirmed | Do not fork Pegasus or build a first-party graphical frontend initially; revisit either option only after the upstream integration exposes concrete limitations. |
+| D-013 | 2026-07-18 | Confirmed | Initial-shell and frontend startup policy must be changeable after installation and support terminal, manual, automatic, and TTY modes. |
+| D-014 | 2026-07-18 | Proposed | Publish a versioned local API and example client after its contracts are proven by the CLI and frontend integration. |
+| D-015 | 2026-07-18 | Confirmed | Normal gaming mode uses a persistent minimal graphical session with a fullscreen terminal as the default visible shell. |
+| D-016 | 2026-07-18 | Confirmed | Preserve a true TTY-only target for recovery and explicit console-only use. |
+| D-017 | 2026-07-18 | Confirmed | Lean is the default runtime profile; Ready supports autostarted resident launchers and rapid switching. |
+| D-018 | 2026-07-18 | Confirmed | Steam is started silently when required; unsupported attempts to split or strip the Steam client are not a project dependency. |
+| D-019 | 2026-07-18 | Confirmed | Heroic-managed providers may use validated command-line backends without Heroic's GUI, through capability-based adapters that preserve configuration ownership. |
+| D-020 | 2026-07-18 | Deferred | Installer questions and their presentation will be designed in a later discussion. |
+| D-021 | 2026-07-18 | Confirmed | Use Project Kiln as a temporary internal codename; centralize branding and keep a tested rename path for the final public name. |
+| D-022 | 2026-07-18 | Confirmed | Use Rust for project-owned backend, CLI, and provider-adapter software. |
+| D-023 | 2026-07-18 | Confirmed | Begin in one Git repository with strict workspace and crate boundaries; extract stable independently useful components later rather than using early multi-repository development or submodules. |
+| D-024 | 2026-07-18 | Confirmed | Implement one narrow vertical capability at a time and require unit, contract, isolated integration, and real-system or VM acceptance gates before dependent work proceeds. |
+| D-025 | 2026-07-18 | Confirmed | Keep heavy compilation, dependency, VM, graphical, controller, package, ISO, and performance work local in Codex CLI; use Work Mode for lightweight planning, scaffolding, fixtures, and review. |
+| D-026 | 2026-07-18 | Confirmed | License project-owned software under AGPL-3.0-or-later. |
+| D-027 | 2026-07-18 | Confirmed | Upstream Pegasus integration is the first planned reference-frontend milestone after version 1 and does not block the version 1 release. |
+| D-028 | 2026-07-18 | Confirmed | Every future spec change requires a cross-spec integrity check; unresolved conflicts that materially affect scope, architecture, release timing, compatibility, or user-visible behavior require owner clarification before a choice is recorded. |
+| D-029 | 2026-07-18 | Confirmed | UMU is an execution runtime rather than a library provider; game identity remains store-qualified or custom while launch plans may select UMU. |
+| D-030 | 2026-07-18 | Confirmed | Track game lifetime only as needed for temporary performance policy, sleep inhibition, state, logging, and cleanup; do not automatically close Steam, Heroic, Lutris, or other provider clients after play. |
+| D-031 | 2026-07-18 | Confirmed | Use normal complete Arch updates without maintaining a delayed tested package channel; deliver project compatibility fixes independently and retain recovery safeguards. |
+| D-032 | 2026-07-18 | Confirmed | Use the regular Arch `linux` kernel as the reference; do not prefer `linux-zen`, while allowing `linux-lts` as a tested recovery fallback. |
+| D-033 | 2026-07-18 | Confirmed | Steam, Heroic-managed stores, and Lutris remain required for version 1; third-party vendor-launcher integrations move outside version 1. D-038 later makes the three Heroic-managed store targets explicit. |
+| D-034 | 2026-07-18 | Confirmed | Separate game identity, installation instance, configuration owner, execution backend, and compatibility runtime; version machine-readable schemas from phase 1 without promising public stability before 1.0. |
+| D-035 | 2026-07-18 | Confirmed | Use validated inert descriptors for Pegasus exports, define reload/restart behavior, and never interpolate metadata into shell commands. |
+| D-036 | 2026-07-18 | Confirmed | Resolve login, seat, user-session, and recovery-loop behavior during the session proof rather than deferring it to ISO work. |
+| D-037 | 2026-07-18 | Confirmed | Define reproducibility initially as reconstruction from recorded repository/package/build inputs; treat bit-for-bit verification as later hardening and require signed releases, provenance, and an SBOM. |
+| D-038 | 2026-07-18 | Confirmed | Treat Heroic-managed Epic, GOG, and Amazon support as three independent v1 capability targets using validated Legendary, GOGDL, and Nile paths; do not infer standalone-helper compatibility from Heroic's integration. |
+| D-039 | 2026-07-18 | Confirmed | Make UMU runtime acquisition explicit and testable through managed caching, prefetch/update, verified downloads where available, and defined offline behavior. |
+| D-040 | 2026-07-18 | Confirmed | Tie GameMode to a real client/wrapper request lasting for actual game execution; lifecycle confidence alone does not activate it. |
+| D-041 | 2026-07-18 | Confirmed | Use MangoApp for Gamescope HUD integration and ordinary MangoHud only on validated non-Gamescope paths. |
+| D-042 | 2026-07-18 | Confirmed | Adopt Bluetui as the interactive Bluetooth TUI, retain project-owned structured diagnostics and automation, and offer Blueman as the optional desktop-neutral Bluetooth GUI. |
+| D-043 | 2026-07-18 | Confirmed | Evaluate InputPlumber as an optional, post-v1-leaning prototype for advanced routing, remapping, virtual devices, overlays, and controller shell control; do not make it a v1 baseline without evidence. |
+| D-044 | 2026-07-18 | Confirmed | Offer ProtonPlus as an optional maintenance GUI while retaining backend ownership of runtime resolution, validation, pinning, provenance, caching, prefetch, and offline behavior. |
+| D-045 | 2026-07-18 | Confirmed | Build the guided installer on archinstall with a maintained project profile/configuration and a pinned local plugin or custom script only where necessary; do not reimplement storage, encryption, account, or base-install functions or fetch unpinned executable plugins. |
+| D-046 | 2026-07-18 | Confirmed | Offer an optional Btrfs recovery profile using Snapper and pacman transaction hooks; do not require Btrfs, and defer boot integration until the bootloader is selected. |
+| D-047 | 2026-07-18 | Confirmed | Reference or reuse ChimeraOS gamescope-session for dedicated frontend sessions where appropriate, but not as the Lean/Ready general multi-window shell. |
+| D-048 | 2026-07-18 | Confirmed | Add OpenGamepadUI as a post-v1 frontend candidate beside Pegasus without granting its internal catalog or plugins backend authority. |
+| D-049 | 2026-07-18 | Confirmed | Use Labwc as the leading stacking-compositor prototype while keeping final selection conditional on application, hardware, portal, multi-monitor, and nested-Gamescope tests. |
+| D-050 | 2026-07-18 | Confirmed | Add a phase 0 repository/evidence baseline before feature work: pinned toolchain and lockfile, CI quality gates, audits, ADRs, fixture rules, threat model, package/source inventory, test-evidence format, and supported-platform record. |
+| D-051 | 2026-07-18 | Confirmed | Start with on-demand authoritative discovery and no persistent database; add only a disposable cache or SQLite index when measured latency or live-state requirements justify it, preserving a no-cache path. |
+| D-052 | 2026-07-18 | Confirmed | Store IDs remain storefront-qualified (`epic:`, `gog:`, `amazon:`) even when Heroic owns configuration; the management client is not part of canonical game identity. |
+| D-053 | 2026-07-18 | Confirmed | Treat window focus as a compositor/session-adapter capability. Labwc keybindings are the baseline because Labwc intentionally exposes no D-Bus or custom IPC; unsupported programmatic focus is reported honestly. |
+| D-054 | 2026-07-18 | Confirmed | Establish explicit XDG, filesystem, process-execution, redaction, atomic-write, local-IPC, and privilege trust boundaries before provider implementation, with adversarial acceptance tests. |
+| D-055 | 2026-07-18 | Confirmed | Do not install Heroic or other non-repository components from live AUR state. Release profiles consume reviewed, pinned, reproducibly built and project-signed packages or verified upstream artifacts recorded in the source inventory. |
+| D-056 | 2026-07-18 | Confirmed | Never guess through ambiguous game names: exact stable IDs are deterministic, unique names/aliases may launch directly, interactive terminals may present a numbered/TUI choice, and noninteractive callers receive a structured ambiguity error with candidates. |
+| D-057 | 2026-07-18 | Confirmed | Persist installation UUIDs and move aliases in a small schema-versioned, atomic project-owned XDG state registry when adapters lack a stable native installation ID; this identity state is distinct from an optional disposable discovery cache. |
+| D-058 | 2026-07-18 | Confirmed | Maintain requirement-to-phase-to-test traceability from phase 0 onward; a release cannot pass with an orphaned Required requirement or prose-only evidence. |
+| D-059 | 2026-07-18 | Superseded by D-065 | Originally required collision-checked install/package/crate/configuration/IPC names during phase 0 before scaffolding public surfaces. D-065 narrows the gate to public, published, or globally installed artifacts so private implementation can proceed with repository-local placeholders. |
+| D-060 | 2026-07-18 | Confirmed | Limit version 1 to x86_64 UEFI systems; legacy BIOS and non-x86 architectures are outside the v1 support boundary. |
+| D-061 | 2026-07-18 | Confirmed | Ship v1 as a single-local-gaming-user appliance while keeping state, services, credentials, paths, libraries, saves, and profiles per-user so multi-user Steam-machine use can be added later. |
+| D-062 | 2026-07-18 | Confirmed | Make AMD and NVIDIA GPU/driver coverage release-blocking for v1; treat Intel as tested best-effort until representative hardware can run the full matrix. |
+| D-063 | 2026-07-18 | Confirmed | Use versioned TOML with commented generated defaults and CLI editing/validation for user configuration; retain JSON for machine-readable contracts and output. |
+| D-064 | 2026-07-18 | Confirmed | Use the Ryzen 9 7900X3D/RTX 5070 desktop with a dedicated external USB project drive as the initial bare-metal reference, and require Xbox-family and PlayStation-family controller coverage over both USB and Bluetooth. |
+| D-065 | 2026-07-18 | Confirmed | Defer technical names until the final public project name can define one related naming system. Permit only clearly temporary repository-local labels during private development, and require the rename manifest, collision screen, and final rename before anything is published or globally installed. |
+| D-066 | 2026-07-18 | Confirmed | Use the temporary Project Kiln naming family for private development: one repository-local `kiln` CLI with subcommands, plus functional `kiln-core`, `kiln-cli`, `kiln-session`, and `kiln-adapter-*` component labels. Do not create separate `play` or administrative executables. |
+
+## 20. Change log
+
+| **Version** | **Date** | **Summary** |
+|-------------|------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 0.1 | 2026-07-17 | Initial living specification created from planning discussion. Added controller requirements, CLI-only scope, unified backend concept, optional future desktop, roadmap, risks, and open questions. |
+| 0.2 | 2026-07-18 | Confirmed a libvirt/QEMU-first development workflow, layered VM and bare-metal validation, spare-SSD isolation, and optional-only GPU passthrough. |
+| 0.3 | 2026-07-18 | Defined replaceable frontend architecture, upstream Pegasus reference integration, changeable graphical-session startup policies, fork/custom-frontend escalation rules, and a phased public API path. |
+| 0.4 | 2026-07-18 | Replaced ephemeral per-launch graphics with a persistent minimal compositor shell and fullscreen terminal; added Lean/Ready/Frontend/Custom/TTY profiles, launcher switching and residency policy, Steam client constraints, Heroic CLI-backend integration, and deferred installer questions. |
+| 0.5 | 2026-07-18 | Adopted the Project Kiln codename and rename policy, Rust, AGPL-3.0-or-later, a modular monorepo with extractable provider crates, strict incremental test gates, and a lightweight Work Mode/local Codex CLI execution split. |
+| 0.6 | 2026-07-18 | Corrected spec authority wording, Pegasus status language, controller CLI namespacing, a deferred-capability example, bootloader status, and AGPL network-use wording; recorded the unresolved version 1 Pegasus boundary explicitly. |
+| 0.7 | 2026-07-18 | Confirmed Pegasus integration as post-version-1 work, removed the related open question, and added an explicit version 1 release boundary after roadmap phase 11. |
+| 0.8 | 2026-07-18 | Added a mandatory cross-spec integrity procedure for future planning changes, including dependency, release-boundary, status, example, ID, link, and version checks plus an explicit clarification rule for material ambiguity. |
+| 0.9 | 2026-07-18 | Reclassified UMU as a runtime; separated game, installation, owner, backend, and runtime identity; defined confidence-based lifecycle tracking; adopted normal Arch updates and the regular kernel; confirmed base-Arch-first/ISO-later delivery; moved vendor launchers post-v1; and added configuration precedence, session ownership, controller states, safe Pegasus descriptors, reproducibility levels, and supply-chain requirements. |
+| 0.10 | 2026-07-18 | Split Heroic-managed Epic, GOG, and Amazon into independent v1 targets; corrected Lutris local-ID handling, GameMode lifetime semantics, Gamescope HUD integration, and UMU acquisition/offline requirements using current upstream documentation. |
+| 0.11 | 2026-07-18 | Reused maintained upstream components where appropriate: Bluetui and optional Blueman for Bluetooth, optional ProtonPlus, archinstall-based installation, optional Snapper/pacman-hook Btrfs recovery, gamescope-session references for dedicated frontend sessions, post-v1 OpenGamepadUI and InputPlumber evaluation, and Labwc as the leading compositor prototype. |
+| 0.12 | 2026-07-18 | Completed a build-readiness audit: added phase 0 and reproducible evidence requirements; corrected store/adapter identity, durable installation-ID state, frontend/provider-native boundaries, ambiguous-name behavior, and post-v1 CLI leakage; made caching conditional; fixed session target ownership and duplicate headings; accounted for Labwc's lack of IPC; defined controller recovery, package-source, AUR, trust-boundary, adversarial-test, and release-matrix requirements; and narrowed the remaining owner decisions. |
+| 0.13 | 2026-07-18 | Confirmed the x86_64/UEFI and single-user v1 boundaries with a multi-user-safe architecture; made AMD/NVIDIA release-blocking and Intel best-effort; selected versioned TOML plus CLI configuration; recorded the external-USB Ryzen 9/RTX 5070 reference system; and required Xbox/PlayStation USB and Bluetooth coverage. |
+| 0.14 | 2026-07-18 | Deferred technical naming until the final project brand is selected; allowed private implementation with repository-local functional placeholders; and required a rename manifest, automated placeholder scan, collision check, and completed rename before public, published, or globally installed artifacts. |
+| 0.15 | 2026-07-18 | Adopted the temporary Kiln development family throughout the active specification: a single repository-local `kiln` CLI and functional `kiln-*` component labels, with no separate convenience or administrative executable. |
+| 0.16 | 2026-07-18 | Began private phase 0 implementation; pinned Rust 1.97.1 after the upstream miscompilation-fix release, established the initial workspace/evidence baseline, and changed project status from planning to implementation. |
+| 0.17 | 2026-07-18 | Closed phase 0 after the exact Rust toolchain, formatting, compilation, unit tests, Clippy, canonical AGPL license, workspace/source checks, temporary-name scan, and cargo-deny advisory/bans/license/source gates all passed. |
+| 0.18 | 2026-07-18 | Promoted Phase 0 lessons into binding development rules: distinguish MSRV from the enforced toolchain pin, version local path dependencies, keep license allowlists evidence-based, audit pinned development tools, and use Phase 0 completion as the Codex CLI handoff point with a root `AGENTS.md`. |
+
+## 21. Reference notes
+
+- [Gamescope](https://github.com/ValveSoftware/gamescope)
+- [Pegasus Frontend](https://github.com/mmatyas/pegasus-frontend)
+- [Bluetui](https://github.com/pythops/bluetui)
+- [Blueman](https://github.com/blueman-project/blueman)
+- [InputPlumber](https://github.com/ShadowBlip/InputPlumber)
+- [ProtonPlus](https://github.com/Vysp3r/ProtonPlus)
+- [archinstall](https://github.com/archlinux/archinstall)
+- [Snapper](https://github.com/openSUSE/snapper)
+- [snap-pac](https://github.com/wesbarnett/snap-pac)
+- [ChimeraOS gamescope-session](https://github.com/ChimeraOS/gamescope-session)
+- [OpenGamepadUI](https://github.com/ShadowBlip/OpenGamepadUI)
+- [Labwc](https://github.com/labwc/labwc)
+- [UMU Launcher](https://github.com/Open-Wine-Components/umu-launcher)
+- [Heroic Games Launcher](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher)
+- [Legendary](https://github.com/derrod/legendary)
+- [GOGDL](https://github.com/Heroic-Games-Launcher/heroic-gogdl)
+- [Nile](https://github.com/imLinguin/nile)
+- [Lutris](https://github.com/lutris/lutris)
+- [Lutris manual page](https://man.archlinux.org/man/lutris.1.en)
+- [GameMode](https://github.com/FeralInteractive/gamemode)
+- [MangoHud and MangoApp](https://github.com/flightlessmango/MangoHud)
+- [ArchWiki — Gaming](https://wiki.archlinux.org/title/Gaming)
+- [ArchWiki — Gamescope](https://wiki.archlinux.org/title/Gamescope)
+- [systemd graphical-session target](https://www.freedesktop.org/software/systemd/man/latest/systemd.special.html#graphical-session.target)
+- [archinstall plugins](https://archinstall.archlinux.page/archinstall/plugins.html)
+- [Arch Linux package — umu-launcher](https://archlinux.org/packages/multilib/x86_64/umu-launcher/)
+- [Arch Linux package — Bluetui](https://archlinux.org/packages/extra/x86_64/bluetui/)
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
new file mode 100644
index 0000000..98eaf31
--- /dev/null
+++ b/rust-toolchain.toml
@@ -0,0 +1,5 @@
+[toolchain]
+channel = "1.97.1"
+profile = "minimal"
+components = ["clippy", "rustfmt"]
+
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..1580019
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1,4 @@
+edition = "2024"
+max_width = 100
+use_field_init_shorthand = true
+
diff --git a/scripts/audit_workspace.py b/scripts/audit_workspace.py
new file mode 100755
index 0000000..bb03cbe
--- /dev/null
+++ b/scripts/audit_workspace.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+"""Audit the dependency-free bootstrap, licensing, and source inventory."""
+
+from __future__ import annotations
+
+import hashlib
+import sys
+import tomllib
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[1]
+EXPECTED_LICENSE_SHA256 = "0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0"
+
+
+def fail(message: str) -> None:
+ print(f"FAIL: {message}", file=sys.stderr)
+ raise SystemExit(1)
+
+
+def load(path: Path) -> dict:
+ with path.open("rb") as stream:
+ return tomllib.load(stream)
+
+
+def main() -> None:
+ workspace = load(ROOT / "Cargo.toml")
+ package_defaults = workspace["workspace"]["package"]
+ if package_defaults.get("license") != "AGPL-3.0-or-later":
+ fail("workspace package license is not AGPL-3.0-or-later")
+ if package_defaults.get("publish") is not False:
+ fail("private workspace packages must set publish = false")
+ if "repository" in package_defaults:
+ fail("private scaffold must not advertise a placeholder repository URL")
+
+ cli_manifest = load(ROOT / "crates" / "kiln-cli" / "Cargo.toml")
+ core_dependency = cli_manifest.get("dependencies", {}).get("kiln-core", {})
+ if core_dependency.get("version") != "=0.0.1":
+ fail("internal kiln-core dependency must use the exact workspace release version")
+ if core_dependency.get("path") != "../kiln-core":
+ fail("internal kiln-core dependency must resolve through the reviewed workspace path")
+
+ license_hash = hashlib.sha256((ROOT / "LICENSE").read_bytes()).hexdigest()
+ if license_hash != EXPECTED_LICENSE_SHA256:
+ fail(f"root LICENSE is not the canonical AGPL-3.0 text: {license_hash}")
+
+ lock = load(ROOT / "Cargo.lock")
+ external = [package for package in lock["package"] if "source" in package]
+ if external:
+ names = [f"{item['name']}@{item['version']}" for item in external]
+ fail(f"unreviewed external Rust dependencies entered the bootstrap: {names}")
+
+ inventory = load(ROOT / "docs" / "phase-0" / "source-inventory.toml")
+ components = {item["name"]: item for item in inventory["components"]}
+ toolchain = load(ROOT / "rust-toolchain.toml")["toolchain"]["channel"]
+ if components.get("rust", {}).get("version") != toolchain:
+ fail("source inventory Rust version does not match rust-toolchain.toml")
+ if components.get("cargo-deny", {}).get("version") != "0.20.2":
+ fail("cargo-deny is absent or not pinned to the reviewed version")
+
+ load(ROOT / "deny.toml")
+ print("PASS: workspace dependency, license, and source baseline")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/scan_placeholders.py b/scripts/scan_placeholders.py
new file mode 100755
index 0000000..f4f7091
--- /dev/null
+++ b/scripts/scan_placeholders.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+"""Inventory temporary names and reject them from public/installable surfaces."""
+
+from __future__ import annotations
+
+import sys
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[1]
+TOKENS = ("Project Kiln", "kiln", "KILN_")
+IGNORED_PARTS = {".git", "target", "__pycache__"}
+PUBLIC_SURFACES = {"dist", "packaging", "public", "release"}
+TEXT_SUFFIXES = {"", ".csv", ".md", ".py", ".rs", ".toml", ".yml", ".yaml"}
+
+
+def main() -> None:
+ matches: list[tuple[Path, str]] = []
+ violations: list[tuple[Path, str]] = []
+ for path in ROOT.rglob("*"):
+ relative = path.relative_to(ROOT)
+ if not path.is_file() or any(part in IGNORED_PARTS for part in relative.parts):
+ continue
+ if path.suffix.lower() not in TEXT_SUFFIXES:
+ continue
+ try:
+ content = path.read_text()
+ except UnicodeDecodeError:
+ continue
+ for token in TOKENS:
+ if token not in content:
+ continue
+ matches.append((relative, token))
+ if any(part in PUBLIC_SURFACES for part in relative.parts):
+ violations.append((relative, token))
+ if violations:
+ for path, token in violations:
+ print(f"FAIL: temporary token {token!r} in public surface {path}", file=sys.stderr)
+ raise SystemExit(1)
+ if not matches:
+ print("FAIL: expected private placeholders were not found", file=sys.stderr)
+ raise SystemExit(1)
+ print(f"PASS: {len(matches)} temporary-name occurrences remain private and inventoried")
+
+
+if __name__ == "__main__":
+ main()
+
diff --git a/scripts/verify_repo.py b/scripts/verify_repo.py
new file mode 100755
index 0000000..d7d837e
--- /dev/null
+++ b/scripts/verify_repo.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python3
+"""Dependency-free Phase 0 repository and specification checks."""
+
+from __future__ import annotations
+
+import csv
+import re
+import sys
+import tomllib
+from urllib.parse import unquote
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[1]
+SPEC = ROOT / "docs" / "spec"
+
+
+def fail(message: str) -> None:
+ print(f"FAIL: {message}", file=sys.stderr)
+ raise SystemExit(1)
+
+
+def check_toml() -> None:
+ manifests = [ROOT / "Cargo.toml", *sorted((ROOT / "crates").glob("*/Cargo.toml"))]
+ for manifest in manifests:
+ with manifest.open("rb") as stream:
+ tomllib.load(stream)
+ toolchain = tomllib.loads((ROOT / "rust-toolchain.toml").read_text())
+ if toolchain["toolchain"]["channel"] != "1.97.1":
+ fail("Rust toolchain is not pinned to 1.97.1")
+
+
+def check_spec() -> set[str]:
+ expected = {f"0{number}_" for number in range(8)}
+ files = sorted(SPEC.glob("0[0-7]_*.md"))
+ prefixes = {path.name[:3] for path in files}
+ if prefixes != expected:
+ fail(f"active spec set is incomplete: {sorted(prefixes)}")
+ combined = "\n".join(path.read_text() for path in files)
+ requirements = re.findall(r"^\| (R-\d{3})\s+\|", combined, re.MULTILINE)
+ decisions = re.findall(r"^\| (D-\d{3})\s+\|", combined, re.MULTILINE)
+ for label, identifiers in (("requirement", requirements), ("decision", decisions)):
+ duplicates = sorted({item for item in identifiers if identifiers.count(item) > 1})
+ if duplicates:
+ fail(f"duplicate {label} IDs: {duplicates}")
+ versions = re.findall(r"^\| \*\*Version\*\*\s+\| ([0-9.]+)", combined, re.MULTILINE)
+ if versions != ["0.18"]:
+ fail(f"active specification version markers are stale or ambiguous: {versions}")
+ return set(requirements)
+
+
+def check_traceability(required: set[str]) -> None:
+ path = ROOT / "docs" / "phase-0" / "traceability.csv"
+ with path.open(newline="") as stream:
+ rows = list(csv.DictReader(stream))
+ traced = {row["requirement_id"] for row in rows}
+ missing = sorted(required - traced)
+ if missing:
+ fail(f"requirements missing from traceability matrix: {missing}")
+
+
+def check_markdown_links() -> None:
+ broken: list[str] = []
+ for document in ROOT.rglob("*.md"):
+ if any(part in {".git", "target"} for part in document.relative_to(ROOT).parts):
+ continue
+ for destination in re.findall(r"\[[^]]*\]\(([^)]+)\)", document.read_text()):
+ target = destination.split("#", 1)[0]
+ if not target or "://" in target or target.startswith("mailto:"):
+ continue
+ resolved = (document.parent / unquote(target)).resolve()
+ if not resolved.exists():
+ broken.append(f"{document.relative_to(ROOT)} -> {destination}")
+ if broken:
+ fail(f"broken Markdown links: {broken}")
+
+
+def check_placeholders() -> None:
+ allowed_roots = {"crates", "docs", "scripts", ".github"}
+ for child in ROOT.iterdir():
+ if child.is_dir() and not child.name.startswith(".") and child.name not in allowed_roots:
+ fail(f"unexpected top-level directory: {child.name}")
+ manifest = (ROOT / "docs" / "phase-0" / "rename-manifest.md").read_text()
+ for token in ("kiln", "KILN", "Project Kiln"):
+ if token not in manifest:
+ fail(f"rename manifest does not track {token!r}")
+
+
+def check_verification_entrypoints() -> None:
+ makefile = (ROOT / "Makefile").read_text()
+ required = (
+ "python3 scripts/verify_repo.py",
+ "python3 scripts/audit_workspace.py",
+ "python3 scripts/scan_placeholders.py",
+ "python3 scripts/verify_rust_toolchain.py",
+ "cargo fmt --all --check",
+ "cargo test --workspace --all-targets --locked",
+ "cargo clippy --workspace --all-targets --locked -- -D warnings",
+ "cargo deny check advisories bans licenses sources",
+ )
+ missing = [command for command in required if command not in makefile]
+ if missing:
+ fail(f"Makefile is missing verification gates: {missing}")
+
+
+def main() -> None:
+ check_toml()
+ requirements = check_spec()
+ check_traceability(requirements)
+ check_markdown_links()
+ check_placeholders()
+ check_verification_entrypoints()
+ print(f"PASS: Phase 0 static baseline ({len(requirements)} requirements traced)")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/verify_rust_toolchain.py b/scripts/verify_rust_toolchain.py
new file mode 100755
index 0000000..b0bef24
--- /dev/null
+++ b/scripts/verify_rust_toolchain.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+"""Require the exact reviewed Rust compiler before running Rust quality gates."""
+
+from __future__ import annotations
+
+import re
+import subprocess
+import sys
+import tomllib
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[1]
+PIN = ROOT / "rust-toolchain.toml"
+
+
+def main() -> None:
+ with PIN.open("rb") as stream:
+ expected = tomllib.load(stream)["toolchain"]["channel"]
+ result = subprocess.run(
+ ["rustc", "--version"],
+ check=True,
+ capture_output=True,
+ text=True,
+ )
+ match = re.match(r"rustc ([0-9]+\.[0-9]+\.[0-9]+)(?:\s|$)", result.stdout)
+ if match is None:
+ print(f"FAIL: could not parse compiler version: {result.stdout.strip()}", file=sys.stderr)
+ raise SystemExit(1)
+ actual = match.group(1)
+ if actual != expected:
+ print(
+ f"FAIL: rustc {actual} is active, but rust-toolchain.toml pins {expected}.\n"
+ "A distro-provided cargo/rustc may ignore rust-toolchain.toml; use the "
+ "pinned rustup toolchain or update the distro packages.",
+ file=sys.stderr,
+ )
+ raise SystemExit(1)
+ print(f"PASS: exact Rust toolchain {actual}")
+
+
+if __name__ == "__main__":
+ main()