Skip to content

fix(env): secrets at rest: ignored staging, tightened modes, expiring mux payloads, doctor secrets hygiene (HACK-2165) - #764

Merged
roodboi merged 49 commits into
nextfrom
claude/hack-2165-secrets-at-rest
Nov 13, 2026
Merged

roodboi merged 49 commits into
nextfrom
claude/hack-2165-secrets-at-rest

Conversation

@roodboi

@roodboi roodboi commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Second of two PRs for HACK-2165 (umbrella HACK-2163): audit findings F1 and S1, lead items 1, 2, 3 and 5, and the hack doctor "secrets hygiene" section as the migration path. The first PR is #762 (F3, F4, F5); please merge this one after it. Item 4 (encrypted-file backend links and key cache) moved to HACK-2169 and is not here.

F1 and item 2: no committable copies of keys or env files

  • Staging leftovers. Private writes (.hack/.env files, .hack.secret.key, the encrypted store and its key) staged their contents in a .<name>.<uuid>.tmp sibling that no ignore entry matched, so a crash could leave a copy for git add -A. They now stage in .hack-staging/ next to the target. That directory is private (0700), and it holds a .gitignore of * that exists before any staging file, so git never lists anything in it, without changing any project ignore file. The rename stays on the same filesystem. The next write there removes leftovers older than ten minutes, plus older versions' siblings for the same target. A linked or shared staging directory is refused. Writers whose directories must hold only their own files (background commands, shared-host claims, the .internal compose override) keep sibling staging. .hack-staging/ stays in the directory afterwards, holding only its .gitignore.
  • Weak-key remedy. It no longer says mv .hack.secret.key .hack.secret.key.old (an unignored name). It now says to keep a 0600 copy outside the worktree (~/.hack/retired-keys/) until every secret is re-added, and to re-add with --value-stdin or the hidden prompt, never as argv. One other doctor hint that suggested --secret KEY VALUE is fixed too.

S1 and item 1: loose machine-local layers

  • A machine-local write drops group and other bits from an existing layer. The staging copy gets the tightened mode before any content is written, and a write that changes nothing tightens the file in place. Shared layers keep their mode. HACK-1680 had kept an existing layer's mode; its test now asserts the tightening.
  • Commands that read env layers (env, the up and run paths, session) warn once per file on stderr about a loose machine-local file. The warning names the file and its mode, and is printed after a successful read, so refusals stay one line.

Item 3: terminal-session env payloads

Payloads in $TMPDIR/hack-mux-env-*/env.json now expire after ten minutes. The pane refuses and removes an expired one. The staging process removes its payload when the time limit passes, if it is still running, and the next staging sweeps this user's older payloads.

Item 5 and the migration path: hack doctor "secrets hygiene"

This section covers the project and the global Hack home, and names files, never values. It reports:

  • secret-bearing files that are loose, links, owned by another user, tracked, or unignored;
  • staging leftovers;
  • stale terminal payloads;
  • a store that is present while its key file is missing: "store present, key missing, cannot be read".

hack doctor --fix tightens modes (through a no-follow handle, only while the file is still the one found), adds missing ignore entries, and removes Hack's own leftovers. It prints each change. It never deletes a store, a key or a user's file, and it never untracks a file. docs/guides/upgrade-to-v5.md gains an "after upgrading, check secrets at rest" step; docs/env.md and the threat model describe the behaviour.

Merge ordering and overlap

Validation

  • New tests, all with temp directories and sentinel values:
    • the staging directory, including a git control showing an interrupted key publication leaves nothing to stage;
    • the sweep, and refusal of linked or shared staging directories;
    • tightening on write and on unchanged writes;
    • the read-time warning;
    • payload expiry and sweep;
    • each hygiene finding and fix, including that --fix never deletes a store.
  • Local, pinned Bun 1.4.4: typecheck, lint, privacy:check, docs:check and gitleaks pass. 162 test files that import the changed modules ran.
    • The failures are all in native and adoption files. They fail the same way without these changes on this host: they need the compiled config compiler, or hit native-state refusals here.
    • Hosted CI runs the full suite.
  • Not run: a real macOS keychain, a real store or key, or a reboot.

🤖 Generated with Claude Code


Prove it works
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

roodboi and others added 5 commits November 13, 2026 06:49
…rotation advice (HACK-2165)

Audit F1 and lead item 2:
- A private write (.hack/.env files, the project key, the encrypted
  store and its key) staged its complete contents in a
  `.<name>.<uuid>.tmp` sibling that no ignore entry covers, so a crash
  could leave a copy git would stage. Staging now happens in
  `.hack-staging/` next to the target: a private (0700) directory
  whose `.gitignore` of `*` exists before any staging file, so git
  never lists a leftover. The next write there sweeps leftovers older
  than ten minutes, and staging siblings from earlier versions of the
  same target. A linked or shared staging directory is refused.
  Store-internal writers (background commands, shared-host claims,
  the .internal compose override) keep sibling staging.
- doctor's weak-key remedy said `mv .hack.secret.key
  .hack.secret.key.old` (a name git does not ignore) and to re-add
  secrets as argv values. It now keeps a 0600 copy of the old key
  outside the worktree until every secret is re-added, and re-adds
  with --value-stdin or the hidden prompt.

Co-Authored-By: Claude <noreply@anthropic.com>
… read (HACK-2165)

Audit S1 and lead item 1: a machine-local layer that predates private
creation, or was made by hand, kept mode 0644 through writes, and its
staging copy took that mode before the contents were written. A
machine-local write now drops group and other bits from an existing
layer, before the staging copy holds any content, and a write that
changes nothing tightens the file in place. Shared layers keep their
mode. Commands that read env layers (env, up/run paths, session) warn
once per file on stderr about a loose machine-local file, after a
successful read so a refusal stays one line. HACK-1680's keep-mode
test now asserts the tightening.

Co-Authored-By: Claude <noreply@anthropic.com>
…K-2165)

Lead item 3: values staged in $TMPDIR/hack-mux-env-*/env.json stayed
there when the pane never ran its command. A payload now expires after
ten minutes: the pane refuses and removes an expired one, the staging
process removes its payload when the limit passes (if it still runs),
and the next staging sweeps this user's older payloads. Tests stage
in a private directory, never the host's temporary directory.

Co-Authored-By: Claude <noreply@anthropic.com>
Lead items 2 and 5 and the migration path: `hack doctor` reports, for
the project and the global Hack home, secret-bearing files (local
layers, .hack/.env files, project keys, encrypted store and key) that
are loose, linked, owned by another user, tracked, or unignored;
staging copies left by interrupted writes; terminal-session payloads
that never ran; and "store present, key missing, cannot be read".
`hack doctor --fix` tightens modes, adds missing ignore entries and
removes Hack's own leftovers, printing each change; it never deletes a
store, a key or a user's file, and never untracks. A doctor hint no
longer suggests a secret value in argv. Docs: the env guide, the
threat model, and an "after upgrading" step in the v5 upgrade guide.

Co-Authored-By: Claude <noreply@anthropic.com>
…ACK-2165)

Keeps writeTextFileAtomicIfChanged under the complexity limit after
tightenExisting; no behavior change.

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel

vercel Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hack-docs Ready Ready Preview Nov 13, 2026 7:15pm UTC

Request Review

@linear-code

linear-code Bot commented Nov 13, 2026

Copy link
Copy Markdown

HACK-2165

…e layer staging (HACK-2165)

Own-reviewer round on d74187c:
- An existing `.hack-staging/.gitignore` (for example one a repository
  committed, checked out 0700 under umask 077) was trusted unread. It
  is now accepted only as a regular file of the user's holding exactly
  `*`; anything else refuses the write, so no staging copy can be
  visible to git.
- The rotation remedy's `install` into a fixed name overwrote an
  earlier retired key. It now copies to a unique mktemp name and
  removes the key only once the copy is written.
- Machine-local layer writes (writeTextFileAtomicIfChanged with
  tightenExisting) still staged as `.<name>.<uuid>.tmp` siblings, which
  only Hack's managed block ignores. They now stage in the private
  directory too; shared layers keep sibling staging.
- Committed dotenv templates (.env.example, .sample, .template, .dist)
  are no longer reported as secret-bearing.
- Tightening an unchanged layer is best effort (another user's file
  keeps working), and a missing store key is a warning on macOS while
  the keychain may still hold it.

Co-Authored-By: Claude <noreply@anthropic.com>
@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-13T19:17:39.058880Z cbcaf53 Manual request
🔒 Security Review ✅ Completed 2026-11-13T19:23:23.528497Z cbcaf53 Manual request

Security findings

Advisory findings (10)

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d8719bdac7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread src/lib/private-staging.ts Resolved
Comment thread src/lib/secrets-hygiene.ts Resolved
@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: d8719bdac7

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ 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.

…oject stores (HACK-2165)

Bot review on d8719bd:
- Concurrent first private writes in one directory could read the new
  `.hack-staging/.gitignore` before its creator wrote `*` and refuse.
  The ignore file is now staged complete and linked into place, so it
  never exists partially and a crash cannot leave an empty one.
- An encrypted store or key configured inside the project checkout
  skipped the git checks. Such files are now checked like the
  project's own secrets (tracked is an error; unignored gets an
  anchored root .gitignore entry); files outside it stay exempt.

Co-Authored-By: Claude <noreply@anthropic.com>
@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e060a3e36

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread src/lib/private-staging.ts Resolved
Comment thread src/lib/secrets-hygiene.ts Resolved

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛡️ Codex Security Review · Automatically triggered

Here are some automated security review suggestions for this pull request.

Reviewed commit: 9e060a3e36

ℹ️ 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.

Comment thread src/lib/secrets-hygiene.ts Resolved
roodboi and others added 2 commits November 13, 2026 07:31
…ene refuses a linked .hack (HACK-2165)

Bot review on 9e060a3:
- On ExFAT/FAT, chmod cannot make the staging directory 0700, so every
  private write there was refused, regressing the documented first
  secret on such a drive. A staging directory of the user's own is now
  made 0700, and accepted at the mount-wide mode when the filesystem
  ignores chmod; a link or another user's directory is still refused,
  and the identity is re-checked before publishing.
- doctor's secrets hygiene followed a `.hack` linked outside the
  project, so --fix could chmod or delete files there. A linked or
  non-directory `.hack` is now reported and not inspected, and every
  fix carries the identity of the directory it changes, checked again
  before the change (an ignore entry is never appended through a
  directory swapped after inspection).

Co-Authored-By: Claude <noreply@anthropic.com>
…ct (HACK-2165)

Bot security review on 9e060a3: a configured store or key under an
in-project directory whose name begins with `..` (for example
`..secrets/`) gave a relative path starting with "..", which was read
as outside the project, so its git checks were skipped. Outside now
means a `..` path segment or an absolute path.

Co-Authored-By: Claude <noreply@anthropic.com>
@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 9ff7fb0892

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛡️ Codex Security Review · Automatically triggered

Here are some automated security review suggestions for this pull request.

Reviewed commit: 9ff7fb0892

ℹ️ 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.

Comment thread src/lib/secrets-hygiene.ts Resolved
…out or Hack home (HACK-2165)

Bot security review on 9ff7fb0: a cloned repository's committed
hack.config.json can point encryptedFile.path/keyPath at any file of
the user's, and `hack doctor --fix` would then chmod it or remove old
`.<name>.<uuid>.tmp` files beside it. Paths that only the project's
configuration chose are now fixed, and their leftovers swept, only when
their directory resolves (links followed) inside the checkout or the
Hack home; elsewhere the finding is reported without a fix. The global
configuration's paths are the user's own and keep their fixes.
inspectSecretsHygiene is split into per-part helpers (no behavior
change) to stay under the complexity limit.

Co-Authored-By: Claude <noreply@anthropic.com>
@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 553731fef3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛡️ Codex Security Review · Automatically triggered

Here are some automated security review suggestions for this pull request.

Reviewed commit: 553731fef3

ℹ️ 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.

Comment thread src/lib/secrets-hygiene.ts Resolved
roodboi and others added 2 commits November 13, 2026 08:19
…165)

Bot security review on 553731f: a project-configured store or key
inside the checkout but spelled through an alias (a link to the
checkout, or another case on a case-insensitive disk) gave a relative
path leaving the root, so its git checks were skipped. Containment now
compares the resolved file directory with the resolved root, and git
is asked about the resolved spelling.

Co-Authored-By: Claude <noreply@anthropic.com>
…ectory (HACK-2165)

Own-reviewer round on f00c17c: on a case-insensitive disk a store or
key named `Store.key` in the configuration while git tracks
`store.key` kept the configured case, so git's exact-case tracked
check missed it. A regular file is now resolved itself (realpath of the
file), so git is asked about its stored name; a link at the final
component is still not followed.

Co-Authored-By: Claude <noreply@anthropic.com>
@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 40d6f8ee62

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread src/lib/secrets-hygiene.ts Resolved
Comment thread src/lib/private-staging.ts Resolved
@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

Ready for lead: #764 (HACK-2165, secrets at rest), head 6af2a480.

Second-family review: Codex reviewer thread, clean at this exact head (round 17): /home/hack/scratch/review-codex-764-6af2a480.md. Rounds 3–16 fixed every blocker and should-fix. The first report (66e28c5: live-key cleanup blocker + 4) was closed in rounds 1–2.

Guard against deleting live inputs (HACK-2172 class): removalStillSafe in src/lib/secrets-hygiene.ts runs just before every hygiene unlink, for both leftovers and stale terminal payloads. It refuses the exact target when the target is a live input (configured stores and keys, the project/shared/primary-worktree keys, hack.config.json, YAML layers; by given or resolved path) in either the inspected scope or the configuration resolved again strictly at that moment. It also refuses when either set can't be determined. Proven by tests/secrets-hygiene.test.ts:

  • "a leftover the configuration selects after inspection is kept by --fix"
  • "a configured key inside a stale terminal payload directory is never removed"
  • "an env input current resolution reads is never removed…"

and by tests/secrets-hygiene-scope.test.ts: "--fix removes nothing while the configuration that would name a file cannot be read". Each fails without the guard.

Merges: real merges of next: a7ec3c7 (74a2e6f; only conflict was in the threat-model doc) and 0a0bfdb (6af2a48, clean). #762's noFollowTarget and reader identity checks, #769's live-input guard, #767's value-free listing, #756's child-key filter, #766 and #768 are kept, with tightenExisting and private staging. The mux payload expiry now uses #759's implementation.

Bot threads: all answered and resolved. computer pr review-status: CLEAR at 6af2a48026. Codex code and security reviews at this head found nothing.

CI at this head: green: Linux shards 4–8 (typecheck, privacy, lint in shard 8), test focus, docker-e2e, docs site, secret-scan. Not run (light PR): macOS shards 1–3, config compiler, candidate core, docker-e2e shards, runtime models/images, linux-process-lifetime.

  • Shard 7 failed once at 385b638 in tmux-private-input (next's file, unchanged). It passed at the heads before and after, so I'm treating it as a flake.

Follow-ups:

  • Needs a ticket (I can't file in Linear from here): the inherited automatic pre-staging mux sweep (fix(lifecycle): private, no-follow lifecycle logs, a private FIFO, and expiring mux env payloads (HACK-2170) #759/HACK-2170, sweepStaleMuxEnvironments) deletes by name, age and ownership without consulting configuration. It is outside the doctor guard, and the threat model says so.
  • Case-insensitive filesystems: one regression ("…checked under its stored case") runs only there. It returns early on Linux, so it needs a macOS run.
  • Previously accepted: older umask-dependent creates, empty self-ignore on no-hard-link filesystems, macOS extended ACLs, shared key via a .git file, overlapping legacy warnings, macOS case-folding qualification.
  • On this host, two env-migration-tracked-consent tests ("--accept-tracked-env-changes migrates…") also fail on plain next a7ec3c7 and 0a0bfdb; they are not from this PR.

#764 6af2a48

…ACK-2165)

findStaleMuxEnvironments built roots from the temp directory as given,
while stageMuxEnvironment returns realpath'd paths, so on macOS
(/var -> /private/var) the two named the same payload differently and two
tests comparing them failed. The finder now resolves its base once, so
hack doctor reports and removes payloads under the same spelling staging
uses.

The live-input check was already by resolved path (isLive compares the
target as given and resolved against inputs as given and resolved); a new
regression configures a key inside a stale payload by a linked temp
directory spelling and checks it is neither offered nor removed.

Regressions (a linked temp directory stands in for macOS /var on Linux):
stale roots equal the resolved staged path; a key configured through the
link survives inspection and --fix. Both fail without the change (the
second only on the reported spelling; its protection held before).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: 6172232d30

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 6172232d30

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ 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.

roodboi added a commit that referenced this pull request Nov 13, 2026
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>
roodboi and others added 2 commits November 13, 2026 18:56
#779 (HACK-2177, retiring a store whose key is gone) and this branch each
added resolveFileSecretStorePaths to src/lib/secret-store.ts; git merged
both without a textual conflict, leaving a duplicate declaration. One
definition remains: #779's, keeping its name and { active, storePath,
keyPath } result for secret-store-retire.ts, now with this branch's
opt-in strict mode (an unreadable or malformed configuration rejects
instead of defaulting), which hack doctor's removal check uses. Doctor
takes only storePath and keyPath from it for its hygiene scope.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…2165, HACK-2177)

A retired store (<store>.retired-<stamp>/, from #779) may hold the only
copy of values its key still opens. Hygiene's detectors never look inside
one, but the removal check now refuses any target whose path, as given or
resolved, has a retired-store component, both when findings are built and
just before the unlink, with or without a scope.

Regression: a store retired with retireEncryptedStoreFile survives
inspection and --fix, and a guarded removal offered for its archived file
(with and without a scope) is refused. It fails without the check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 334b3c134d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

…d (HACK-2165)

The retired-store and live-input checks treated a failed realpath of the
target as "no resolved spelling", so an alias into a retired store whose
resolution failed (EIO, say) passed both. Both now use realpathOrMissing:
only a missing target has no resolved spelling; any other failure makes
the target live and the removal is refused.

Regression: an alias directory to a retired store, realpath failing with
EIO for the target only, and a holding directory guard: the offered
removal is refused with and without a scope. It fails without the change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: f81a8ea59d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: f81a8ea59d

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ 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.

…t unknown (HACK-2165)

livePaths added each input's realpath when it could and silently skipped
it otherwise, so an alias whose resolution failed (EIO, say) left the
resolved file unprotected. It now uses realpathOrMissing: a missing input
has no resolved spelling, and any other failure makes the whole set
unknown, so nothing is removed.

Regression: a configured key reached through an alias directory whose
resolution fails, at a leftover-shaped real path: no removal is offered
and --fix keeps it. It fails without the change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: cbcaf530e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: cbcaf530e1

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ 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.

@roodboi

roodboi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

Ready for lead: #764 (HACK-2165), head cbcaf530, merged with next 6ab1ace.

Second-family review: Codex reviewer thread, clean at this exact head (round 21): /home/hack/scratch/review-codex-764-cbcaf530.md.

Since 6af2a48:

  • macOS /private/var (6172232). findStaleMuxEnvironments now resolves its temp directory once. Its roots, hygiene findings and remove_mux targets therefore use the spelling stageMuxEnvironment returns. I changed the product, not the tests. The live-input comparison was already by resolved path on both sides; a regression with a linked temp directory proves it on Linux.
  • feat(secrets): retire a store whose key is gone, and fail doctor only where the store is read (HACK-2177) #779 merge (cae44eb). There is now one resolveFileSecretStorePaths: feat(secrets): retire a store whose key is gone, and fail doctor only where the store is read (HACK-2177) #779's, with its name, export and { active, storePath, keyPath } result kept for secret-store-retire.ts. It gains this PR's opt-in strict mode, which doctor's removal check uses. Doctor takes only storePath and keyPath from it. I checked every caller: the retire module's three call sites (unchanged), doctor, and the scope tests.
  • Retired stores (334b3c1, f81a8ea, cbcaf53). removalStillSafe never removes anything inside a retired store (<store>.retired-<stamp>/), with or without a scope. It also refuses a target, or a live set built from an input, whose path can't be resolved for any reason other than "missing". Tests in tests/secrets-hygiene.test.ts:
    • "a retired store (HACK-2177) is never removed by hygiene, whatever offers it" (a real retireEncryptedStoreFile archive, then a guarded removal offered for it);
    • "a removal whose target cannot be resolved is refused, even through an alias to a retired store";
    • "a configured input whose alias cannot be resolved makes the live set unknown, not smaller".

Guard (updated): for doctor's remove_leftover and remove_mux fixes, removalStillSafe checks the live inputs both as inspected and with the configuration re-read strictly at removal time. A target is protected if it is an input's path as written or resolved, or anything in a retired store. If the scope, an input or the target itself can't be resolved, nothing is removed.

Tests at this head: the merged tree typechecks. On this Linux host, tests/secrets-hygiene*.test.ts, tests/mux-private-environment.test.ts, tests/secret-store*.test.ts (including #779's secret-store-retire), tests/doctor-*.test.ts and fixture-hermeticity: 336 pass. The 8 failures are the known host-limited adopted-project doctor tests, which need the native config compiler.

CI at this head: Linux shards 4–8 (typecheck, privacy, lint), test focus, docker-e2e, docs site and secret-scan are green. The macOS shards 1–3 and the other heavy jobs are skipped on this light PR. Bot threads: CLEAR at cbcaf530e1; Codex code and security reviews at this head found nothing.

Follow-ups: HACK-2181 (the automatic mux sweep, which doesn't consult configuration). Case-insensitive filesystem checks are covered by your macOS runs.

#764 cbcaf53

@roodboi
roodboi merged commit 25bd63c into next Nov 13, 2026
21 checks passed
@roodboi
roodboi deleted the claude/hack-2165-secrets-at-rest branch November 13, 2026 20:14
roodboi added a commit that referenced this pull request Nov 13, 2026
Document next.17 recovery for an old secret store whose key is lost, and
fold in merged #764's secrets-hygiene report and repairs. Users get two
choices—restore the original key or retire the store reversibly—and a
separate Doctor path for loose modes, staging leftovers and stale
terminal payloads.

Merged current `next` `d9df57c6` normally (no rebase). The conflict in
`docs/guides/upgrade-to-v5.md` keeps both hygiene and retirement
guidance. It replaces the old “separate change” wording and manual
store-deletion advice. These changes remain **intended for next.17**;
next.16's original behavior and key-backup warning stay explicit.

| Claim | Source at merged base `d9df57c6` |
| --- | --- |
| Doctor severity, registered readers and restore-or-retire choices |
[doctor-secret-integrity.ts](https://github.com/hack-dance/hack/blob/d9df57c626cb951d540ce23a41780275dbebd192/src/lib/doctor-secret-integrity.ts)
|
| Project selection, confirmation, `--allow-unchecked`, `--yes` and
value-free retirement output |
[secrets.ts](https://github.com/hack-dance/hack/blob/d9df57c626cb951d540ce23a41780275dbebd192/src/commands/secrets.ts),
[retirement
checks](https://github.com/hack-dance/hack/blob/d9df57c626cb951d540ce23a41780275dbebd192/src/lib/secret-store-retire.ts)
|
| Hygiene report, eligible mode tightening, project ignore entries,
removal guards and fresh configuration checks |
[secrets-hygiene.ts](https://github.com/hack-dance/hack/blob/d9df57c626cb951d540ce23a41780275dbebd192/src/lib/secrets-hygiene.ts),
[scope regression
tests](https://github.com/hack-dance/hack/blob/d9df57c626cb951d540ce23a41780275dbebd192/tests/secrets-hygiene-scope.test.ts)
|
| Ten-minute staging and terminal-payload age |
[private-staging.ts](https://github.com/hack-dance/hack/blob/d9df57c626cb951d540ce23a41780275dbebd192/src/lib/private-staging.ts),
[private-environment.ts](https://github.com/hack-dance/hack/blob/d9df57c626cb951d540ce23a41780275dbebd192/src/mux/private-environment.ts)
|
| Tracked cleanup consent and truthful outcomes |
[doctor.ts](https://github.com/hack-dance/hack/blob/d9df57c626cb951d540ce23a41780275dbebd192/src/commands/doctor.ts)
|

The hygiene repair removes group/other permission bits from eligible own
files; it does not promise to force every mode to exactly 0600. Removal
protects live stores, keys, config and YAML by path and resolved path,
keeps retired stores, and rechecks configuration before removing
anything. It never untracks files. Retirement remains a deliberate
separate operation, preserving the encrypted entries and explaining how
to put them back.

Validation at **`e5a88ea6af096c9fb12cffae3257975fa26b530b`**:
- Persistent reviewer: clean at the exact merge head.
- Only four docs differ from `next`; all runtime, test and script files
are byte-identical to `d9df57c6`.
- Bun 1.4.4: docs prepare/check/typecheck and production build pass.
Normal hooks pass with six existing complexity warnings in imported
code.
- Production HTTP smoke: 95 docs, 37 diagram blocks/74 SVGs and 184
local links/anchors pass. The rendered guide returns 200 with hygiene,
live-input protection and retirement guidance.
- Privacy/diff checks and complete reachable-history Gitleaks pass
(1,299 commits).
- Obsolete tracked-file cleanup quotation remains absent.

No live key/store, migration, daemon or native runtime was exercised. No
pin, snapshot, workflow or client changes. Lead owns batch merge and
deployment.

---------

Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
roodboi added a commit that referenced this pull request Nov 13, 2026
Give v5 a short start-here path, with the current first-run messages and
a cause/fix lookup for Doctor. Stable remains v4; v5 installs beside it.
The pages keep Compose selection and the shared/private home boundary
explicit.

| Page route (preview/local build until deployment) | What it covers |
Diagram |
| --- | --- | --- |
| `/docs/v5/install` | Channels, install/check/remove, select Compose,
routing setup | Install flow |
| `/docs/v5/getting-started` | Init or manual Compose adoption, review
files, up/open/logs/down | First-run sequence |
| `/docs/v5/upgrade` | Backup first, numbered trial steps and rollback |
Upgrade flow |
| `/docs/v5/native/start` | Setup consent, completed preflight,
start/stop and back to Compose | Native state chart |
| `/docs/v5/troubleshooting` | Finding/message → cause → next action |
Lookup table |

The index/sidebar expose the path. Existing URLs and legacy fragment
links remain valid. The long references remain, with repeated first-run
prose trimmed from the native guide. Contributor guidance now requires
behavior PRs to update the affected short page. Correct an inherited
claim that init automatically adopts Compose: it discovers app packages;
existing Compose services need a reviewed manual scaffold/copy path.

This head normally merges `next` `2c1f665157` and includes the requested
#791 messages:
- Compose `open` keeps the URL and adds the DNS hint: confirmed
`unresolved`, or macOS `unconfigured` when Hack's resolver is missing
and the lookup is unknown. The pages explain the older-suffix trap and
the same-CLI routing/domain remedies.
- `init --auto` warns when it generated the Bun `app` placeholder; edit
its image/command before starting. Discovery successes and explicit
manual/no-discovery choices do not get that notice.
- #764's hygiene report replaces the old “separate change” note,
including live-input/retired-store protection and configuration
rechecks.

**Release pins, immutable snapshots and diagram sources are unchanged by
the merge.** Newer behavior is marked as next.17 source, not retroactive
to next.16. The setup line remains isolated for HACK-2193, and manual
upgrade is marked for replacement by HACK-2189/HACK-2191.

Sources at merged base `2c1f665157e8645f79fe09812aca84448552e07a`:
[generated CLI
reference](https://github.com/hack-dance/hack/blob/2c1f665157e8645f79fe09812aca84448552e07a/docs/reference/cli.md),
[init/open
implementation](https://github.com/hack-dance/hack/blob/2c1f665157e8645f79fe09812aca84448552e07a/src/commands/project.ts),
[DNS
classification](https://github.com/hack-dance/hack/blob/2c1f665157e8645f79fe09812aca84448552e07a/src/lib/proxy-loopback.ts),
[hygiene
rules](https://github.com/hack-dance/hack/blob/2c1f665157e8645f79fe09812aca84448552e07a/src/lib/secrets-hygiene.ts),
[channel manager
CLI](https://github.com/hack-dance/hack/blob/2c1f665157e8645f79fe09812aca84448552e07a/scripts/install-prerelease.ts),
[native setup
CLI](https://github.com/hack-dance/hack/blob/2c1f665157e8645f79fe09812aca84448552e07a/packages/runtime-core/src/runtime_setup_cli.rs).
The source DNS reference now distinguishes definite misses from unknown
lookups accurately.

Validation at **`095b740bfd56405eed8699745d45373ab2a43328`**:
- Persistent reviewer clean at the exact merge head. All runtime and
test files match `next`; only docs/contributor guidance/docs tooling
differ.
- Bun 1.4.4, frozen dependencies: docs prepare/check/typecheck/build,
changed-script lint, site tests (2 tests/25 assertions), privacy and
diff checks pass. Normal merge hooks passed with seven existing
imported-code complexity warnings.
- Production-mode HTTP smoke: 97 docs, version isolation/refusals, 41
diagram blocks/82 SVGs and 214 local links/anchors pass. New first-run
and hygiene messages render on both updated pages.
- 16 command families and flags checked against the generated CLI
reference; native setup and manager commands checked against their
separate CLI contracts.
- Four Pele 1.9.0 house-theme diagrams inspected in both themes (366–563
px wide). Static image evidence only; the merge leaves them unchanged.
- Complete reachable-history Gitleaks: 1,300 commits, no findings.

No live install, DNS change, migration, key/store or native VM was
exercised. **Lead's Mac walkthrough of the first two pages remains the
user acceptance step.** Lead owns batch integration, merge and
deployment. HACK-2195 stays open for those notes and the pending
setup/upgrade commands.

---------

Co-authored-by: Kit <344842+roodboi@users.noreply.github.com>
roodboi added a commit that referenced this pull request Nov 13, 2026
…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.

![Update publication and
recovery](https://raw.githubusercontent.com/hack-dance/hack/test/v4-upgrade-regression/docs/reference/update-publication.svg)

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>
roodboi added a commit that referenced this pull request Nov 14, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant