Skip to content

feat: tt permissions suggest <workflow> for batch pre-approval - #53

Merged
nutt-adam merged 14 commits into
mainfrom
fix/issue-37-permissions-suggest
Mar 16, 2026
Merged

feat: tt permissions suggest <workflow> for batch pre-approval#53
nutt-adam merged 14 commits into
mainfrom
fix/issue-37-permissions-suggest

Conversation

@nutt-adam

@nutt-adam nutt-adam commented Mar 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds workflow-level permission suggestion so operators can pre-approve blocked commands before autonomous runs.

What changed

  • Added tt permissions suggest <workflow> subcommand.
  • Added --json output with blocked command details.
  • Added --apply to append suggested wildcard rules into ~/.config/tutti/config.toml.
  • Reused WorkflowResolver + evaluate_command_policy to inspect resolved command steps.

Validation

  • cargo test -q (all passing)

Fixes #37

Summary by CodeRabbit

  • New Features

    • Added a "suggest" subcommand that reports blocked permissions, can emit JSON reports, and can optionally apply suggested rules to the global policy; shows status when applying changes.
  • Tests

    • Added tests covering suggestion reports, nested workflows, deduplication, applying rules, and JSON shape stability.
  • Chores

    • Added a development-only test utility dependency.
    • Safer global config saves via a locking and atomic-write mechanism to prevent concurrent-write issues.

@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new CLI subcommand permissions suggest <workflow> to collect blocked commands (including nested workflows), deduplicate them, optionally append wildcard allow-rules to the global config with --apply, and emit a JSON report with --json. Also adds a global config write lock for safe atomic saves.

Changes

Cohort / File(s) Summary
CLI enum definition
src/cli/mod.rs
Added Suggest { workflow: String, apply: bool, json: bool } variant to PermissionsSubcommand to expose the new subcommand and flags.
Suggest implementation & tests
src/cli/permissions.rs
Added run_suggest() plus internal types (PermissionSuggestion, PermissionSuggestReport) and helpers to resolve workflows, collect blocked command steps (including nested workflows), deduplicate suggestions, evaluate via existing policy, optionally append wildcard allow-rules to global permissions and persist when --apply is used, and render JSON or human output. Added tests covering deduplication, nested resolution, apply behavior, and JSON shape. Attention: mutation/persistence of global config when --apply is used and JSON output shape stability for consumers.
Global config save locking
src/config/mod.rs
Introduced GlobalConfigLockGuard, acquire_global_config_lock(), stale-lock cleanup, and updated GlobalConfig::save to acquire the lock and perform atomic write to a temp file before renaming. Ensures single-writer semantics for config persistence.
Dev dependency
Cargo.toml
Added serial_test = "3" to [dev-dependencies] for tests requiring serial execution.

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI as CLI Handler
    participant Config as Config System
    participant Resolver as Workflow Resolver
    participant Policy as Permission Policy
    participant Output as Output Handler

    User->>CLI: permissions suggest <workflow> [--apply] [--json]
    CLI->>Config: Load global configuration
    Config-->>CLI: Config loaded
    CLI->>Resolver: Resolve workflow -> ResolvedSteps
    Resolver-->>CLI: ResolvedSteps
    loop each command step
        CLI->>Policy: evaluate_command_policy(command)
        Policy-->>CLI: allowed / blocked
    end
    CLI->>CLI: Collect blocked commands, deduplicate, build report
    alt --apply
        CLI->>Config: Acquire write lock, append allow-rules, persist
        Config-->>CLI: Persisted
    end
    alt --json
        CLI->>Output: Serialize JSON report
    else
        CLI->>Output: Format human-readable summary
    end
    Output-->>User: Display results
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Poem

🐰 I hopped through steps and sniffed each blocked command,
I stitched a little wildcard with a gentle, careful hand.
Apply the change or save JSON for later store,
A rabbit's small blessing — fewer permission chores. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete relative to the template. Critical versioning section items are unchecked: Cargo.toml version not updated, CHANGELOG.md not added, SemVer choice not specified, and validation checklist items not marked. Complete the Versioning section with version bump, CHANGELOG entry, SemVer selection, and mark validation items as complete; add explicit justification if no version bump is intended.
Out of Scope Changes check ⚠️ Warning Changes include a new global config write lock mechanism that prevents concurrent saves, which is beyond the scope of issue #37's permission suggestion feature requirements. Move the global config locking mechanism to a separate PR focused on concurrency safety, or document its necessity as a prerequisite fix for this feature in the PR description.
Docstring Coverage ⚠️ Warning Docstring coverage is 54.55% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main feature: adding a 'tt permissions suggest ' subcommand for batch pre-approval of blocked commands.
Linked Issues check ✅ Passed The implementation fully addresses issue #37: resolves workflows, extracts command steps, evaluates policies, outputs blocked commands, implements --apply to append rules, and provides --json output for machine consumption.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/issue-37-permissions-suggest
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

Synced with latest main (merge commit 33e288a) to clear the BEHIND status. Checks are green; waiting on required review approval.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

@coderabbitai review\n\nAll CI checks are green after syncing with main; requesting fresh pass for merge readiness.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

Synced this branch with latest \ again (commit 1688231) to clear the behind state and keep required checks current. CI re-run expected; remaining blocker is still required approving review.

coderabbitai[bot]
coderabbitai Bot previously requested changes Mar 16, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/cli/permissions.rs (1)

161-258: Consider adding unit tests for run_suggest.

The new run_suggest function implements substantial logic (workflow resolution, permission evaluation, deduplication, optional config mutation, and dual output modes) but lacks test coverage. The existing tests in this module cover other functionality but not the suggest feature.

Consider adding tests that verify:

  • Blocked commands are correctly identified and deduplicated
  • The --apply flag correctly modifies the config (using tempfile per guidelines)
  • JSON output structure matches PermissionSuggestReport
  • Edge cases: empty workflow, no blocked commands, all commands already allowed
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/permissions.rs` around lines 161 - 258, Add unit tests for
run_suggest that cover detection, deduplication, config mutation, JSON output,
and edge cases: write tests that set up a temporary workspace (use tempfile) and
create a TuttiConfig and GlobalConfig with a known permissions state, then call
run_suggest with varying workflows resolved via WorkflowResolver (or stub/mocked
resolution) and assert behavior — verify evaluate_command_policy is exercised by
asserting blocked commands appear once (deduplicated) in the returned
report/printed output, verify --apply updates GlobalConfig.permissions.allow
(and that global.save() persists by inspecting the temp file), verify JSON
output matches PermissionSuggestReport shape (workflow, total_commands, blocked,
applied_rules) using serde_json, and add edge-case tests for empty workflows, no
blocked commands, and when all commands are already allowed; reference
run_suggest, WorkflowResolver::resolve, evaluate_command_policy,
GlobalConfig::load/save, and PermissionSuggestReport to locate code to test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/cli/permissions.rs`:
- Around line 187-203: The loop in run_suggest only handles
ResolvedStep::Command and ignores ResolvedStep::Workflow, so commands inside
nested workflows are never analyzed; update the loop to recursively inspect
ResolvedStep::Workflow entries (or call a helper that walks a ResolvedStep tree)
and apply the same logic (normalize run, skip empty, evaluate_command_policy,
track seen, and push PermissionSuggestion) to commands found inside nested
workflows; reference ResolvedStep::Workflow and reuse the same
decision/evaluation flow used for ResolvedStep::Command so nested workflow
commands get permission suggestions just like top-level commands.

---

Nitpick comments:
In `@src/cli/permissions.rs`:
- Around line 161-258: Add unit tests for run_suggest that cover detection,
deduplication, config mutation, JSON output, and edge cases: write tests that
set up a temporary workspace (use tempfile) and create a TuttiConfig and
GlobalConfig with a known permissions state, then call run_suggest with varying
workflows resolved via WorkflowResolver (or stub/mocked resolution) and assert
behavior — verify evaluate_command_policy is exercised by asserting blocked
commands appear once (deduplicated) in the returned report/printed output,
verify --apply updates GlobalConfig.permissions.allow (and that global.save()
persists by inspecting the temp file), verify JSON output matches
PermissionSuggestReport shape (workflow, total_commands, blocked, applied_rules)
using serde_json, and add edge-case tests for empty workflows, no blocked
commands, and when all commands are already allowed; reference run_suggest,
WorkflowResolver::resolve, evaluate_command_policy, GlobalConfig::load/save, and
PermissionSuggestReport to locate code to test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 089ca710-c862-4f0d-b491-47cbbfa75dd2

📥 Commits

Reviewing files that changed from the base of the PR and between d14dfd2 and 1688231.

📒 Files selected for processing (2)
  • src/cli/mod.rs
  • src/cli/permissions.rs

Comment thread src/cli/permissions.rs Outdated
@nutt-adam

Copy link
Copy Markdown
Contributor Author

Addressed the actionable CodeRabbit blocker in commit 3a8f1dd.\n\n- now recursively inspects nested entries (not just top-level command steps).\n- Added focused tests for nested-workflow detection/dedup and /JSON report behavior.\n- Validation:
running 239 tests
....................................................................................... 87/239
....................................................................................... 174/239
.................................................................
test result: ok. 239 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.18s

running 1 test
.
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.25s passed (239 + 1).\n\n@coderabbitai review

@nutt-adam

Copy link
Copy Markdown
Contributor Author

Correcting prior comment (shell ate backticks):

Addressed the actionable CodeRabbit blocker in commit 3a8f1dd.

  • run_suggest now recursively inspects nested ResolvedStep::Workflow entries (not just top-level command steps).
  • Added focused tests for nested-workflow detection/dedup and --apply/JSON report behavior.
  • Validation: cargo test -q passed (239 + 1).

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown

@nutt-adam: Thanks for the detailed update! The recursive ResolvedStep::Workflow fix is exactly the right approach to catch nested permission requirements, and it's good to see dedicated tests covering nested-workflow detection, dedup, and the --apply/JSON report paths. Triggering a fresh review pass now.


🧠 Learnings used
Learnt from: CR
Repo: nutthouse/tutti PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T19:46:08.576Z
Learning: Applies to src/worktree/**/*.rs : Organize code in `src/worktree/` for Git worktree lifecycle
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

Follow-up: fixed CI format failure by running in commit 94a28ce.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

Addressed CI blocker: Clippy warning (denied as error) fixed in commit 83c4815.\n\nValidation rerun locally: and
running 239 tests
....................................................................................... 87/239
....................................................................................... 174/239
.................................................................
test result: ok. 239 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.18s

running 1 test
.
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.11s both pass.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

Correction: Clippy failure was due to the too_many_arguments lint being treated as error under -D warnings. Fixed in commit 83c4815.

Local validation passed:

  • cargo clippy -- -D warnings
  • cargo test -q

@nutt-adam
nutt-adam dismissed coderabbitai[bot]’s stale review March 16, 2026 14:39

Dismissing stale CodeRabbit change request: findings addressed in commits 3a8f1dd, 94a28ce, and 83c4815; current checks (including CodeRabbit status) are green.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

Readiness driver update: dismissed stale CodeRabbit CHANGES_REQUESTED review (3954193362) after follow-up fixes landed and checks are green. Remaining hard blocker is branch protection requiring an approving review from a writer other than the PR author.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

@coderabbitai please review now

@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown

@nutt-adam: Triggering a fresh full review pass now. The recursive ResolvedStep::Workflow fix, dedup/JSON tests, cargo fmt, and the Clippy too_many_arguments lint fix all look like solid resolutions to the previously flagged items.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai Bot previously requested changes Mar 16, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/cli/permissions.rs (1)

279-281: Make this CLI error actionable for operators.

The message is clear but not actionable. Add a concrete remediation hint (for example: run from a directory containing tutti.toml or pass the workspace root).

💡 Suggested wording tweak
-        TuttiError::ConfigValidation("could not determine workspace root".to_string())
+        TuttiError::ConfigValidation(
+            "could not determine workspace root; run `tt permissions suggest` from a workspace containing tutti.toml".to_string()
+        )

As per coding guidelines: "src/{cli,error}/**/*.rs: User-facing errors should include actionable guidance".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/permissions.rs` around lines 279 - 281, The error returned when
determining project_root via config_path.parent() uses
TuttiError::ConfigValidation with an unhelpful message; update that error to
provide actionable remediation guidance (e.g., tell the operator to run the
command from the directory containing tutti.toml or to pass the workspace root
via a flag/environment variable). Locate the project_root assignment and replace
the current error string ("could not determine workspace root") with a message
that includes concrete steps (for example: "could not determine workspace root:
run this command from the directory containing tutti.toml or pass the workspace
root via --workspace-root"). Ensure the change still constructs
TuttiError::ConfigValidation and preserves the ok_or_else usage so behavior and
error type remain the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/cli/permissions.rs`:
- Around line 166-174: The global seen_workflows check is incorrectly
short-circuiting valid repeated nested invocations; replace the global visited
guard with a recursion-stack (cycle detection) guard so only true cycles are
skipped. Add or rename the parameter (e.g., active_workflows: &mut
std::collections::BTreeSet<String> or Vec<String>) and change the logic in the
function that currently uses seen_workflows.insert(workflow.to_string()) ->
Ok(()) to: if active_workflows.contains(workflow) return Err/cycle-handled
Ok(()); else insert into active_workflows, process the workflow (updating
total_commands, seen_commands, blocked, etc.), then remove it from
active_workflows when done; keep or optionally use a separate seen_workflows
cache only after full processing to avoid re-processing identical workflow
definitions but do not use that cache to skip legitimate repeated nested
invocations without cycle detection; update callers to pass the new
active_workflows parameter.
- Around line 505-556: The test mutates HOME unsafely for parallel runs; mark
the test as serial by adding the serial_test attribute (add use
serial_test::serial; and prepend #[serial] to the test function) or move it into
a single-threaded integration test; ensure serial_test is added to Cargo.toml if
missing so the block that sets/ restores HOME around calls to TuttiConfig::load,
suggest_workflow_permissions, and global_config_path() runs sequentially to
avoid race conditions.

---

Nitpick comments:
In `@src/cli/permissions.rs`:
- Around line 279-281: The error returned when determining project_root via
config_path.parent() uses TuttiError::ConfigValidation with an unhelpful
message; update that error to provide actionable remediation guidance (e.g.,
tell the operator to run the command from the directory containing tutti.toml or
to pass the workspace root via a flag/environment variable). Locate the
project_root assignment and replace the current error string ("could not
determine workspace root") with a message that includes concrete steps (for
example: "could not determine workspace root: run this command from the
directory containing tutti.toml or pass the workspace root via
--workspace-root"). Ensure the change still constructs
TuttiError::ConfigValidation and preserves the ok_or_else usage so behavior and
error type remain the same.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f1798e69-6b8d-42f5-a26d-dbd1fea5d568

📥 Commits

Reviewing files that changed from the base of the PR and between 1688231 and 83c4815.

📒 Files selected for processing (1)
  • src/cli/permissions.rs

Comment thread src/cli/permissions.rs Outdated
@nutt-adam

Copy link
Copy Markdown
Contributor Author

Addressed the fresh CodeRabbit requested change in commit 286d493.\n\n- Replaced manual HOME cleanup in with an RAII that restores HOME in , making cleanup panic-safe.\n- Removed the old manual cleanup block to avoid duplicate/fragile restoration paths.\n\nValidation:\n-
running 1 test
.
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 238 filtered out; finished in 0.00s

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s\n-
running 17 tests
.................
test result: ok. 17 passed; 0 failed; 0 ignored; 0 measured; 222 filtered out; finished in 0.00s

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s\n\n@coderabbitai review

@nutt-adam

Copy link
Copy Markdown
Contributor Author

Correction (prior comment had shell formatting issues):

Addressed the fresh CodeRabbit requested change in commit 286d493.

  • Replaced manual HOME cleanup in suggest_apply_writes_global_permissions_and_json_shape_is_stable with an RAII HomeGuard that restores HOME in Drop, making cleanup panic-safe.
  • Removed the old manual cleanup block to avoid duplicate/fragile restoration paths.

Validation:

  • cargo test -q suggest_apply_writes_global_permissions_and_json_shape_is_stable
  • cargo test -q permissions

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown

@nutt-adam: Great fix — replacing the manual HOME teardown with an RAII guard (restoring in Drop) is the idiomatic Rust approach and correctly handles cleanup even when the test panics. Removing the old manual block eliminates the risk of double-restore or skipped cleanup on a panic path. The validation output looks solid — 1/1 and 17/17 passing. Triggering a fresh review pass now.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown

@nutt-adam: Thanks for the correction and the clear summary. Replacing the manual HOME cleanup with an RAII HomeGuard that restores the value in Drop is the idiomatic Rust approach — it guarantees cleanup even if the test panics mid-way. Removing the old manual block also eliminates the risk of double-restore or missed cleanup. Triggering a fresh review pass now.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai Bot previously requested changes Mar 16, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/cli/permissions.rs`:
- Around line 254-270: The read-modify-write in the apply path (when apply &&
!blocked.is_empty()) mutates global.permissions (PermissionsConfig.allow) and
then calls global.save(), which is vulnerable to lost updates under concurrent
runs; update GlobalConfig::save() to acquire an exclusive config-file lock
before writing and perform an atomic write (write to temp file then rename into
place) so all callers including the code that pushes suggested_rule into
policy.allow (variables: apply, blocked, policy, allow, applied_rules) are
protected from races and concurrent overwrites.
- Around line 172-175: The current cycle-check branch silently returns Ok(())
when active_workflows.contains(workflow) is true; change this to return a
user-facing error: construct and return TuttiError::ConfigValidation (or the
equivalent config validation variant) including the offending workflow name/path
(the workflow variable) and an actionable message telling the operator to remove
or fix the cyclic reference so suggestions can be generated; update the branch
where active_workflows.contains(workflow) is checked to return that error
instead of Ok(()), preserving the surrounding function's Result<T, TuttiError>
signature.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: be3a22ec-c4f0-4f56-9364-1501167f458c

📥 Commits

Reviewing files that changed from the base of the PR and between 2263a7a and 286d493.

📒 Files selected for processing (1)
  • src/cli/permissions.rs

Comment thread src/cli/permissions.rs
Comment thread src/cli/permissions.rs
@nutt-adam

Copy link
Copy Markdown
Contributor Author

Addressed the two current CodeRabbit blockers in commit f482629.

  • Cycle handling: collect_blocked_commands now returns a ConfigValidation error naming the workflow when a cyclic reference is detected (instead of silently no-oping), with actionable remediation text.
  • Concurrent apply safety: GlobalConfig::save() now acquires an exclusive lock file (config.toml.lock) and performs atomic write via temp-file + rename, preventing lost updates during concurrent --apply runs.

Validation:

  • cargo test -q suggest_apply_writes_global_permissions_and_json_shape_is_stable
  • cargo test -q permissions
  • cargo test -q config

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown

@nutt-adam: Both fixes look like exactly the right approach:

  • Cycle detection: Surfacing a ConfigValidation error with the offending workflow name (instead of silently no-oping) gives operators an actionable signal when a cyclic reference is present — silent failures here are especially hard to debug during autonomous runs.
  • Concurrent apply safety: The exclusive lock file + atomic temp-file rename is the standard safe-write pattern for concurrent file updates, preventing torn writes or lost updates when multiple --apply calls race.

The validation across suggest_apply, permissions, and config test suites all passing is a solid sign. Triggering a fresh review pass now.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai Bot previously requested changes Mar 16, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/config/mod.rs`:
- Around line 1113-1123: Collapse the nested `if let` checks by combining
metadata and modification-time retrieval into one `if let` using `and_then` to
satisfy Clippy: replace the two nested `if let Ok(meta) =
std::fs::metadata(&lock_path)` / `if let Ok(modified) = meta.modified()` with a
single `if let Ok(modified) = std::fs::metadata(&lock_path).and_then(|m|
m.modified())` and keep the existing `modified.elapsed().map(|age| age >
stale_after).unwrap_or(false)` check and the `std::fs::remove_file(&lock_path)`
call unchanged (use the same `lock_path` and `stale_after` symbols).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 67dd378f-9c5b-443a-a0f3-e39c0e21f5a6

📥 Commits

Reviewing files that changed from the base of the PR and between 286d493 and f482629.

📒 Files selected for processing (2)
  • src/cli/permissions.rs
  • src/config/mod.rs

Comment thread src/config/mod.rs Outdated
@nutt-adam

Copy link
Copy Markdown
Contributor Author

Pushed commit 2e44b2c to address current CI blockers: collapsed nested if-let lock checks in src/config/mod.rs (Clippy collapsible_if), then re-ran cargo fmt, cargo clippy -D warnings, and cargo test (all passing locally).

@nutt-adam
nutt-adam dismissed stale reviews from coderabbitai[bot], coderabbitai[bot], and coderabbitai[bot] March 16, 2026 18:29

Dismissing stale bot CHANGES_REQUESTED after follow-up fixes (f482629,2e44b2c) and green CI.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

Readiness driver: dismissed stale CodeRabbit CHANGES_REQUESTED reviews (3955594302, 3955708325, 3955762481) after follow-up fixes landed and CI stayed green. Current hard blocker is required approving review from a writer other than PR author.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

Readiness driver fix: merged latest \ into this branch (commit 7f00ac6) to resolve merge conflicts and clear the DIRTY/CONFLICTING gate. CI/CodeQL re-runs are now queued; remaining blocker after checks is required approving review from a writer other than the PR author.

@nutt-adam

Copy link
Copy Markdown
Contributor Author

Correction: merged latest main into this branch (commit 7f00ac6) to resolve merge conflicts and clear the DIRTY/CONFLICTING gate. CI/CodeQL re-runs are now queued; remaining blocker after checks is required approving review from a writer other than the PR author.

@nutt-adam
nutt-adam merged commit efdfaf6 into main Mar 16, 2026
10 checks passed
nutt-adam added a commit that referenced this pull request Mar 19, 2026
…anges

Cover startup grace window (#67), persistent memory (#62/#63), merge gate
enforcement (#59), permissions suggest (#53), orchestration state machine
(#54/#55), and all fixes shipped since 0.2.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
nutt-adam added a commit that referenced this pull request Mar 19, 2026
…choir runs (#71)

* feat(health): add startup grace window to wait_for_agent_idle (#67)

Prevent fresh prompt steps from falsely completing before the agent
has consumed the prompt. The startup grace period (default 30s) gates
completion detection until real working activity is observed.

Key changes:
- wait_for_agent_idle accepts a startup_grace Duration parameter
- AgentStatus::Working counts as activity even without pane hash change,
  requiring 2+ consecutive polls to avoid flicker false positives
- First pane capture no longer counts as a hash "change"
- Completion signals before any activity are held until grace expires
- "Unravelling" added to claude-code working patterns
- startup_grace_secs field threaded through config and automation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add 0.3.0 changelog entry for issue #67 and prior unreleased changes

Cover startup grace window (#67), persistent memory (#62/#63), merge gate
enforcement (#59), permissions suggest (#53), orchestration state machine
(#54/#55), and all fixes shipped since 0.2.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: reduce startup grace to 10s and validate wait settings

- Reduce DEFAULT_STARTUP_GRACE_SECS from 30 to 10 so the
  completion-before-activity path fires before typical wait timeouts
- Validate that wait_timeout_secs/startup_grace_secs are only set when
  wait_for_idle is true, failing fast with actionable guidance

Addresses CodeRabbit feedback on PR #71.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.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.

feat: tt permissions suggest <workflow> — batch pre-approve all workflow commands

2 participants