Repository navigation
fix(env): preserve live keys during migration cleanup (HACK-2172) - #769
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@codex review |
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
Security findingsAdvisory findings (1)ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. You're on a roll. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Ready for lead: urgent HACK-2172 is isolated in #769 directly against The reproduced The real-files regression failed on exact Hosted Linux checks and bot re-review of this latest push remain pending; macOS and Docker qualification are not claimed or waited on. No merge performed. This PR can be reviewed and landed independently before #756/#767/#768. Unexpected identity lookup failures still fail closed and remove nothing; broader cleanup receipt/outcome handling remains in #768. |
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Here are some automated security review suggestions for this pull request.
Reviewed commit: d776550f19
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
|
@codex review |
|
Codex Review: Didn't find any major issues. You're on a roll. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
Ready for lead: macOS fixture-path fix is pushed at c303909. fixture() resolves its temp root once with realpath and preserves the unresolved spelling as an additional protected-key candidate. All five tests pass with both normal and deliberately symlinked TMPDIR on Linux; changed-test lint passes. Persistent reviewer is clean at this exact head. Product code is unchanged from the independently reviewed 6855940. Current-head hosted checks remain pending. No merge performed; ready for the requested urgent merge. |
|
@codex review |
|
Codex Review: Didn't find any major issues. 🚀 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
…K-2166) (#767) Env listings exposed migrated plaintext, legacy lifecycle commands received service values outside their scope, and secret writes accepted values in argv. Listings now show metadata by default, lifecycle delivery is scoped, and chosen plaintext entries can be encrypted in place without copying values through a terminal. - Text and JSON listings expose names, scope, source layer and set state. Revealing values requires an explicit flag and an interactive terminal. This reduces accidental output exposure; it is not access control against a local process. - `env add/set --secret` refuses positional values with stdin guidance before effects. Malformed add keys are validated before that guard, so pasted assignments receive a fixed, value-free refusal in either interactivity mode. - Legacy lifecycle hooks/processes receive only global values. Docker inspection/log/event helpers receive OS and transport settings, preserving Docker, Podman, SSH and XDG context variables without application values. - `env protect` lists plaintext names; `env protect KEY...` encrypts matching entries in their existing scopes, overlays and local layers. Existing ciphertext must decrypt before conversion; missing/wrong keys refuse before writes. Local-overlay overrides remain part of the local overlay. Doctor prints a names-only inventory and protection guidance after migration. - Daemon GET uses canonical YAML metadata without values; YAML-project legacy set/unset routes retain the parent's HTTP 409 refusal. Agent source, generated plugin, repository examples, ownership fingerprints, security model and diagram agree with these boundaries. Breaking change: scripts must replace `env list --json --show-secrets` with explicit `hack env get KEY` reads for only the keys needed; never log those plaintext reads. Use `has_value` for availability checks. Pipe secret input with `--value-stdin`. Update text parsers for modern key/scope/set/layer columns (value only on reveal) and legacy set/layer columns 7/8. Review legacy hooks that depended on service values and move only their required values to global scope. Use `env protect` to inventory and encrypt chosen plaintext entries while keeping existing key backups. Next.17's generated release notes carry this breaking change, the migration commands, daemon API changes and HACK-2172's live-key preservation fix. The upgrade guide distinguishes planned next.17 behavior from the published next.16 snapshot. Publish next.17 only after this PR is included; no release is performed here. Existing secret-to-plaintext downgrade without `--secret` remains HACK-2173. Validation on pinned Bun 1.4.4: root typecheck/lint/build, docs generation/checks, 19 argument/exposure cases, 21 daemon/dependency cases, 37 guidance/matrix cases, 51 scanner/background-process cases, release-note tests and ownership tests pass. Additional original listing/protection/worktree regressions remain in the branch. One plugin release-preparation fixture cannot complete locally because a managed runtime refuses an untrusted host toolchain config; no trust approval is bypassed. Prepared-host verification or hosted CI is still needed for that fixture. The selector chooses 742/full; the compiler-dependent full local suite remains unavailable. Local checks do not qualify Mac VM or real Docker behavior. Targets `next` and includes next 021b16b. #756 and #769 have landed; their squash history is reconciled additively. The merge-only comparison tree for the lead's earlier verification is 814fbd1; later deliberate changes are the refusal ordering, release notes, current-base integration and guidance/audit reconciliation. HACK-2171/#768 follows with cleanup receipts and truthful deletion failures. Other sessions retain ownership of at-rest, store/key and lifecycle-log findings. --------- Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
next edf23ae (the squash of #762, plus #767 and #769) conflicts in src/lib/fs.ts and src/lib/project-env-config.ts. Both sides are kept: - writeTextFileAtomicIfChanged has #762's noFollowTarget (destination never resolved through a link) and this branch's tightenExisting and private staging; machine-local writes pass all of createMode 0600, noFollowTarget and tightenExisting, with #762's link recheck before the rename. The in-place tighten for an unchanged write honours noFollowTarget too. - #769's live-input guard and #767's value-free listing are untouched (auto-merged). docs/env.md no longer says an existing layer keeps its mode. Co-Authored-By: Claude <noreply@anthropic.com>
…rechecked at removal (HACK-2165) The leftover filter knew configured stores and keys, the shared key and the project key, but not the other inputs current env resolution reads, and it ran only at inspection. It now also keeps the project inputs legacy cleanup keeps (#769: the primary worktree's key, hack.config.json and every YAML layer), now exported as projectEnvLiveInputPaths, each as given and resolved. --fix asks again just before each unlink, and when the project's inputs cannot be inspected nothing counts as removable. Matching is by path, not inode: removing another link to a live file never removes the name resolution reads, and a publication interrupted after its link step leaves exactly such a second name to clean. Regressions: a YAML layer that comes to resolve to a staging-shaped file between inspection and --fix keeps it; an uninspectable hack.config.json blocks every leftover removal. Both fail without the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…768) Migration cleanup could delete a newer legacy env file after an earlier confirmation decision. It now carries bounded content and file-identity receipts from before migration, rechecks current scoped delivery and Compose references under writer locks after consent, and checks each target again before unlinking. - Source files and YAML destinations use their existing env-layer writer locks; the encrypted store and key use their separate owner locks in the same sorted lock set. The key lock is shared by every store using that path. Cleanup creates no repository-root `.internal/` for a key. - Changed inputs, unavailable receipts or delivery drift preserve remaining files. Partial failures retain every confirmed removal; the key is removed only after its store. - Automatic cleanup catches cleanup errors and warns so env/up/session commands can continue. Explicit doctor cleanup fails closed. Recovery advice preserves `--local`, secrecy, scopes and overlays and uses stdin rather than promising a migration rerun imports changed values into existing YAML. - Doctor puts an untracked legacy key in its tracked store's confirmation batch. Declining that batch keeps both; accepting it removes the store before its key. The key-only deletion refusal remains intact. - Legacy daemon secret deletion failure returns HTTP 500 `partial_failure`, fixed `secret_delete_unconfirmed` text and `secretDeleted: null`, preserving the completed `dotenvChanged` result. It does not claim backend absence or rollback. This addresses audit F10 and S5. S6's value-free legacy JSON diagnostics arrived in merged #756. HACK-2172/#769 already preserves live project/shared keys, config and YAML inputs, including aliases; this PR keeps those guards before/under locks and immediately before unlink. The integration includes next `ab29d491` and the landed parent fixes. A held-key-writer regression fails without adopting the new HACK-2169 key-owner lock and passes with it. A real temporary Git regression reproduces the tracked-store/untracked-key batching refusal without the fix and passes afterward. Pinned Bun validation: 39 cleanup/live-key/daemon cases, 56 store/integrity cases and 14 selected doctor migration cases passed before the final batching change. For the batching change, 19 legacy cleanup cases (117 assertions), both doctor store batches (19 assertions), typecheck, root and changed-file lint, build and docs checks pass. The plugin release-preparation fixture also passes (13 assertions) after an owner-approved trust step scoped to an isolated test home; no global trust setting changed. Persistent review is clean at exact head `6cf07d3801ba00c6f4399b4eadc6ae8e85fa051f`. Hosted checks and the refreshed GitHub review remain pending. The full compiler-dependent suite remains a hosted gate; no new Mac VM or real Docker qualification is claimed locally. Noncooperating writers can still race the last unlink. The reverse consent case (untracked store, tracked key, initial cleanup declined) retains its existing safe refusal. Opposing future lock nesting can time out safely; normal key writers hold only the key lock and normal store writers resolve the key before taking the store lock. No cipher-format or rotation change is made. Targets `next`; all parent PRs have landed and their squash ancestry is reconciled by additive merge. No history rewrite, merge to next or publication is performed here. The lead arranges independent review before merge. --------- Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
Add next.17 “what changed and what to do” notes to the release summary, both upgrade guides and the env guide. Users get concrete script migrations for hidden env values and native followed logs, the next.16 key-backup warning, and recovery guidance for partial cleanup. These describe merged source changes intended for next.17; they do not claim a release is published. The docs site remains pinned to next.16. #764 and #779 remain explicitly pending, and the recorded next.16 trials keep their original limits. | Subject | Merged contract checked at base `0a0bfdb8` | | --- | --- | | #747: native plain followed logs, streams, timestamps and structured session results | [native-log-follow.ts](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/src/backends/native-log-follow.ts), [followed-service-log contract](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/docs/reference/native-authored-commands.md#followed-service-logs) | | #767: metadata/`has_value`, scoped plaintext reads, terminal-only reveal, stdin secret writes, `env protect`, global-only lifecycle hooks/processes and YAML daemon API | [canonical prerelease wording](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/scripts/prerelease-plan.ts#L158), [env command](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/src/commands/env.ts), [env routes](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/src/daemon/routes/env.ts), [env contract](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/docs/env.md) | | #769 / HACK-2172 and #768/#783: protect live keys/config/YAML including filesystem aliases; cleanup receipts, partial removal and config-pointer reconciliation | [project-env-config.ts](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/src/lib/project-env-config.ts), [Doctor cleanup](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/src/commands/doctor.ts), [canonical cleanup note](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/scripts/prerelease-plan.ts#L164) | | #766: Doctor refuses unusable env layers | [doctor-secret-integrity.ts](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/src/lib/doctor-secret-integrity.ts) | | #773: loopback proxy ports, diagnosis without automatic repair | [proxy-loopback.ts](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/src/lib/proxy-loopback.ts), [Doctor](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/src/commands/doctor.ts) | | #770: inferred route readiness, 240-second grace, HTTP 200–499 limits and `service_healthy` exclusion | [http_probe.rs](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/packages/runtime-core/src/provider/http_probe.rs), [probe contract](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/docs/guides/native-candidate.md#native-http-readiness-probe) | | #778: bridge connection readiness after pool restart | [bridge.rs](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/packages/runtime-core/src/provider/bridge.rs) | | #758 and #776: merged startup fix and newer optional-daemon behavior, kept separate from next.16 | [project command](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/src/commands/project.ts), [Doctor](https://github.com/hack-dance/hack/blob/0a0bfdb8d1ee818d89bb49a2109bd88b0a9fea1b/src/commands/doctor.ts) | Validation at `f1d0d72fede5db6ce46f56039ba22a47911aa308`: - Persistent reviewer: clean after round 2. - Pinned Bun 1.4.4: docs prepare/check/typecheck and production site build pass. - Production-mode HTTP smoke: 95 docs, isolated searches/exports, redirects/refusals, 37 diagram blocks / 74 SVGs and 183 recipe links/anchors pass. The rendered upgrade guide returns 200 and contains the new guidance. - Privacy check, diff check and full-history Gitleaks pass (1,295 commits, no leaks). - Source citations and documented command forms checked against the merged base. Documentation only: no runtime, workflow, site pin, snapshot or global client changes. No live migration, keys, daemon, Docker or native VM tests were run. Lead owns batch integration and deployment. <!-- codesmith:footer --> --- <a href="https://backend.blacksmith.sh/track/run-proof?expires=1797183263&installation_model_id=17053&pr_number=785&ref=codesmith_pr_footer&repository=hack-dance%2Fhack&return_to=https%3A%2F%2Fgithub.com%2Fhack-dance%2Fhack%2Fpull%2F785&variant=run_proof_on_this_pr&signature=b04dd421a08341f70e804e671fd68678f102d1c4152146bdea18adf6de909981"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/proof-run-proof-on-this-pr-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/proof-run-proof-on-this-pr-light.svg"><img alt="Run Proof on this PR" src="https://pr-comments-assets.blacksmith.sh/codesmith/proof-run-proof-on-this-pr-dark-3x.png" width="168" height="28"></picture></a> <sup><a href="https://app.blacksmith.sh/hack-dance/codesmith/hack/pr/785?autoLogin=true&ref=codesmith_pr_footer">Open in [code]smith</a> · Need help on this PR? Tag <code>@codesmith-bot</code> with what you need.</sup> <!-- codesmith:autofix:disabled --> <!-- /codesmith:footer --> --------- Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
…HACK-2190) (#793) ## Problem and behavior No CI workflow previously exercised the documented upgrade from a v4 home. Add a reusable historical-byte fixture and compiled-CLI regression for Doctor, tracked-file consent, migration, env resolution and legacy store retirement. The fixture covers live/dead registry entries, healthy/lost global store keys, a project store reusing its live project key, tracked/untracked Git files and a linked worktree. It checks the exact changed-file inventory, every declared value, live-key preservation and sentinel-free output/journals. The same command/snapshot helpers can drive the upgrade assistant as it lands. The stable updater now verifies the release inventory and selected version before installation, streams bounded downloads and retries transient failures from fresh files. It stages full assets, preserves extra installed assets, installs the matching compiler and replaces the CLI last. Caught publication failures restore previous files; successful updates retain previous files with a private manifest containing paths and hashes. Native prerelease transfers use the same bounded retry/cancellation implementation, preserve their existing hashes/signatures, reclaim recognized private abandoned stages and gain reversible uninstall with read-only preview. Uninstall retains the whole channel and its user homes; it never recursively deletes candidate data.  Sources: [diagram](docs/reference/update-publication.mmd), [upgrade/recovery contract](docs/guides/upgrading-from-v4.md). ## Validation - Pinned Bun: **142 tests pass, 1,199 assertions, eight focused files**, including existing updater/manager/download/shard regressions. - Root `bun run typecheck`, `bun run check`, explicit changed-test/script lint, and production `bun run build` pass. The updater's version parser also runs against the real compiled current CLI output. - **#769 negative control:** the exact reverse patch no longer applies after subsequent cleanup receipt changes. Locally disabled its shared live-input predicate instead: the new compiled upgrade test failed **both cases**, because migration removed `.hack.secret.key` (ENOENT at the preservation assertion). Restored the source byte-for-byte; both positive cases pass. No mutation is included. - Loopback server cases cover interrupted/truncated transfer, HTTP 503 retry, offline, checksum/wrong-version refusal, stalled body and uncertain cancellation. Four thrown publication faults roll back. Two real child-process SIGKILL cases, after asset and compiler publication, leave the previous built CLI able to rerun `update --yes` successfully against the fixture server; compiler tripwire verifies the rerun does not need it. - Release-layout fixture calls the **actual release archive producer**, then consumes it through the current updater and the v4-compatible directory contract. - Both new test files are explicitly in the normal Linux and macOS pools; shard coverage verifies all 761 files. Hosted macOS execution remains external evidence. ## Hosted integration correction The first hosted run exercised the merge with #764, whose private-write staging landed after the original local base. The upgrade snapshot correctly caught four new self-ignoring staging markers per case. Merge current next and name those exact paths; assert their contents, Git ignore behavior and empty staging inventory. The remaining file-for-file, key, value and sentinel assertions stay intact. The merged tree passes the 142-test qualification and the #769 negative control still fails both cases before byte-identical restoration. ## Boundaries and release signal `fix`: updater integrity and recovery corrections; no CLI migration or required-check change. The ordinary light PR policy still reports selected macOS files as deferred; this PR changes protected CI planning inputs, so it requests full hosted coverage automatically. Stable origin trust remains official GitHub HTTPS plus checksums, not a publisher signature. The swap across several directories is not power-loss atomic; the process-kill rerun tests do not prove filesystem durability or hostile external-writer safety. Completed backups remain until the user disposes of them, and docs give their location and safe disposal point. Older installed v4 updater code retains its old behavior; preserving the release layout protects its compatibility independently. Native runtime applications and published downloads are not exercised by hermetic fixtures. The existing installer model coverage gap is recorded, not presented as formal verification. HACK-2190 Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
The next.17 section omitted the tmux breaking-change warning that already existed at the page tail. Move it into the release section and put its v4 stop procedure before the v5 trial. The env breaking entry was already correct; keep its scoped single-key/terminal/stdin migration guidance. Audit all **71 commits** from `v5.0.0-next.16` (`b21c3b1898`) through candidate **`5002cf87bb50686b17ceae8a4c835f524ee1b3a5`** against merged code and PR text. Add missing upgrade-assistant, activity, observe/plan/version, interactive exec, recovery, background-command and host/secret-custody notes. Preserve the complete native env-file behavior table and mark the four new JSON contracts **shape may change before 5.0.0**, with the planned HACK-2238 envelope migration. Correct stale native interactive-exec/network/metadata/Ctrl-C claims and the short upgrade assistant wording. Credit the publisher-shutdown fix to #719, already in next.16; keep next.17 lifecycle-command retirement separate. Retake a private stopped-state backup after v4 stops zellij, keeping the first copy too. Keep next.16 warnings scoped to that bundle. Keep original-key backups before older Doctor migrations and distinguish file rollback from runtime/data recovery. Only eight Markdown files change. Runtime, tests, workflows, generated CLI reference, diagrams, immutable snapshots and the site pin are unchanged. No diagram changed, so a new visual would add nothing. The site re-pin remains a separate release follow-up. Merge timing: respect the lead's candidate freeze; intended for the batch immediately after next.17 publication and the site re-pin. The moved tmux breaking-change notice is called out for the lead's pre-cut decision. This PR does not merge or publish anything. Validation at **`d95cfc554fabc4a0d70e3ba6caeb6746f63a198c`**: - Bun 1.4.4, frozen dependencies. Docs prepare/check/typecheck/build and site tests (2 passed, 25 assertions) pass. Production-mode HTTP smoke: 97 docs, 82 SVGs, 217 local links/anchors; task server stopped. - All 50 Hack commands named anywhere in the notes exist in the current generated CLI reference; 19 option contracts checked. CLI-reference regeneration has no diff. - All 71 commits have one row below, including the test commit and merge for #786. All 70 source evidence paths exist at the fixed candidate. Source release-note local links/anchors pass. - Privacy and complete reachable-history Gitleaks pass (1,330 commits, no findings). Persistent Claude Opus second-family review is CLEAN at this exact head. Hosted run 43585059152 passed docs site, secret scan and every planned Linux unit shard (4–8), plus the required test fan-in. Typecheck/privacy/quality ran on shard 8. Focus had no selected tests. Compiler, native core, runtime images/models, process-lifetime and Docker execution were out of scope; a green Docker fan-in is not Docker execution evidence. All bot comments were read; CLEAR at d95cfc5, zero unresolved threads/change requests. Codex code/security reviews found no issues. - No real install, migration, daemon/DNS/trust change, Docker or native VM run was performed for this documentation audit. Native acceptance and the candidate's hosted release qualification remain separate. ## Candidate commit coverage `entry present` means the behavior already had an entry within the next.17 section (some now have fuller detail). `added` means missing behavior or migration guidance was added there; #824 moves the existing warning into that section. `not user-visible` means no shipped CLI/runtime change: documentation, test/CI/repository housekeeping or the internal desktop preview. Source links pin the candidate, rather than a moving branch. | Commit / PR | Coverage | Entry or reason | Audited source | | --- | --- | --- | --- | | [70d328e](70d328e) [#743](#743) | added | Host setup: privileged/NSS safeguards | [src/lib/linux-trust-setup.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/linux-trust-setup.ts) | | [51f15c8](51f15c8) [#746](#746) | not user-visible | Docs-only upgrade checklist and site generation; no installed behavior | [scripts/docs/prepare.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/docs/prepare.ts) | | [c14f3f5](c14f3f5) [#744](#744) | added | Native setup JSON accounting | [packages/runtime-core/src/provider/setup.rs](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/packages/runtime-core/src/provider/setup.rs) | | [b0c6bcd](b0c6bcd) [#705](#705) | added | Retained background exec/run and cursor tools | [src/commands/background-command-start.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/background-command-start.ts) | | [c89f4fd](c89f4fd) [#745](#745) | added | Linux daemon query/home refusals | [src/commands/daemon-systemd.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/daemon-systemd.ts) | | [cce4b59](cce4b59) [#752](#752) | not user-visible | Site pin/snapshots and editorial pages only | [scripts/docs/versions.json](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/docs/versions.json) | | [56676fc](56676fc) [#754](#754) | added | Setup reuse/offline accounting; pin-watch changes are internal | [packages/runtime-core/src/provider/setup.rs](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/packages/runtime-core/src/provider/setup.rs) | | [7a496f1](7a496f1) [#755](#755) | added | MCP registered selectors and background tool guidance | [src/mcp/server.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/mcp/server.ts) | | [e7a7039](e7a7039) [#747](#747) | entry present | Native follow text shape; added session ends/restart recovery | [src/backends/native-log-follow.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/backends/native-log-follow.ts) | | [87a6df5](87a6df5) [#758](#758) | added | Compose short one-shot startup | [src/lib/compose-startup-state.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/compose-startup-state.ts) | | [2afb5c4](2afb5c4) [#761](#761) | added | Native Hack networks and inert generated labels | [src/lib/native-hack-compose-conventions.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/native-hack-compose-conventions.ts) | | [342a585](342a585) [#771](#771) | not user-visible | Docs-only next.16 trial record | [docs/versions/v5/guides/upgrade-from-v4.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/versions/v5/guides/upgrade-from-v4.md) | | [6f0acf1](6f0acf1) [#769](#769) | entry present | Migration live-key/alias preservation | [src/lib/project-env-config.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/project-env-config.ts) | | [c96c444](c96c444) [#756](#756) | added | Child key filtering, fixed diagnostics, legacy ignore/YAML API refusals | [src/lib/child-environment.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/child-environment.ts) | | [e2c73c6](e2c73c6) [#748](#748) | not user-visible | Contributor CI selection/coalescing, outside product release notes | [scripts/ci-change-scope.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/ci-change-scope.ts) | | [ebf794e](ebf794e) [#760](#760) | added | Agent/output custody warning; runtime unchanged | [src/agents/instruction-source.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/agents/instruction-source.ts) | | [021b16b](021b16b) [#763](#763) | added | One-pass background redaction scan; no public benchmark claim | [src/lib/background-command/output-scanner.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/background-command/output-scanner.ts) | | [8564ec4](8564ec4) [#765](#765) | added | Shared preflight/start admission and detached failure reporting | [src/backends/native-project-review.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/backends/native-project-review.ts) | | [0c0fba2](0c0fba2) [#767](#767) | entry present | Breaking env exposure/protect/stdin/scope/API guidance | [src/commands/env.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/env.ts) | | [9435da9](9435da9) [#762](#762) | added | Local Git/link refusals and no-follow dotenv | [src/lib/project-env-config.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/project-env-config.ts) | | [edf23ae](edf23ae) [#753](#753) | added | Daemon stop proves the live Hack home | [src/commands/daemon-systemd.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/daemon-systemd.ts) | | [573ceec](573ceec) [#766](#766) | entry present | Doctor layer/integrity error; added store/key write refusals | [src/lib/secret-store.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/secret-store.ts) | | [a0e9760](a0e9760) [#757](#757) | added | Orphan output truncation and final-sync evidence | [src/lib/background-command/recovery.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/background-command/recovery.ts) | | [10e1958](10e1958) [#759](#759) | added | Private lifecycle logs/FIFO and expiring mux payloads | [src/lib/private-file.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/private-file.ts) | | [bd899ee](bd899ee) [#775](#775) | not user-visible | Portable test fixtures only | [tests/single-file-tar.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/single-file-tar.test.ts) | | [80dae3d](80dae3d) [#776](#776) | added | Candidate missing-daemon diagnosis is optional/healthy | [src/commands/doctor.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/doctor.ts) | | [5b2a2d0](5b2a2d0) [#772](#772) | added | Bounded attaching-network retry; strict saved reads remain | [src/lib/native-compose-ownership.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/native-compose-ownership.ts) | | [ab29d49](ab29d49) [#777](#777) | not user-visible | CI scheduling only | [docs/reference/ci-test-selection.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/reference/ci-test-selection.md) | | [31339c7](31339c7) [#770](#770) | entry present | Native inferred readiness, 240 s, HTTP/service_healthy limits | [packages/runtime-core/src/project/compose/service.rs](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/packages/runtime-core/src/project/compose/service.rs) | | [156ee7f](156ee7f) [#773](#773) | entry present | Loopback proxy port/Doctor/open checks | [src/lib/proxy-loopback.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/proxy-loopback.ts) | | [a7ec3c7](a7ec3c7) [#768](#768) | entry present | Cleanup receipts/partial outcomes and tracked-file wording | [src/lib/project-env-config.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/project-env-config.ts) | | [ceb3e23](ceb3e23) [#778](#778) | entry present | Native bridge socket readiness | [packages/runtime-core/src/provider/bridge.rs](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/packages/runtime-core/src/provider/bridge.rs) | | [af91049](af91049) [#783](#783) | entry present | Pointer reconciliation after partial cleanup | [src/commands/doctor.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/doctor.ts) | | [0a0bfdb](0a0bfdb) [#780](#780) | not user-visible | Site-only Linux guide publication; no CLI behavior | [scripts/docs/versions.json](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/docs/versions.json) | | [d0cf767](d0cf767) [#786](#786) | not user-visible | Consent test wording only (both commits) | [tests/env-migration-tracked-consent.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/env-migration-tracked-consent.test.ts) | | [7e2e630](7e2e630) [#786](#786) | not user-visible | Consent test wording only (both commits) | [tests/env-migration-tracked-consent.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/env-migration-tracked-consent.test.ts) | | [91c311e](91c311e) [#779](#779) | entry present | Restore or reversible retire; missing store keys scoped to readers | [src/lib/secret-store-retire.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/secret-store-retire.ts) | | [6ab1ace](6ab1ace) [#785](#785) | not user-visible | Docs-only release/upgrade/env notes | [docs/guides/v5-release-notes.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/guides/v5-release-notes.md) | | [25bd63c](25bd63c) [#764](#764) | entry present | Doctor hygiene, local modes, ignored staging and live-input protection | [src/lib/secrets-hygiene.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/secrets-hygiene.ts) | | [d9df57c](d9df57c) [#784](#784) | not user-visible | Resolver/proxy and consent test corrections only | [tests/project-open-loopback.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/project-open-loopback.test.ts) | | [2c1f665](2c1f665) [#791](#791) | added | Detached failure names, open DNS hint, init placeholder; prune guidance | [src/commands/project.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/project.ts) | | [f6fe55f](f6fe55f) [#787](#787) | not user-visible | Docs-only retirement/hygiene follow-up | [docs/guides/v5-release-notes.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/guides/v5-release-notes.md) | | [7f9548c](7f9548c) [#792](#792) | not user-visible | Start-here docs, navigation and contributor rule only | [docs/versions/v5/install.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/versions/v5/install.md) | | [a0cfc73](a0cfc73) [#793](#793) | added | Verified updater publication, backups and reversible candidate removal | [src/lib/self-update.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/self-update.ts) | | [292d312](292d312) [#782](#782) | added | Lock-free native ps and proved failed-start down | [src/backends/native-project-observe.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/backends/native-project-observe.ts) | | [b1e123b](b1e123b) [#796](#796) | added | Doctor reader count/worktree grouping in store recovery | [src/lib/doctor-secret-integrity.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/doctor-secret-integrity.ts) | | [286d00f](286d00f) [#789](#789) | added | Foreground command-before-wrapper retirement | [src/lib/project-lifecycle-processes.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/project-lifecycle-processes.ts) | | [bb6a7d1](bb6a7d1) [#788](#788) | not user-visible | Linux qualification runbook only | [docs/guides/linux-host-qualification.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/docs/guides/linux-host-qualification.md) | | [a262d42](a262d42) [#800](#800) | not user-visible | Internal desktop design; outside supported CLI release scope | [apps/desktop/DESIGN.md](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/apps/desktop/DESIGN.md) | | [6b161ba](6b161ba) [#774](#774) | added | Native interactive exec, finite fallback and receipt recovery | [src/backends/native-project-exec.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/backends/native-project-exec.ts) | | [1249272](1249272) [#799](#799) | not user-visible | Portable output-contract CI selection only | [scripts/test-shard-plan.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/test-shard-plan.ts) | | [fa3f03d](fa3f03d) [#790](#790) | added | Read-only upgrade check, snapshot and rollback | [src/commands/upgrade.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/upgrade.ts) | | [c3b79bc](c3b79bc) [#807](#807) | added | Observe-only global status and unknown evidence | [src/commands/global-status-observe.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/global-status-observe.ts) | | [29be043](29be043) [#812](#812) | added | Read-only local CA trust diagnosis | [src/lib/ca-trust-status.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/ca-trust-status.ts) | | [f0102fd](f0102fd) [#814](#814) | not user-visible | Prepared-base verifier test fixture only | [tests/qualify-provider-pin.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/qualify-provider-pin.test.ts) | | [b4ebfec](b4ebfec) [#815](#815) | added | Compact upgrade plan, snapshot-backed apply/resume | [src/lib/upgrade-apply.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/upgrade-apply.ts) | | [c44b266](c44b266) [#801](#801) | not user-visible | Internal optional desktop preview; not shipped CLI behavior | [apps/desktop/Cargo.toml](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/apps/desktop/Cargo.toml) | | [56d1d0f](56d1d0f) [#804](#804) | added | Automatic mux sweep preserves live/retired config inputs | [src/lib/live-inputs.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/live-inputs.ts) | | [1958363](1958363) [#805](#805) | added | MCP timedOut result and Codex installer timeout | [src/mcp/server.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/mcp/server.ts) | | [e6207e8](e6207e8) [#810](#810) | added | Lifecycle activity writes including handler refusals; activity JSON | [src/commands/lifecycle-activity.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/lifecycle-activity.ts) | | [23fe08f](23fe08f) [#825](#825) | added | Read-only batch review and permission-only key repair | [src/lib/upgrade-review.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/upgrade-review.ts) | | [cab596c](cab596c) [#781](#781) | entry present | Full native env-file behavior table; added support/precedence summary | [src/backends/native-compose-environment.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/backends/native-compose-environment.ts) | | [1e84684](1e84684) [#798](#798) | not user-visible | Rust test process isolation/nextest; internal qualification only | [scripts/test-runtime-core.sh](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/scripts/test-runtime-core.sh) | | [518af29](518af29) [#817](#817) | not user-visible | Remove accidental empty checkout files; no installed CLI change | [.gitignore](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/.gitignore) | | [07192f7](07192f7) [#824](#824) | added | BREAKING warning moved from page tail into next.17; v4 stop procedure retained | [src/mux/mux-config.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/mux/mux-config.ts) | | [fe09a5b](fe09a5b) [#816](#816) | added | Read-only install/trust admin plans and exits | [src/commands/global.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/global.ts) | | [8977676](8977676) [#827](#827) | added | Registry-preserving project observe, runtime opt-in | [src/commands/projects.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/commands/projects.ts) | | [5965b23](5965b23) [#828](#828) | added | Running CLI version identity JSON | [src/lib/version-report.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/version-report.ts) | | [2922210](2922210) [#830](#830) | added | Upgrade safe/admin/manual action kinds | [src/lib/upgrade-action-kind.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/upgrade-action-kind.ts) | | [51b55c0](51b55c0) [#820](#820) | not user-visible | Archive/plan/shared-helper verification fixtures only | [tests/python-free-download.test.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/tests/python-free-download.test.ts) | | [5002cf8](5002cf8) [#809](#809) | added | Retirement read retry, second Ctrl-C and native cancellation cleanup | [src/lib/project-lifecycle-processes.ts](https://github.com/hack-dance/hack/blob/5002cf87bb50686b17ceae8a4c835f524ee1b3a5/src/lib/project-lifecycle-processes.ts) | --------- Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
Legacy migration cleanup could remove
.hack.secret.keywhen an encrypted-file backend reused it as its own key file. The migration encrypted YAML entries with that key, then offered the same file for deletion. Removing it made the migrated entries unreadable.Cleanup candidate selection now excludes live project inputs: the local, shared Git and primary-checkout project keys, YAML env layers and project config. Paths and device/inode identities protect aliases through symlinked directories, hard links and case-insensitive spellings. Both
.hackand legacy.devinputs are covered. The deletion boundary independently refuses any request containing a live input before removing any files, and rechecks before each unlink. The env guide states that legacy backend configuration cannot make those files disposable.The real-files regression fails against
nextatcce4b5954a4b1889b095bda796bea561142d6b52: cleanup removes the reused key and the next YAML read throwsProjectEnvKeyMissingError. With this change the legacy store and contract are removed, the key remains and the migrated value decrypts. A second regression covers shared/local keys, YAML/config candidates, and refusal before an earlier ordinary file can be deleted. Fixtures use synthetic values and temp directories only.Validation: pinned Bun typecheck and lint pass; five regressions pass (40 assertions), and all 60 focused project-env-config cases pass. The regression includes a real migration through a symlinked parent and a legacy
.devdeletion guard. Case-variant coverage runs when the fixture filesystem supports it; no macOS qualification is claimed. The selector chooses 677 files; the full compiler-dependent local suite is unavailable, so hosted Linux CI remains the wider gate. No host Docker or real credential state was used.This is an urgent, independent HACK-2172 fix directly against
next, ahead of #756/#767/#768. F10 content/identity receipts and broader cleanup failure reporting remain in #768. No history rewrite or merge is performed by this session; lead review remains required.