Repository navigation
Conversation
… a Tree (#3509) Implements #3505, with the design points the maintainer settled on the issue before the first edit. ## What Changed - **`lib/sh/secrets.sh`** is the hub's runtime library: `unresolved_link_reason`, `secret_state`, the shape, content, set, and full verdicts, `require_secret`, and `read_env_value`. Each function body is byte-identical to the source implementation, compared with `declare -f`. Its comments now describe the mechanism rather than the adopter. The installer path helpers, the push interlock, and `write_state_file` stay in the source repository. The source has no owner check, so the issue's owner-exemption parameter had nothing to parameterize. - **`host-secrets`** is a new project type. `spec/project-types.json` gives it `detect` and one intent check, `spec/scope-model.md` lists its token, `spec/type-model.md` gains "Runtime Libraries", and the conformance matrix has its row. - **`spec/files.json`** carries `lib/sh` to `lib/fleet/sh` as a `verbatim-tree` for `appliesTo: ["host-secrets"]`, so `carry.py`, the audit, and the canonical sweep pick it up with no code of their own. - **`repo_gate.py` `carried-trees`** compares each carried tree a scanned repository tracks with the hub tree beside the gate, the pinned action's in CI. It loads the hub's own `scripts/carry.py` and reuses its tree functions, including the new `target_patterns` and `compare_declaration` that `carry.py`'s own check and post-apply comparison now share. A difference is a `note:` plus a `::warning` annotation and never a finding. A repository tracking `spec/files.json` is a hub and compares nothing. A tree that cannot be compared, or a `carry.py` that will not load or run, says so in a note. - **`GOVERNANCE.md`**: "Hub-Hosted Tooling" states why code a repository's own runtime executes is carried rather than reached. "Repo-Scoped Secrets" states the reader rule the type's check judges, and "Repository Layout" lists `lib/`. - **Tests**: `tests/test_secrets_sh.py` drives every verdict and the env read against constructed files. `tests/test_repo_gate.py` covers the new check and `gate_hub_root`. `tests/test_cli_usage.py` lists the library as sourced rather than run. ## Verification - The full unit suite under `tests/requirements.txt` passes: 3023 tests, 7 skipped. - Mutating the library, by dropping `-u BASH_ENV` or the `unset`, reading `$2` at the end, dropping `/dev/null`, reordering the set verdict, or sourcing in process, fails the case written for each fault. - `spec/validate.py`, `build_dist.py --check`, the prose gate with comments allowed, every `repo_gate.py` check, and the Docker lint wrapper's seven linters are clean. - `carried-trees` was run against two downstream checkouts. Blog's `.github/skills` matches the hub. One checkout's copy differs in 37 files and warns as designed. The check also runs under Python 3.12, the runner's system interpreter. ## Local Review Each push's content went through recorded `local-strict-review` passes at the `frontier` tier, and each push spent its two-round edit budget. The seven pushes' passes raised 11, 15, and 4 findings, then 6 and 4, then 4, 4, and 3, then 5 and 3, then 2 and 2, then 3 and 1, then 3 and 1, and the eighth push's pass raised none. The seventh push also fixes the Windows unit test job, which failed on an unresolved 8.3 temp path in the new `carry.run` case. Every `introduced` finding is answered. ### Declined in the sixth push - The import-time `uv python find` probe in `tests/host_capability.py` follows the file's existing eager `can_symlink()` probe. ### Pre-existing findings, not filed - `pre-existing`: `tests/test_repo_gate.py`, whose write-verb scan reads `scripts/repo_gate.py`, a `run_path` shim, rather than the gate under `.github/actions/repo-gate/`. ### Declined, with evidence - The library's own hardening (the positional-parameter guard, `grep -D skip`, the `readarray -d /` split): the bodies move byte-identical by the issue's design, so a change to them is its own issue in the authoring repository. - The note not naming the hub commit: the pinned action's tree is an archive with no `.git`, and the run log already names the action's pin. - Untracked files in a local hub checkout's source tree: `carry.py`'s own `inventory` reads the source the same way, so the gate and a carry agree. - CRLF working-tree bytes on a Windows checkout: every registry entry declares `lineEndings: lf`. - The `spec/files.json` hub test catching an unpruned template copy: the note says "is a hub", so the result is visible rather than silent. - The issue's point that the same rule gives `hub_fetch_run.py` a declared home: that loader is not a `spec/files.json` tree, and the "Hub-Hosted Tooling" paragraph beginning "A loader is outside this section" already governs it. - The `try` around the manifest read: `load_json` belongs to a `carry.py` of whatever hub version the pin holds, so the reason for the other broad catches covers it too. - Folding the gate test helpers `TestCarriedTrees.write` and `TestGateHubRoot.place` into one: a preference between defensible forms, which "Review the Change" says to omit. ### Dropped findings - The module docstring's table framing, and long sentences in comments and docstrings, which an advisory check reports and no gate enforces. - `spec/audit.py` `check_tree_verbatim` keeps its own blob-based statement of the tree ownership rule. That file is untouched here, and it reads blobs rather than inventories. The pull request carries the `comments` label. The added comments are each function's caller contract and the measured reasons behind each check. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
There was a problem hiding this comment.
🟡 Changes recommended
Three unresolved findings remain, including a critical symlink-handling issue in the secret reader.
2 open issues
What changed in this PR
This pull request promotes the hub-hosted secret and environment readers to main, adding the host-secrets project type, carried-tree contract, repository-gate support, tests, and governance documentation.
Changes:
- Adds and tests
lib/sh/secrets.shfor secret validation and isolated environment-file reads. - Defines
host-secretsand carrieslib/shtolib/fleet/shthroughspec/files.json. - Adds carried-tree comparison support, updated carry behavior, workflow documentation, and governance guidance.
Unresolved findings:
lib/sh/secrets.sh:242— moderate, P1: Preserve the requested environment variable name while sourcing the file.lib/sh/secrets.sh:61— critical, P1: Reject resolving parent symlinks before reading secrets.spec/files.json:6— moderate, P1: Carry the reader tests with the runtime tree.
| File | Description |
|---|---|
tests/test_secrets_sh.py |
Tests secret verdicts, required secrets, and environment-file reads. |
tests/test_repo_gate.py |
Tests carried-tree comparison, warnings, and hub-root detection. |
tests/test_cli_usage.py |
Classifies the shell library as sourced rather than executed. |
tests/test_carry.py |
Tests non-pruned tree ownership and comparison helpers. |
tests/host_capability.py |
Adds Python 3.12 capability detection for gate tests. |
spec/type-model.md |
Documents runtime-library project types. |
spec/scope-model.md |
Adds host-secrets to the project-type selector namespace. |
spec/project-types.json |
Defines the host-secrets type and reader contract. |
spec/files.json |
Declares the lib/sh to lib/fleet/sh carried tree. |
spec/fidelity-model.md |
Clarifies byte-for-byte tree comparison. |
scripts/README.md |
Documents the carried-trees gate behavior. |
scripts/carry.py |
Shares target ownership and declaration comparison logic. |
reports/conformance-matrix.md |
Adds the host-secrets overlay to the conformance matrix. |
lib/sh/secrets.sh |
Provides the hub-hosted secret and environment readers. |
GOVERNANCE.md |
Defines runtime-library carrying and repo-scoped secret-reader rules. |
AUDIT.md |
Adds host-secrets discovery guidance. |
.github/workflows/validate-task.yml |
Documents carried-tree exclusion handling. |
.github/actions/repo-gate/repo_gate.py |
Implements the non-blocking carried-tree currency check. |
.github/actions/repo-gate/action.yml |
Updates the gate description for carried-tree checks. |
Review effort: Lite
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3512 +/- ##
==========================================
+ Coverage 81.11% 81.54% +0.42%
==========================================
Files 26 26
Lines 8914 8918 +4
==========================================
+ Hits 7231 7272 +41
+ Misses 1683 1646 -37
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Answering the review body's third unresolved finding, |


Summary
Promotes the pull request merged into develop since release 2.0.1196.
lib/sh/secrets.sh, the hardened secret and env readers a fleet repository runs on its own hosts. A repository declaring the newhost-secretstype carries it byte-for-byte atlib/fleet/shthrough aspec/files.jsontree.repo_gate.pygains acarried-treescheck, which compares each carried tree with the hub tree beside the gate and reports a difference as a warning that never fails the gate.carry.pygains the sharedtarget_patternsandcompare_declaration, which fix its post-apply comparison for a tree that does not prune.GOVERNANCE.md"Hub-Hosted Tooling" states why a runtime library is carried rather than reached, and "Repo-Scoped Secrets" states the reader rule.Closes #3505
Constituent coverage
85b2c4addevelop, recording 0 findings, and a Copilot round on an earlier head whose five findings were fixed or declined with evidence and resolved🤖 Generated with Claude Code