Skip to content

fix: address pre-launch env review findings#9

Merged
donbeave merged 3 commits into
feature/pre-launch-hooks-env-varsfrom
fix/pre-launch-hooks-review-findings
Apr 6, 2026
Merged

fix: address pre-launch env review findings#9
donbeave merged 3 commits into
feature/pre-launch-hooks-env-varsfrom
fix/pre-launch-hooks-review-findings

Conversation

@donbeave

@donbeave donbeave commented Apr 6, 2026

Copy link
Copy Markdown
Member

Summary

  • reject skipping required interactive env prompts
  • preserve caller-provided CLAUDE_ENV in the runtime entrypoint
  • reject symlinked pre_launch hook paths during agent repo validation

Verification

  • cargo clippy
  • cargo nextest run

@donbeave donbeave merged commit da5729a into feature/pre-launch-hooks-env-vars Apr 6, 2026
@donbeave donbeave deleted the fix/pre-launch-hooks-review-findings branch April 6, 2026 18:07
donbeave pushed a commit that referenced this pull request Apr 11, 2026
…lved

Rewrite the trust confirmation message to clearly explain what trusting
an agent means: Dockerfile execution, arbitrary commands on the host,
and workspace file access. The non-interactive error now tells the user
how to pre-trust via config.toml. The decline message explains how to
retry.

Also mark security finding #9 (mount policy guardrails) as resolved
since sensitive mount warnings were already implemented.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT
donbeave added a commit that referenced this pull request Apr 11, 2026
* feat: implement trust-on-first-use model for third-party agent sources

Add a trust gate that prompts operators before building untrusted
third-party agents. Built-in agents are always trusted. New namespaced
agents default to untrusted and require explicit confirmation on first
use. The trusted flag is persisted in config.toml so subsequent runs
proceed without prompts. Non-interactive sessions bail with a clear
error for untrusted sources.

Also syncs the roadmap with TODO items: adds missing completed item
(JACKIN_DIND_HOSTNAME), adds missing planned items (Bollard migration),
and marks the agent source trust security finding as resolved.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* improve trust prompt with clear risk details and mark finding #9 resolved

Rewrite the trust confirmation message to clearly explain what trusting
an agent means: Dockerfile execution, arbitrary commands on the host,
and workspace file access. The non-interactive error now tells the user
how to pre-trust via config.toml. The decline message explains how to
retry.

Also mark security finding #9 (mount policy guardrails) as resolved
since sensitive mount warnings were already implemented.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: address PR review — docs, stale comment, save clarity, test, serde

Review fixes for the agent source trust model:

- Fix duplicate doc comment on trust_agent() (copy-paste from
  sync_builtin_agents)
- Replace confusing `!source.trusted` save condition with explicit
  `newly_trusted` flag for readability
- Add unit test for non-interactive trust gate (verifies the error
  includes agent name and git URL)
- Skip serializing `trusted = false` to keep config.toml clean
  (only `trusted = true` appears)
- Document trust in load.mdx (step 3 in "What happens", warning
  callout for CI) and security-model.mdx (new section 4 with
  config.toml example, threat model row, best practices update)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: broken docs anchor link and misleading test name

- Fix cross-reference link in load.mdx: use #4-agent-source-trust
  (matching the numbered heading in security-model.mdx)
- Rename test to `load_trusted_namespaced_agent_builds_and_runs` since
  it no longer exercises auto-registration (that's covered by the
  config test `resolve_agent_source_adds_owner_repo_on_first_use`)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* feat: add jackin trust/untrust CLI, testable trust gate, revocation

Address all follow-up items from the maintainer review:

- Extract load_agent_with() with injected trust callback, following the
  resolve_agent_repo_with() pattern. Tests can now exercise accept and
  decline paths without mocking dialoguer.
- Restore auto-registration test coverage: the accept test uses
  load_agent_with(auto_trust) so resolve_agent_source's is_new path is
  exercised again. Add decline test verifying no config persistence and
  no Docker commands when trust is refused.
- Add `jackin trust <selector>` and `jackin untrust <selector>` CLI
  commands so operators can manage trust without editing config.toml.
- Add untrust_agent() to AppConfig with tests.
- Document trust/untrust CLI in security-model.mdx and load.mdx.
- Document that trust is keyed by selector (not URL) with a note about
  remote-mismatch protection.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: consolidate trust/untrust into single CLI command

Follow mise's pattern: `jackin trust` is one command with flags
instead of separate trust/untrust subcommands.

  jackin trust <selector>              # grant trust
  jackin trust <selector> --untrust    # revoke trust
  jackin trust <selector> --show       # check status

The --show and --untrust flags conflict with each other (enforced
by clap).

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: move trust CLI under config with grant/revoke/list subcommands

Follow the same pattern as `jackin config mount {add,remove,list}`:

  jackin config trust grant chainargos/the-architect
  jackin config trust revoke chainargos/the-architect
  jackin config trust list

This keeps all config mutations under `jackin config` and uses the
subcommand pattern consistently throughout the CLI. The `list`
subcommand shows all currently trusted agents.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: refuse to revoke trust on builtins, add CLI parsing tests

- is_builtin_agent() check prevents revoking trust on built-in agents
  (agent-smith, the-architect) which would be silently re-granted by
  sync_builtin_agents on next load
- Add 3 CLI parsing tests for config trust {grant, revoke, list},
  matching the existing coverage for config mount {add, remove, list}
- Tighten TrustCommand::List doc comment to "List all currently
  trusted agent sources"

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

---------

Co-authored-by: Claude <noreply@anthropic.com>
donbeave added a commit that referenced this pull request Apr 20, 2026
…-findings

fix: address pre-launch env review findings
donbeave added a commit that referenced this pull request Apr 20, 2026
* feat: implement trust-on-first-use model for third-party agent sources

Add a trust gate that prompts operators before building untrusted
third-party agents. Built-in agents are always trusted. New namespaced
agents default to untrusted and require explicit confirmation on first
use. The trusted flag is persisted in config.toml so subsequent runs
proceed without prompts. Non-interactive sessions bail with a clear
error for untrusted sources.

Also syncs the roadmap with TODO items: adds missing completed item
(JACKIN_DIND_HOSTNAME), adds missing planned items (Bollard migration),
and marks the agent source trust security finding as resolved.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* improve trust prompt with clear risk details and mark finding #9 resolved

Rewrite the trust confirmation message to clearly explain what trusting
an agent means: Dockerfile execution, arbitrary commands on the host,
and workspace file access. The non-interactive error now tells the user
how to pre-trust via config.toml. The decline message explains how to
retry.

Also mark security finding #9 (mount policy guardrails) as resolved
since sensitive mount warnings were already implemented.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: address PR review — docs, stale comment, save clarity, test, serde

Review fixes for the agent source trust model:

- Fix duplicate doc comment on trust_agent() (copy-paste from
  sync_builtin_agents)
- Replace confusing `!source.trusted` save condition with explicit
  `newly_trusted` flag for readability
- Add unit test for non-interactive trust gate (verifies the error
  includes agent name and git URL)
- Skip serializing `trusted = false` to keep config.toml clean
  (only `trusted = true` appears)
- Document trust in load.mdx (step 3 in "What happens", warning
  callout for CI) and security-model.mdx (new section 4 with
  config.toml example, threat model row, best practices update)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: broken docs anchor link and misleading test name

- Fix cross-reference link in load.mdx: use #4-agent-source-trust
  (matching the numbered heading in security-model.mdx)
- Rename test to `load_trusted_namespaced_agent_builds_and_runs` since
  it no longer exercises auto-registration (that's covered by the
  config test `resolve_agent_source_adds_owner_repo_on_first_use`)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* feat: add jackin trust/untrust CLI, testable trust gate, revocation

Address all follow-up items from the maintainer review:

- Extract load_agent_with() with injected trust callback, following the
  resolve_agent_repo_with() pattern. Tests can now exercise accept and
  decline paths without mocking dialoguer.
- Restore auto-registration test coverage: the accept test uses
  load_agent_with(auto_trust) so resolve_agent_source's is_new path is
  exercised again. Add decline test verifying no config persistence and
  no Docker commands when trust is refused.
- Add `jackin trust <selector>` and `jackin untrust <selector>` CLI
  commands so operators can manage trust without editing config.toml.
- Add untrust_agent() to AppConfig with tests.
- Document trust/untrust CLI in security-model.mdx and load.mdx.
- Document that trust is keyed by selector (not URL) with a note about
  remote-mismatch protection.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: consolidate trust/untrust into single CLI command

Follow mise's pattern: `jackin trust` is one command with flags
instead of separate trust/untrust subcommands.

  jackin trust <selector>              # grant trust
  jackin trust <selector> --untrust    # revoke trust
  jackin trust <selector> --show       # check status

The --show and --untrust flags conflict with each other (enforced
by clap).

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: move trust CLI under config with grant/revoke/list subcommands

Follow the same pattern as `jackin config mount {add,remove,list}`:

  jackin config trust grant chainargos/the-architect
  jackin config trust revoke chainargos/the-architect
  jackin config trust list

This keeps all config mutations under `jackin config` and uses the
subcommand pattern consistently throughout the CLI. The `list`
subcommand shows all currently trusted agents.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: refuse to revoke trust on builtins, add CLI parsing tests

- is_builtin_agent() check prevents revoking trust on built-in agents
  (agent-smith, the-architect) which would be silently re-granted by
  sync_builtin_agents on next load
- Add 3 CLI parsing tests for config trust {grant, revoke, list},
  matching the existing coverage for config mount {add, remove, list}
- Tighten TrustCommand::List doc comment to "List all currently
  trusted agent sources"

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

---------

Co-authored-by: Claude <noreply@anthropic.com>
donbeave added a commit that referenced this pull request Apr 21, 2026
…-findings

fix: address pre-launch env review findings
donbeave added a commit that referenced this pull request Apr 21, 2026
* feat: implement trust-on-first-use model for third-party agent sources

Add a trust gate that prompts operators before building untrusted
third-party agents. Built-in agents are always trusted. New namespaced
agents default to untrusted and require explicit confirmation on first
use. The trusted flag is persisted in config.toml so subsequent runs
proceed without prompts. Non-interactive sessions bail with a clear
error for untrusted sources.

Also syncs the roadmap with TODO items: adds missing completed item
(JACKIN_DIND_HOSTNAME), adds missing planned items (Bollard migration),
and marks the agent source trust security finding as resolved.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* improve trust prompt with clear risk details and mark finding #9 resolved

Rewrite the trust confirmation message to clearly explain what trusting
an agent means: Dockerfile execution, arbitrary commands on the host,
and workspace file access. The non-interactive error now tells the user
how to pre-trust via config.toml. The decline message explains how to
retry.

Also mark security finding #9 (mount policy guardrails) as resolved
since sensitive mount warnings were already implemented.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: address PR review — docs, stale comment, save clarity, test, serde

Review fixes for the agent source trust model:

- Fix duplicate doc comment on trust_agent() (copy-paste from
  sync_builtin_agents)
- Replace confusing `!source.trusted` save condition with explicit
  `newly_trusted` flag for readability
- Add unit test for non-interactive trust gate (verifies the error
  includes agent name and git URL)
- Skip serializing `trusted = false` to keep config.toml clean
  (only `trusted = true` appears)
- Document trust in load.mdx (step 3 in "What happens", warning
  callout for CI) and security-model.mdx (new section 4 with
  config.toml example, threat model row, best practices update)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: broken docs anchor link and misleading test name

- Fix cross-reference link in load.mdx: use #4-agent-source-trust
  (matching the numbered heading in security-model.mdx)
- Rename test to `load_trusted_namespaced_agent_builds_and_runs` since
  it no longer exercises auto-registration (that's covered by the
  config test `resolve_agent_source_adds_owner_repo_on_first_use`)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* feat: add jackin trust/untrust CLI, testable trust gate, revocation

Address all follow-up items from the maintainer review:

- Extract load_agent_with() with injected trust callback, following the
  resolve_agent_repo_with() pattern. Tests can now exercise accept and
  decline paths without mocking dialoguer.
- Restore auto-registration test coverage: the accept test uses
  load_agent_with(auto_trust) so resolve_agent_source's is_new path is
  exercised again. Add decline test verifying no config persistence and
  no Docker commands when trust is refused.
- Add `jackin trust <selector>` and `jackin untrust <selector>` CLI
  commands so operators can manage trust without editing config.toml.
- Add untrust_agent() to AppConfig with tests.
- Document trust/untrust CLI in security-model.mdx and load.mdx.
- Document that trust is keyed by selector (not URL) with a note about
  remote-mismatch protection.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: consolidate trust/untrust into single CLI command

Follow mise's pattern: `jackin trust` is one command with flags
instead of separate trust/untrust subcommands.

  jackin trust <selector>              # grant trust
  jackin trust <selector> --untrust    # revoke trust
  jackin trust <selector> --show       # check status

The --show and --untrust flags conflict with each other (enforced
by clap).

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: move trust CLI under config with grant/revoke/list subcommands

Follow the same pattern as `jackin config mount {add,remove,list}`:

  jackin config trust grant chainargos/the-architect
  jackin config trust revoke chainargos/the-architect
  jackin config trust list

This keeps all config mutations under `jackin config` and uses the
subcommand pattern consistently throughout the CLI. The `list`
subcommand shows all currently trusted agents.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: refuse to revoke trust on builtins, add CLI parsing tests

- is_builtin_agent() check prevents revoking trust on built-in agents
  (agent-smith, the-architect) which would be silently re-granted by
  sync_builtin_agents on next load
- Add 3 CLI parsing tests for config trust {grant, revoke, list},
  matching the existing coverage for config mount {add, remove, list}
- Tighten TrustCommand::List doc comment to "List all currently
  trusted agent sources"

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

---------

Co-authored-by: Claude <noreply@anthropic.com>
donbeave added a commit that referenced this pull request Apr 21, 2026
fix: address pre-launch env review findings
donbeave added a commit that referenced this pull request Apr 21, 2026
* feat: implement trust-on-first-use model for third-party agent sources

Add a trust gate that prompts operators before building untrusted
third-party agents. Built-in agents are always trusted. New namespaced
agents default to untrusted and require explicit confirmation on first
use. The trusted flag is persisted in config.toml so subsequent runs
proceed without prompts. Non-interactive sessions bail with a clear
error for untrusted sources.

Also syncs the roadmap with TODO items: adds missing completed item
(JACKIN_DIND_HOSTNAME), adds missing planned items (Bollard migration),
and marks the agent source trust security finding as resolved.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* improve trust prompt with clear risk details and mark finding #9 resolved

Rewrite the trust confirmation message to clearly explain what trusting
an agent means: Dockerfile execution, arbitrary commands on the host,
and workspace file access. The non-interactive error now tells the user
how to pre-trust via config.toml. The decline message explains how to
retry.

Also mark security finding #9 (mount policy guardrails) as resolved
since sensitive mount warnings were already implemented.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: address PR review — docs, stale comment, save clarity, test, serde

Review fixes for the agent source trust model:

- Fix duplicate doc comment on trust_agent() (copy-paste from
  sync_builtin_agents)
- Replace confusing `!source.trusted` save condition with explicit
  `newly_trusted` flag for readability
- Add unit test for non-interactive trust gate (verifies the error
  includes agent name and git URL)
- Skip serializing `trusted = false` to keep config.toml clean
  (only `trusted = true` appears)
- Document trust in load.mdx (step 3 in "What happens", warning
  callout for CI) and security-model.mdx (new section 4 with
  config.toml example, threat model row, best practices update)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: broken docs anchor link and misleading test name

- Fix cross-reference link in load.mdx: use #4-agent-source-trust
  (matching the numbered heading in security-model.mdx)
- Rename test to `load_trusted_namespaced_agent_builds_and_runs` since
  it no longer exercises auto-registration (that's covered by the
  config test `resolve_agent_source_adds_owner_repo_on_first_use`)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* feat: add jackin trust/untrust CLI, testable trust gate, revocation

Address all follow-up items from the maintainer review:

- Extract load_agent_with() with injected trust callback, following the
  resolve_agent_repo_with() pattern. Tests can now exercise accept and
  decline paths without mocking dialoguer.
- Restore auto-registration test coverage: the accept test uses
  load_agent_with(auto_trust) so resolve_agent_source's is_new path is
  exercised again. Add decline test verifying no config persistence and
  no Docker commands when trust is refused.
- Add `jackin trust <selector>` and `jackin untrust <selector>` CLI
  commands so operators can manage trust without editing config.toml.
- Add untrust_agent() to AppConfig with tests.
- Document trust/untrust CLI in security-model.mdx and load.mdx.
- Document that trust is keyed by selector (not URL) with a note about
  remote-mismatch protection.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: consolidate trust/untrust into single CLI command

Follow mise's pattern: `jackin trust` is one command with flags
instead of separate trust/untrust subcommands.

  jackin trust <selector>              # grant trust
  jackin trust <selector> --untrust    # revoke trust
  jackin trust <selector> --show       # check status

The --show and --untrust flags conflict with each other (enforced
by clap).

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: move trust CLI under config with grant/revoke/list subcommands

Follow the same pattern as `jackin config mount {add,remove,list}`:

  jackin config trust grant chainargos/the-architect
  jackin config trust revoke chainargos/the-architect
  jackin config trust list

This keeps all config mutations under `jackin config` and uses the
subcommand pattern consistently throughout the CLI. The `list`
subcommand shows all currently trusted agents.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: refuse to revoke trust on builtins, add CLI parsing tests

- is_builtin_agent() check prevents revoking trust on built-in agents
  (agent-smith, the-architect) which would be silently re-granted by
  sync_builtin_agents on next load
- Add 3 CLI parsing tests for config trust {grant, revoke, list},
  matching the existing coverage for config mount {add, remove, list}
- Tighten TrustCommand::List doc comment to "List all currently
  trusted agent sources"

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

---------

Co-authored-by: Claude <noreply@anthropic.com>
donbeave added a commit that referenced this pull request Apr 21, 2026
fix: address pre-launch env review findings
donbeave added a commit that referenced this pull request Apr 21, 2026
* feat: implement trust-on-first-use model for third-party agent sources

Add a trust gate that prompts operators before building untrusted
third-party agents. Built-in agents are always trusted. New namespaced
agents default to untrusted and require explicit confirmation on first
use. The trusted flag is persisted in config.toml so subsequent runs
proceed without prompts. Non-interactive sessions bail with a clear
error for untrusted sources.

Also syncs the roadmap with TODO items: adds missing completed item
(JACKIN_DIND_HOSTNAME), adds missing planned items (Bollard migration),
and marks the agent source trust security finding as resolved.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* improve trust prompt with clear risk details and mark finding #9 resolved

Rewrite the trust confirmation message to clearly explain what trusting
an agent means: Dockerfile execution, arbitrary commands on the host,
and workspace file access. The non-interactive error now tells the user
how to pre-trust via config.toml. The decline message explains how to
retry.

Also mark security finding #9 (mount policy guardrails) as resolved
since sensitive mount warnings were already implemented.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: address PR review — docs, stale comment, save clarity, test, serde

Review fixes for the agent source trust model:

- Fix duplicate doc comment on trust_agent() (copy-paste from
  sync_builtin_agents)
- Replace confusing `!source.trusted` save condition with explicit
  `newly_trusted` flag for readability
- Add unit test for non-interactive trust gate (verifies the error
  includes agent name and git URL)
- Skip serializing `trusted = false` to keep config.toml clean
  (only `trusted = true` appears)
- Document trust in load.mdx (step 3 in "What happens", warning
  callout for CI) and security-model.mdx (new section 4 with
  config.toml example, threat model row, best practices update)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: broken docs anchor link and misleading test name

- Fix cross-reference link in load.mdx: use #4-agent-source-trust
  (matching the numbered heading in security-model.mdx)
- Rename test to `load_trusted_namespaced_agent_builds_and_runs` since
  it no longer exercises auto-registration (that's covered by the
  config test `resolve_agent_source_adds_owner_repo_on_first_use`)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* feat: add jackin trust/untrust CLI, testable trust gate, revocation

Address all follow-up items from the maintainer review:

- Extract load_agent_with() with injected trust callback, following the
  resolve_agent_repo_with() pattern. Tests can now exercise accept and
  decline paths without mocking dialoguer.
- Restore auto-registration test coverage: the accept test uses
  load_agent_with(auto_trust) so resolve_agent_source's is_new path is
  exercised again. Add decline test verifying no config persistence and
  no Docker commands when trust is refused.
- Add `jackin trust <selector>` and `jackin untrust <selector>` CLI
  commands so operators can manage trust without editing config.toml.
- Add untrust_agent() to AppConfig with tests.
- Document trust/untrust CLI in security-model.mdx and load.mdx.
- Document that trust is keyed by selector (not URL) with a note about
  remote-mismatch protection.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: consolidate trust/untrust into single CLI command

Follow mise's pattern: `jackin trust` is one command with flags
instead of separate trust/untrust subcommands.

  jackin trust <selector>              # grant trust
  jackin trust <selector> --untrust    # revoke trust
  jackin trust <selector> --show       # check status

The --show and --untrust flags conflict with each other (enforced
by clap).

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: move trust CLI under config with grant/revoke/list subcommands

Follow the same pattern as `jackin config mount {add,remove,list}`:

  jackin config trust grant chainargos/the-architect
  jackin config trust revoke chainargos/the-architect
  jackin config trust list

This keeps all config mutations under `jackin config` and uses the
subcommand pattern consistently throughout the CLI. The `list`
subcommand shows all currently trusted agents.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: refuse to revoke trust on builtins, add CLI parsing tests

- is_builtin_agent() check prevents revoking trust on built-in agents
  (agent-smith, the-architect) which would be silently re-granted by
  sync_builtin_agents on next load
- Add 3 CLI parsing tests for config trust {grant, revoke, list},
  matching the existing coverage for config mount {add, remove, list}
- Tighten TrustCommand::List doc comment to "List all currently
  trusted agent sources"

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

---------

Co-authored-by: Claude <noreply@anthropic.com>
donbeave added a commit that referenced this pull request Apr 21, 2026
fix: address pre-launch env review findings
donbeave added a commit that referenced this pull request Apr 21, 2026
* feat: implement trust-on-first-use model for third-party agent sources

Add a trust gate that prompts operators before building untrusted
third-party agents. Built-in agents are always trusted. New namespaced
agents default to untrusted and require explicit confirmation on first
use. The trusted flag is persisted in config.toml so subsequent runs
proceed without prompts. Non-interactive sessions bail with a clear
error for untrusted sources.

Also syncs the roadmap with TODO items: adds missing completed item
(JACKIN_DIND_HOSTNAME), adds missing planned items (Bollard migration),
and marks the agent source trust security finding as resolved.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* improve trust prompt with clear risk details and mark finding #9 resolved

Rewrite the trust confirmation message to clearly explain what trusting
an agent means: Dockerfile execution, arbitrary commands on the host,
and workspace file access. The non-interactive error now tells the user
how to pre-trust via config.toml. The decline message explains how to
retry.

Also mark security finding #9 (mount policy guardrails) as resolved
since sensitive mount warnings were already implemented.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: address PR review — docs, stale comment, save clarity, test, serde

Review fixes for the agent source trust model:

- Fix duplicate doc comment on trust_agent() (copy-paste from
  sync_builtin_agents)
- Replace confusing `!source.trusted` save condition with explicit
  `newly_trusted` flag for readability
- Add unit test for non-interactive trust gate (verifies the error
  includes agent name and git URL)
- Skip serializing `trusted = false` to keep config.toml clean
  (only `trusted = true` appears)
- Document trust in load.mdx (step 3 in "What happens", warning
  callout for CI) and security-model.mdx (new section 4 with
  config.toml example, threat model row, best practices update)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: broken docs anchor link and misleading test name

- Fix cross-reference link in load.mdx: use #4-agent-source-trust
  (matching the numbered heading in security-model.mdx)
- Rename test to `load_trusted_namespaced_agent_builds_and_runs` since
  it no longer exercises auto-registration (that's covered by the
  config test `resolve_agent_source_adds_owner_repo_on_first_use`)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* feat: add jackin trust/untrust CLI, testable trust gate, revocation

Address all follow-up items from the maintainer review:

- Extract load_agent_with() with injected trust callback, following the
  resolve_agent_repo_with() pattern. Tests can now exercise accept and
  decline paths without mocking dialoguer.
- Restore auto-registration test coverage: the accept test uses
  load_agent_with(auto_trust) so resolve_agent_source's is_new path is
  exercised again. Add decline test verifying no config persistence and
  no Docker commands when trust is refused.
- Add `jackin trust <selector>` and `jackin untrust <selector>` CLI
  commands so operators can manage trust without editing config.toml.
- Add untrust_agent() to AppConfig with tests.
- Document trust/untrust CLI in security-model.mdx and load.mdx.
- Document that trust is keyed by selector (not URL) with a note about
  remote-mismatch protection.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: consolidate trust/untrust into single CLI command

Follow mise's pattern: `jackin trust` is one command with flags
instead of separate trust/untrust subcommands.

  jackin trust <selector>              # grant trust
  jackin trust <selector> --untrust    # revoke trust
  jackin trust <selector> --show       # check status

The --show and --untrust flags conflict with each other (enforced
by clap).

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: move trust CLI under config with grant/revoke/list subcommands

Follow the same pattern as `jackin config mount {add,remove,list}`:

  jackin config trust grant chainargos/the-architect
  jackin config trust revoke chainargos/the-architect
  jackin config trust list

This keeps all config mutations under `jackin config` and uses the
subcommand pattern consistently throughout the CLI. The `list`
subcommand shows all currently trusted agents.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: refuse to revoke trust on builtins, add CLI parsing tests

- is_builtin_agent() check prevents revoking trust on built-in agents
  (agent-smith, the-architect) which would be silently re-granted by
  sync_builtin_agents on next load
- Add 3 CLI parsing tests for config trust {grant, revoke, list},
  matching the existing coverage for config mount {add, remove, list}
- Tighten TrustCommand::List doc comment to "List all currently
  trusted agent sources"

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

---------

Co-authored-by: Claude <noreply@anthropic.com>
donbeave added a commit that referenced this pull request Apr 24, 2026
Mechanical cleanup of clippy warnings in files added or modified by
PR #166. Addresses finding #4 of the second-pass review:

tests/manager_flow.rs:
- missing_const_for_fn on the `key` helper -> mark `const fn`.
- redundant_clone on the third use of `host_path` -> drop the
  trailing `.clone()` so the value moves on its last use.
- default_trait_access on `Default::default()` for env/agents
  fields -> use the explicit `BTreeMap::new()` constructor.

src/launch/manager/input/save.rs (test module):
- used_underscore_binding on `_tmp` -> rename to `tmp`. The binding
  has to be held to keep the TempDir alive for the test, but it is
  also read via `.path()`, so the underscore was misleading; the
  rename makes the read explicit.
- used_underscore_binding on `_config0` -> swap for the `_`
  bit-bucket pattern; the loaded config is genuinely unused in
  those tests (they re-open the config via ConfigEditor).
- redundant_clone on `ws_b.clone()` at the last use site -> drop
  the clone and let the value move.

No #[allow(...)] suppressions -- every warning is addressed by code
change.

Warnings in files outside this PR remain as documented pre-existing
drift (finding #9 of the first-pass review).

Addresses finding #4 of the second-pass PR #166 review.

Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
donbeave added a commit that referenced this pull request May 7, 2026
fix: address pre-launch env review findings
Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
Co-authored-by: Codex <codex@openai.com>
donbeave added a commit that referenced this pull request May 7, 2026
* feat: implement trust-on-first-use model for third-party agent sources

Add a trust gate that prompts operators before building untrusted
third-party agents. Built-in agents are always trusted. New namespaced
agents default to untrusted and require explicit confirmation on first
use. The trusted flag is persisted in config.toml so subsequent runs
proceed without prompts. Non-interactive sessions bail with a clear
error for untrusted sources.

Also syncs the roadmap with TODO items: adds missing completed item
(JACKIN_DIND_HOSTNAME), adds missing planned items (Bollard migration),
and marks the agent source trust security finding as resolved.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* improve trust prompt with clear risk details and mark finding #9 resolved

Rewrite the trust confirmation message to clearly explain what trusting
an agent means: Dockerfile execution, arbitrary commands on the host,
and workspace file access. The non-interactive error now tells the user
how to pre-trust via config.toml. The decline message explains how to
retry.

Also mark security finding #9 (mount policy guardrails) as resolved
since sensitive mount warnings were already implemented.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: address PR review — docs, stale comment, save clarity, test, serde

Review fixes for the agent source trust model:

- Fix duplicate doc comment on trust_agent() (copy-paste from
  sync_builtin_agents)
- Replace confusing `!source.trusted` save condition with explicit
  `newly_trusted` flag for readability
- Add unit test for non-interactive trust gate (verifies the error
  includes agent name and git URL)
- Skip serializing `trusted = false` to keep config.toml clean
  (only `trusted = true` appears)
- Document trust in load.mdx (step 3 in "What happens", warning
  callout for CI) and security-model.mdx (new section 4 with
  config.toml example, threat model row, best practices update)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: broken docs anchor link and misleading test name

- Fix cross-reference link in load.mdx: use #4-agent-source-trust
  (matching the numbered heading in security-model.mdx)
- Rename test to `load_trusted_namespaced_agent_builds_and_runs` since
  it no longer exercises auto-registration (that's covered by the
  config test `resolve_agent_source_adds_owner_repo_on_first_use`)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* feat: add jackin trust/untrust CLI, testable trust gate, revocation

Address all follow-up items from the maintainer review:

- Extract load_agent_with() with injected trust callback, following the
  resolve_agent_repo_with() pattern. Tests can now exercise accept and
  decline paths without mocking dialoguer.
- Restore auto-registration test coverage: the accept test uses
  load_agent_with(auto_trust) so resolve_agent_source's is_new path is
  exercised again. Add decline test verifying no config persistence and
  no Docker commands when trust is refused.
- Add `jackin trust <selector>` and `jackin untrust <selector>` CLI
  commands so operators can manage trust without editing config.toml.
- Add untrust_agent() to AppConfig with tests.
- Document trust/untrust CLI in security-model.mdx and load.mdx.
- Document that trust is keyed by selector (not URL) with a note about
  remote-mismatch protection.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: consolidate trust/untrust into single CLI command

Follow mise's pattern: `jackin trust` is one command with flags
instead of separate trust/untrust subcommands.

  jackin trust <selector>              # grant trust
  jackin trust <selector> --untrust    # revoke trust
  jackin trust <selector> --show       # check status

The --show and --untrust flags conflict with each other (enforced
by clap).

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: move trust CLI under config with grant/revoke/list subcommands

Follow the same pattern as `jackin config mount {add,remove,list}`:

  jackin config trust grant chainargos/the-architect
  jackin config trust revoke chainargos/the-architect
  jackin config trust list

This keeps all config mutations under `jackin config` and uses the
subcommand pattern consistently throughout the CLI. The `list`
subcommand shows all currently trusted agents.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: refuse to revoke trust on builtins, add CLI parsing tests

- is_builtin_agent() check prevents revoking trust on built-in agents
  (agent-smith, the-architect) which would be silently re-granted by
  sync_builtin_agents on next load
- Add 3 CLI parsing tests for config trust {grant, revoke, list},
  matching the existing coverage for config mount {add, remove, list}
- Tighten TrustCommand::List doc comment to "List all currently
  trusted agent sources"

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

---------

Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
Co-authored-by: Codex <codex@openai.com>
donbeave added a commit that referenced this pull request May 7, 2026
fix: address pre-launch env review findings

Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
Co-authored-by: Codex <codex@openai.com>
donbeave added a commit that referenced this pull request May 7, 2026
* feat: implement trust-on-first-use model for third-party agent sources

Add a trust gate that prompts operators before building untrusted
third-party agents. Built-in agents are always trusted. New namespaced
agents default to untrusted and require explicit confirmation on first
use. The trusted flag is persisted in config.toml so subsequent runs
proceed without prompts. Non-interactive sessions bail with a clear
error for untrusted sources.

Also syncs the roadmap with TODO items: adds missing completed item
(JACKIN_DIND_HOSTNAME), adds missing planned items (Bollard migration),
and marks the agent source trust security finding as resolved.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* improve trust prompt with clear risk details and mark finding #9 resolved

Rewrite the trust confirmation message to clearly explain what trusting
an agent means: Dockerfile execution, arbitrary commands on the host,
and workspace file access. The non-interactive error now tells the user
how to pre-trust via config.toml. The decline message explains how to
retry.

Also mark security finding #9 (mount policy guardrails) as resolved
since sensitive mount warnings were already implemented.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: address PR review — docs, stale comment, save clarity, test, serde

Review fixes for the agent source trust model:

- Fix duplicate doc comment on trust_agent() (copy-paste from
  sync_builtin_agents)
- Replace confusing `!source.trusted` save condition with explicit
  `newly_trusted` flag for readability
- Add unit test for non-interactive trust gate (verifies the error
  includes agent name and git URL)
- Skip serializing `trusted = false` to keep config.toml clean
  (only `trusted = true` appears)
- Document trust in load.mdx (step 3 in "What happens", warning
  callout for CI) and security-model.mdx (new section 4 with
  config.toml example, threat model row, best practices update)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: broken docs anchor link and misleading test name

- Fix cross-reference link in load.mdx: use #4-agent-source-trust
  (matching the numbered heading in security-model.mdx)
- Rename test to `load_trusted_namespaced_agent_builds_and_runs` since
  it no longer exercises auto-registration (that's covered by the
  config test `resolve_agent_source_adds_owner_repo_on_first_use`)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* feat: add jackin trust/untrust CLI, testable trust gate, revocation

Address all follow-up items from the maintainer review:

- Extract load_agent_with() with injected trust callback, following the
  resolve_agent_repo_with() pattern. Tests can now exercise accept and
  decline paths without mocking dialoguer.
- Restore auto-registration test coverage: the accept test uses
  load_agent_with(auto_trust) so resolve_agent_source's is_new path is
  exercised again. Add decline test verifying no config persistence and
  no Docker commands when trust is refused.
- Add `jackin trust <selector>` and `jackin untrust <selector>` CLI
  commands so operators can manage trust without editing config.toml.
- Add untrust_agent() to AppConfig with tests.
- Document trust/untrust CLI in security-model.mdx and load.mdx.
- Document that trust is keyed by selector (not URL) with a note about
  remote-mismatch protection.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: consolidate trust/untrust into single CLI command

Follow mise's pattern: `jackin trust` is one command with flags
instead of separate trust/untrust subcommands.

  jackin trust <selector>              # grant trust
  jackin trust <selector> --untrust    # revoke trust
  jackin trust <selector> --show       # check status

The --show and --untrust flags conflict with each other (enforced
by clap).

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: move trust CLI under config with grant/revoke/list subcommands

Follow the same pattern as `jackin config mount {add,remove,list}`:

  jackin config trust grant chainargos/the-architect
  jackin config trust revoke chainargos/the-architect
  jackin config trust list

This keeps all config mutations under `jackin config` and uses the
subcommand pattern consistently throughout the CLI. The `list`
subcommand shows all currently trusted agents.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: refuse to revoke trust on builtins, add CLI parsing tests

- is_builtin_agent() check prevents revoking trust on built-in agents
  (agent-smith, the-architect) which would be silently re-granted by
  sync_builtin_agents on next load
- Add 3 CLI parsing tests for config trust {grant, revoke, list},
  matching the existing coverage for config mount {add, remove, list}
- Tighten TrustCommand::List doc comment to "List all currently
  trusted agent sources"

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

---------

Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
Co-authored-by: Codex <codex@openai.com>
donbeave added a commit that referenced this pull request May 7, 2026
fix: address pre-launch env review findings

Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
Co-authored-by: Codex <codex@openai.com>
donbeave added a commit that referenced this pull request May 7, 2026
* feat: implement trust-on-first-use model for third-party agent sources

Add a trust gate that prompts operators before building untrusted
third-party agents. Built-in agents are always trusted. New namespaced
agents default to untrusted and require explicit confirmation on first
use. The trusted flag is persisted in config.toml so subsequent runs
proceed without prompts. Non-interactive sessions bail with a clear
error for untrusted sources.

Also syncs the roadmap with TODO items: adds missing completed item
(JACKIN_DIND_HOSTNAME), adds missing planned items (Bollard migration),
and marks the agent source trust security finding as resolved.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* improve trust prompt with clear risk details and mark finding #9 resolved

Rewrite the trust confirmation message to clearly explain what trusting
an agent means: Dockerfile execution, arbitrary commands on the host,
and workspace file access. The non-interactive error now tells the user
how to pre-trust via config.toml. The decline message explains how to
retry.

Also mark security finding #9 (mount policy guardrails) as resolved
since sensitive mount warnings were already implemented.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: address PR review — docs, stale comment, save clarity, test, serde

Review fixes for the agent source trust model:

- Fix duplicate doc comment on trust_agent() (copy-paste from
  sync_builtin_agents)
- Replace confusing `!source.trusted` save condition with explicit
  `newly_trusted` flag for readability
- Add unit test for non-interactive trust gate (verifies the error
  includes agent name and git URL)
- Skip serializing `trusted = false` to keep config.toml clean
  (only `trusted = true` appears)
- Document trust in load.mdx (step 3 in "What happens", warning
  callout for CI) and security-model.mdx (new section 4 with
  config.toml example, threat model row, best practices update)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: broken docs anchor link and misleading test name

- Fix cross-reference link in load.mdx: use #4-agent-source-trust
  (matching the numbered heading in security-model.mdx)
- Rename test to `load_trusted_namespaced_agent_builds_and_runs` since
  it no longer exercises auto-registration (that's covered by the
  config test `resolve_agent_source_adds_owner_repo_on_first_use`)

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* feat: add jackin trust/untrust CLI, testable trust gate, revocation

Address all follow-up items from the maintainer review:

- Extract load_agent_with() with injected trust callback, following the
  resolve_agent_repo_with() pattern. Tests can now exercise accept and
  decline paths without mocking dialoguer.
- Restore auto-registration test coverage: the accept test uses
  load_agent_with(auto_trust) so resolve_agent_source's is_new path is
  exercised again. Add decline test verifying no config persistence and
  no Docker commands when trust is refused.
- Add `jackin trust <selector>` and `jackin untrust <selector>` CLI
  commands so operators can manage trust without editing config.toml.
- Add untrust_agent() to AppConfig with tests.
- Document trust/untrust CLI in security-model.mdx and load.mdx.
- Document that trust is keyed by selector (not URL) with a note about
  remote-mismatch protection.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: consolidate trust/untrust into single CLI command

Follow mise's pattern: `jackin trust` is one command with flags
instead of separate trust/untrust subcommands.

  jackin trust <selector>              # grant trust
  jackin trust <selector> --untrust    # revoke trust
  jackin trust <selector> --show       # check status

The --show and --untrust flags conflict with each other (enforced
by clap).

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* refactor: move trust CLI under config with grant/revoke/list subcommands

Follow the same pattern as `jackin config mount {add,remove,list}`:

  jackin config trust grant chainargos/the-architect
  jackin config trust revoke chainargos/the-architect
  jackin config trust list

This keeps all config mutations under `jackin config` and uses the
subcommand pattern consistently throughout the CLI. The `list`
subcommand shows all currently trusted agents.

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

* fix: refuse to revoke trust on builtins, add CLI parsing tests

- is_builtin_agent() check prevents revoking trust on built-in agents
  (agent-smith, the-architect) which would be silently re-granted by
  sync_builtin_agents on next load
- Add 3 CLI parsing tests for config trust {grant, revoke, list},
  matching the existing coverage for config mount {add, remove, list}
- Tighten TrustCommand::List doc comment to "List all currently
  trusted agent sources"

https://claude.ai/code/session_01SkHoAne5Q5EpUybYk6ghUT

---------

Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
Co-authored-by: Codex <codex@openai.com>
donbeave added a commit that referenced this pull request May 22, 2026
…escing

Four small daemon/dialog correctness fixes.

`dialog::box_rect` (#9)
- Clamp dialog height to the area below the status bar so a very
  small terminal does not paint past the bottom edge (which would
  scroll the host terminal and destroy the operator's pane content)
  and does not overlap row 0 (the brand pill / tab strip). Trade-off
  is that the dialog renders unusable when the terminal is
  pathologically small, but the host terminal stays in a recoverable
  state regardless.
- `render_bottom_hint`: tighten the bail to `total > term_cols` so
  an exact-fit hint renders instead of being dropped at `==`. Use
  saturating subtraction for the start_col centring math.

`Multiplexer::spawn_session` (#34, cap side)
- Cap tabs at `MAX_TABS=32` and sessions at `MAX_SESSIONS=64`. A
  runaway client (or an operator mis-click loop) cannot allocate
  unbounded PTYs — each session retains scrollback, a master+slave
  PTY pair, and a child process, so unbounded growth is a real OOM
  risk. The CLI surface returns an `anyhow::bail!` which
  `dispatch_spawn_intent` already clog's.

`SessionEvent::Output` (#36)
- Move `drain_mode_transitions` inside the `is_focused` gate. The
  previous code drained and discarded the bytes on every backgrounded
  pane — wasted work, plus a future change that reads
  `bracketed_paste_active` after drain on an unfocused pane would
  silently see the wrong state. Also restructured to collect the
  to-emit bytes into a local Vec so the `&mut Session` borrow ends
  before `mux.send_output` (which needs `&self`).

Render ticker (#37)
- Drop the `mux.dialog.is_none()` gate from the render ticker
  condition. `compose_frame` already includes the dialog overlay
  when one is open, so the open-dialog path now composes at the
  normal ~30 fps instead of accumulating `dirty` until dismiss —
  without this the dismiss frame was a sudden jump of N frames'
  worth of accumulated PTY output that the operator had no way to
  see coming.

Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
donbeave added a commit that referenced this pull request May 23, 2026
…escing

Four small daemon/dialog correctness fixes.

`dialog::box_rect` (#9)
- Clamp dialog height to the area below the status bar so a very
  small terminal does not paint past the bottom edge (which would
  scroll the host terminal and destroy the operator's pane content)
  and does not overlap row 0 (the brand pill / tab strip). Trade-off
  is that the dialog renders unusable when the terminal is
  pathologically small, but the host terminal stays in a recoverable
  state regardless.
- `render_bottom_hint`: tighten the bail to `total > term_cols` so
  an exact-fit hint renders instead of being dropped at `==`. Use
  saturating subtraction for the start_col centring math.

`Multiplexer::spawn_session` (#34, cap side)
- Cap tabs at `MAX_TABS=32` and sessions at `MAX_SESSIONS=64`. A
  runaway client (or an operator mis-click loop) cannot allocate
  unbounded PTYs — each session retains scrollback, a master+slave
  PTY pair, and a child process, so unbounded growth is a real OOM
  risk. The CLI surface returns an `anyhow::bail!` which
  `dispatch_spawn_intent` already clog's.

`SessionEvent::Output` (#36)
- Move `drain_mode_transitions` inside the `is_focused` gate. The
  previous code drained and discarded the bytes on every backgrounded
  pane — wasted work, plus a future change that reads
  `bracketed_paste_active` after drain on an unfocused pane would
  silently see the wrong state. Also restructured to collect the
  to-emit bytes into a local Vec so the `&mut Session` borrow ends
  before `mux.send_output` (which needs `&self`).

Render ticker (#37)
- Drop the `mux.dialog.is_none()` gate from the render ticker
  condition. `compose_frame` already includes the dialog overlay
  when one is open, so the open-dialog path now composes at the
  normal ~30 fps instead of accumulating `dirty` until dismiss —
  without this the dismiss frame was a sudden jump of N frames'
  worth of accumulated PTY output that the operator had no way to
  see coming.

Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
donbeave added a commit that referenced this pull request May 23, 2026
…escing

Four small daemon/dialog correctness fixes.

`dialog::box_rect` (#9)
- Clamp dialog height to the area below the status bar so a very
  small terminal does not paint past the bottom edge (which would
  scroll the host terminal and destroy the operator's pane content)
  and does not overlap row 0 (the brand pill / tab strip). Trade-off
  is that the dialog renders unusable when the terminal is
  pathologically small, but the host terminal stays in a recoverable
  state regardless.
- `render_bottom_hint`: tighten the bail to `total > term_cols` so
  an exact-fit hint renders instead of being dropped at `==`. Use
  saturating subtraction for the start_col centring math.

`Multiplexer::spawn_session` (#34, cap side)
- Cap tabs at `MAX_TABS=32` and sessions at `MAX_SESSIONS=64`. A
  runaway client (or an operator mis-click loop) cannot allocate
  unbounded PTYs — each session retains scrollback, a master+slave
  PTY pair, and a child process, so unbounded growth is a real OOM
  risk. The CLI surface returns an `anyhow::bail!` which
  `dispatch_spawn_intent` already clog's.

`SessionEvent::Output` (#36)
- Move `drain_mode_transitions` inside the `is_focused` gate. The
  previous code drained and discarded the bytes on every backgrounded
  pane — wasted work, plus a future change that reads
  `bracketed_paste_active` after drain on an unfocused pane would
  silently see the wrong state. Also restructured to collect the
  to-emit bytes into a local Vec so the `&mut Session` borrow ends
  before `mux.send_output` (which needs `&self`).

Render ticker (#37)
- Drop the `mux.dialog.is_none()` gate from the render ticker
  condition. `compose_frame` already includes the dialog overlay
  when one is open, so the open-dialog path now composes at the
  normal ~30 fps instead of accumulating `dirty` until dismiss —
  without this the dismiss frame was a sudden jump of N frames'
  worth of accumulated PTY output that the operator had no way to
  see coming.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
donbeave added a commit that referenced this pull request May 23, 2026
…escing

Four small daemon/dialog correctness fixes.

`dialog::box_rect` (#9)
- Clamp dialog height to the area below the status bar so a very
  small terminal does not paint past the bottom edge (which would
  scroll the host terminal and destroy the operator's pane content)
  and does not overlap row 0 (the brand pill / tab strip). Trade-off
  is that the dialog renders unusable when the terminal is
  pathologically small, but the host terminal stays in a recoverable
  state regardless.
- `render_bottom_hint`: tighten the bail to `total > term_cols` so
  an exact-fit hint renders instead of being dropped at `==`. Use
  saturating subtraction for the start_col centring math.

`Multiplexer::spawn_session` (#34, cap side)
- Cap tabs at `MAX_TABS=32` and sessions at `MAX_SESSIONS=64`. A
  runaway client (or an operator mis-click loop) cannot allocate
  unbounded PTYs — each session retains scrollback, a master+slave
  PTY pair, and a child process, so unbounded growth is a real OOM
  risk. The CLI surface returns an `anyhow::bail!` which
  `dispatch_spawn_intent` already clog's.

`SessionEvent::Output` (#36)
- Move `drain_mode_transitions` inside the `is_focused` gate. The
  previous code drained and discarded the bytes on every backgrounded
  pane — wasted work, plus a future change that reads
  `bracketed_paste_active` after drain on an unfocused pane would
  silently see the wrong state. Also restructured to collect the
  to-emit bytes into a local Vec so the `&mut Session` borrow ends
  before `mux.send_output` (which needs `&self`).

Render ticker (#37)
- Drop the `mux.dialog.is_none()` gate from the render ticker
  condition. `compose_frame` already includes the dialog overlay
  when one is open, so the open-dialog path now composes at the
  normal ~30 fps instead of accumulating `dirty` until dismiss —
  without this the dismiss frame was a sudden jump of N frames'
  worth of accumulated PTY output that the operator had no way to
  see coming.

Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
Co-authored-by: Codex <codex@openai.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