Skip to content

feat: v0.9.0 — First 5 Minutes Magic - #116

Merged
nutt-adam merged 8 commits into
mainfrom
feat/first-5-minutes
Mar 23, 2026
Merged

feat: v0.9.0 — First 5 Minutes Magic#116
nutt-adam merged 8 commits into
mainfrom
feat/first-5-minutes

Conversation

@nutt-adam

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

Copy link
Copy Markdown
Contributor

Summary

  • Interactive tt init: Progressive disclosure bootstrap — auto-detects repo type, shows team preview table, offers Launch/Customize/Quit
  • Customize mode: Swap runtimes, remove agents, change project name with live preview
  • Auto-launch: Press L to write config + tt up in one step
  • 5 built-in templates: gstack-startup, rust-cli, node-fullstack, python-api, minimal
  • tt template list: Shows all available templates with detection rules
  • Custom template discovery: ~/.config/tutti/templates/*.toml auto-discovered
  • Run telemetry: Step-level timing to .tutti/state/run-telemetry.jsonl
  • Re-init with backup: Offers backup instead of refusing when tutti.toml exists

Pre-Landing Review

4 auto-fixed from adversarial review (EOF stdin loop, scoring inconsistency, negative duration, swallowed read errors). 0 critical remaining. 10 informational noted (acceptable).

Test plan

  • 371 tests pass (single-threaded; 2 flaky in parallel due to pre-existing global config race)
  • cargo clippy clean (1 pre-existing dead code warning)
  • tt template list renders correctly with 5 templates
  • Adversarial review: Claude 14 findings, 4 fixed, 10 informational

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Interactive init: repo auto-detection, team preview, Customize mode with live previews, optional auto-launch, and a new "tt template list" command
    • New Node.js (node-fullstack) and Python (python-api) templates; discover custom templates from user config
    • Run telemetry now persisted to state file after runs
  • Bug Fixes

    • Safer re-init with backup option and improved prompt EOF/error handling
    • Telemetry durations clamped to non-negative values
  • Documentation

    • Changelog updated for 0.9.0

nutt-adam and others added 4 commits March 23, 2026 15:44
…scovery

Two new built-in templates: node-fullstack (4-agent frontend/backend split,
detects package.json) and python-api (3-agent, detects pyproject.toml/requirements.txt).

Custom template discovery from ~/.config/tutti/templates/ with validation
and warning on malformed files. Unified scoring via score_template_detection().

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

Progressive disclosure bootstrap: auto-detect repo → show team preview table →
[L]aunch / [C]ustomize / [Q]uit. Customize mode lets users swap runtimes,
remove agents, and change project name with live preview re-rendering.

tt template list shows all built-in and custom templates with detection rules.
InputSource trait enables full test coverage of interactive flows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Emits step-level timing and pass/fail data to .tutti/state/run-telemetry.jsonl
after each tt run completes. Includes template_id/version attribution.
Duration clamped to max(0.0) to handle clock skew.

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

coderabbitai Bot commented Mar 23, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds v0.9.0: an interactive tt init with repo/template auto-detection, preview/customize/launch flow, built-in Node/Python templates plus custom-template discovery/listing, and appends run telemetry to .tutti/state/run-telemetry.jsonl.

Changes

Cohort / File(s) Summary
Version & Changelog
CHANGELOG.md, Cargo.toml
Bumped package to 0.9.0 and documented new init interactivity, templates, discovery, and telemetry.
Interactive Init CLI
src/cli/init.rs
Introduced InputSource abstraction & StdinInput; added run_with_input variants; reworked init flow to allow re-init backup, template resolution (explicit/detection/custom/interactive), preview + customize loop (L/S/C/Q), config write/register, tt up launch integration, template_list() command, and expanded tests using MockInput.
CLI Command Wiring
src/cli/mod.rs, src/main.rs
Added Commands::Template and TemplateSubcommand::List, wired dispatch to cli::init::template_list().
Template system & discovery
src/template/mod.rs
Added two built-ins; replaced detection logic with score_template_detection (score>0 filter, sort by score then name); added discover_custom_templates() scanning ~/.config/tutti/templates/; updated load_template lookup to try built-ins then custom and return hint on not found.
New built-in templates
templates/node-fullstack.toml, templates/python-api.toml
Added node-fullstack and python-api templates with detection patterns, role/agent definitions, and multi-step workflows.
Automation run telemetry
src/automation/mod.rs
Persisted template_id/template_version to run records and emit best-effort RunTelemetryEntry after runs (aggregate counts, per-step timings, mapped statuses).
State & telemetry persistence
src/state/mod.rs
Added StepTimingEntry and RunTelemetryEntry structs and append_run_telemetry() to append JSONL to .tutti/state/run-telemetry.jsonl; handles dir creation and non-fatal IO warnings; added unit tests.
Config helpers
src/config/mod.rs
Added pub fn agent_name(&self) -> Option<&str> to WorkflowStepConfig.
Error variant tweak
src/error.rs
Added #[allow(dead_code)] to TuttiError::ConfigAlreadyExists(PathBuf) to suppress unused-variant warnings.

Sequence Diagram(s)

sequenceDiagram
    participant User as User (tty)
    participant CLI as tt init CLI
    participant Templates as Template resolver
    participant FS as Filesystem / .tutti
    participant Up as tt up (launcher)

    User->>CLI: run `tt init` (interactive)
    CLI->>Templates: resolve_template (explicit | detect | custom)
    Templates-->>CLI: selected template + metadata
    CLI->>CLI: render_team_preview()
    alt user chooses Customize
        CLI->>CLI: customize_template() loop -> render preview
    end
    opt user chooses Save or Launch
        CLI->>FS: write_config_and_register(tutti.toml)
    end
    opt user chooses Launch
        CLI->>Up: launch_agents (run `tt up`)
        Up-->>CLI: success/failure
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~55 minutes

Possibly related PRs

Poem

🐰 Hooray—v0.9 hops into sight,

Templates found and previews bright,
Tweak the team, then write or fly,
Telemetry logs each run's try,
A happy rabbit cheers: "Deploy!" 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: v0.9.0 — First 5 Minutes Magic' clearly summarizes the main feature addition: an interactive initialization system with template support and enhanced UX, directly reflecting the primary changes in the changeset.
Description check ✅ Passed The description covers all required template sections including summary of changes, versioning updates (Cargo.toml and CHANGELOG.md marked), SemVer choice (MINOR), validation status (tests pass, CI green), and release readiness.
Docstring Coverage ✅ Passed Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/first-5-minutes

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 and others added 2 commits March 23, 2026 16:02

@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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/cli/init.rs (1)

428-455: ⚠️ Potential issue | 🟠 Major

Global workspace registration is still a racy read-modify-write.

Lines 451-453 load, mutate, and save the global config with no lock. Two concurrent tt init runs can overwrite each other's workspace additions, which matches the parallel-test flake already called out in the PR summary.

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

In `@src/cli/init.rs` around lines 428 - 455, The GlobalConfig read-modify-write
in write_config_and_register is racy: replace the unguarded
GlobalConfig::load(); global.register_workspace(...); global.save() sequence
with a protected critical section that acquires an exclusive lock on the global
config (or its parent directory) before loading, mutating, and saving; use a
stable locking mechanism (e.g., an OS file lock via fs2 or a lockfile around the
same global path) so register_workspace and save occur while holding the lock
and are retried/return an error if the lock cannot be acquired.
🧹 Nitpick comments (3)
src/automation/mod.rs (1)

2591-2603: Make telemetry step IDs unique per step execution.

At Line 2595, StepTimingEntry.id is set to s.step_type, which can collide for repeated step types (e.g., multiple command steps). Use a stable unique ID (index + type, or step key) for reliable downstream analysis.

Proposed tweak
-                id: s.step_type.clone(),
+                id: format!("{:03}-{}", s.index, s.step_type),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/automation/mod.rs` around lines 2591 - 2603, The telemetry step IDs are
currently set to s.step_type which can collide for repeated step types; in the
mapping that builds step_timings (iterating over result.step_results and
constructing StepTimingEntry) change the id to a stable unique value—e.g., use
.enumerate() to include the index (format as index + step_type) or use an
existing unique step key if available on the step object—so StepTimingEntry.id
is unique per execution rather than just the step type; update the mapping where
StepTimingEntry is created and leave the duration_secs and status handling
unchanged.
src/main.rs (1)

188-190: Route template handling through a dedicated CLI subcommand module.

At Line 189, Commands::Template is dispatched to cli::init::template_list(), which couples two subcommands. Prefer a dedicated src/cli/template.rs handler (cli::template::list()), with init and template kept separate.

As per coding guidelines: src/cli/*.rs: Organize code structure with src/cli/ for Clap command handlers (one file per subcommand).

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

In `@src/main.rs` around lines 188 - 190, The Commands::Template arm currently
calls cli::init::template_list(), coupling template handling into the init
module; create a dedicated template handler and route to it by (1) adding a new
cli::template module with a public list() function to handle
TemplateSubcommand::List, (2) update the match arm for Commands::Template to
call cli::template::list() instead of cli::init::template_list(), and (3) wire
the new module into the cli module exports (pub mod template) so the symbol
cli::template::list is available.
src/template/mod.rs (1)

122-173: These discovery helpers probably shouldn't be public.

Lines 122, 146, and 176 are CLI-oriented helpers, but exposing them as pub locks in Vec/usize return shapes and the current stderr-warning behavior. If external callers do not need them, pub(crate) is the safer default; otherwise they should follow the crate's normal Result<T, TuttiError> contract.

As per coding guidelines, "All public functions must return Result<T, TuttiError>."

Also applies to: 175-219

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

In `@src/template/mod.rs` around lines 122 - 173, The two CLI-oriented helpers
detect_templates and score_template_detection are currently public but should
not be part of the external API; change their visibility to pub(crate) (or to
non-pub) so callers within the crate can still use them without locking in
return types/behaviour, and update any internal call sites accordingly; if these
functions must be public, instead change their signatures to return Result<...,
TuttiError> following the crate convention (e.g., detect_templates ->
Result<Vec<(String, ParsedTemplate, usize)>, TuttiError> and
score_template_detection -> Result<usize, TuttiError>) and propagate/convert
errors, referencing the functions detect_templates and score_template_detection
and the TemplateMetadata type to locate and modify the definitions and call
sites.
🤖 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/automation/mod.rs`:
- Around line 12-15: Run rustfmt (cargo fmt) to fix formatting issues in
src/automation/mod.rs: tidy the import list containing AutomationRunRecord,
ControlEvent, RunTelemetryEntry, StepTimingEntry, VerifyLastSummary,
WorkflowStepIntentRecord, WorkflowStepOutcomeRecord, append_automation_run,
append_control_event, append_policy_decision, append_run_telemetry,
load_workflow_checkpoint, load_workflow_intent, save_verify_last_summary so it
adheres to rustfmt rules, and reformat the duration_secs expression around the
code that computes duration_secs (the wrapping at the duration_secs expression
near where run telemetry or step timing is handled) so it matches rustfmt line
wrapping. After running cargo fmt, verify the imports and the expression are
properly wrapped and commit the formatted file.

In `@src/cli/init.rs`:
- Around line 21-45: The prompt_choice function currently treats EOF/read errors
as selecting the first option which can be "Q" but still lets the caller perform
side effects; update prompt_choice to explicitly return "Q" (or a clear "QUIT")
on EOF or read error so non-interactive stdin always aborts, and then modify the
caller logic that handles the selection (the branch that writes tutti.toml and
calls workspace registration) to check for the explicit "Q"/"QUIT" value and
immediately return/abort without creating or overwriting files; refer to
prompt_choice and the code block that writes tutti.toml / registers the
workspace and ensure the Quit path is side-effect free.

In `@src/state/mod.rs`:
- Around line 652-684: The new public function append_run_telemetry currently
swallows all errors and returns (), violating the guideline that public APIs
return Result; either make it non-public for best-effort telemetry (change pub
to pub(crate) on append_run_telemetry) or change its signature to return
Result<(), TuttiError> and propagate failures (filesystem and serde errors) as
TuttiError from create_dir_all, serde_json::to_string, OpenOptions::open and
writeln! so callers can decide how to handle/log them; update call sites
accordingly.

In `@templates/node-fullstack.toml`:
- Around line 11-18: The template defines a dedicated template.roles.frontend
agent but never routes any implementation steps to it (planner, backend, tester
are used exclusively), so either add a frontend step or remove the unused agent:
update the planner's plan generation or the implementation dispatch logic to
include a frontend implementation path that sends UI-related steps to the
template.roles.frontend agent (e.g., create a "frontend" implementation step
alongside "backend" and "tester" and ensure the implementation dispatcher sends
that step to template.roles.frontend), or alternatively delete
template.roles.frontend and any references to a frontend role so the template
only advertises agents actually used.

---

Outside diff comments:
In `@src/cli/init.rs`:
- Around line 428-455: The GlobalConfig read-modify-write in
write_config_and_register is racy: replace the unguarded GlobalConfig::load();
global.register_workspace(...); global.save() sequence with a protected critical
section that acquires an exclusive lock on the global config (or its parent
directory) before loading, mutating, and saving; use a stable locking mechanism
(e.g., an OS file lock via fs2 or a lockfile around the same global path) so
register_workspace and save occur while holding the lock and are retried/return
an error if the lock cannot be acquired.

---

Nitpick comments:
In `@src/automation/mod.rs`:
- Around line 2591-2603: The telemetry step IDs are currently set to s.step_type
which can collide for repeated step types; in the mapping that builds
step_timings (iterating over result.step_results and constructing
StepTimingEntry) change the id to a stable unique value—e.g., use .enumerate()
to include the index (format as index + step_type) or use an existing unique
step key if available on the step object—so StepTimingEntry.id is unique per
execution rather than just the step type; update the mapping where
StepTimingEntry is created and leave the duration_secs and status handling
unchanged.

In `@src/main.rs`:
- Around line 188-190: The Commands::Template arm currently calls
cli::init::template_list(), coupling template handling into the init module;
create a dedicated template handler and route to it by (1) adding a new
cli::template module with a public list() function to handle
TemplateSubcommand::List, (2) update the match arm for Commands::Template to
call cli::template::list() instead of cli::init::template_list(), and (3) wire
the new module into the cli module exports (pub mod template) so the symbol
cli::template::list is available.

In `@src/template/mod.rs`:
- Around line 122-173: The two CLI-oriented helpers detect_templates and
score_template_detection are currently public but should not be part of the
external API; change their visibility to pub(crate) (or to non-pub) so callers
within the crate can still use them without locking in return types/behaviour,
and update any internal call sites accordingly; if these functions must be
public, instead change their signatures to return Result<..., TuttiError>
following the crate convention (e.g., detect_templates -> Result<Vec<(String,
ParsedTemplate, usize)>, TuttiError> and score_template_detection ->
Result<usize, TuttiError>) and propagate/convert errors, referencing the
functions detect_templates and score_template_detection and the TemplateMetadata
type to locate and modify the definitions and call sites.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5de598c7-c5ef-4512-82ff-8ed2c0bd014f

📥 Commits

Reviewing files that changed from the base of the PR and between df5d60f and 02e2941.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • CHANGELOG.md
  • Cargo.toml
  • src/automation/mod.rs
  • src/cli/init.rs
  • src/cli/mod.rs
  • src/main.rs
  • src/state/mod.rs
  • src/template/mod.rs
  • templates/node-fullstack.toml
  • templates/python-api.toml

Comment thread src/automation/mod.rs Outdated
Comment thread src/cli/init.rs
Comment thread src/cli/init.rs
Comment thread src/state/mod.rs
Comment thread templates/node-fullstack.toml

@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: 3

♻️ Duplicate comments (3)
src/state/mod.rs (1)

652-684: ⚠️ Potential issue | 🟠 Major

Make the telemetry writer internal or return Result<()>.

This new pub fn swallows serialization and filesystem failures behind eprintln!, so callers cannot decide whether telemetry loss should warn, retry, or fail the command. If telemetry is intentionally best-effort, make the function pub(crate); otherwise return Result<()> and let the caller downgrade it to a warning. As per coding guidelines, "All public functions must return Result<T, TuttiError>."

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

In `@src/state/mod.rs` around lines 652 - 684, The public function
append_run_telemetry currently swallows serialization and IO errors with
eprintln!; change it to either be internal (pub(crate) fn append_run_telemetry)
if telemetry should stay best-effort, or update the signature to pub fn
append_run_telemetry(project_root: &Path, entry: &RunTelemetryEntry) ->
Result<(), TuttiError> and propagate failures instead of printing: return
Err(TuttiError::Serialization(...)) for serde_json::to_string errors and
Err(TuttiError::Io(...)) for create_dir_all/OpenOptions/writeln failures (or map
them to existing TuttiError variants), removing eprintln! calls so callers can
decide to downgrade to a warning or fail.
src/cli/init.rs (2)

353-387: ⚠️ Potential issue | 🟠 Major

Block agent removal while workflows still reference it.

This removes the [[agent]] block and maybe the role, but it never rewrites or validates workflow steps that still target that agent. Customize can therefore save a config that parses but fails later when the workflow reaches the removed agent.

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

In `@src/cli/init.rs` around lines 353 - 387, Before removing an [[agent]] block,
check all workflows in the parsed config for any steps that reference that agent
(by name or by role) and refuse the removal if any reference exists;
specifically, in the "2" branch where you call
remove_agent_from_config_body(&mut parsed.config_body, agent_name) and mutate
parsed.metadata.roles, first iterate config.workflows (and each workflow's
steps/targets) to detect any step.agent == agent_name or any step that targets
the agent's role, and if any are found print a clear blocking message (e.g.,
"Cannot remove agent — referenced by workflow X step Y.") and continue without
removing; only proceed to remove the [[agent]] block and metadata.roles when no
workflow references the agent.

20-33: ⚠️ Potential issue | 🟠 Major

Abort on EOF/read errors, and keep Quit side-effect free.

prompt_choice still turns EOF/read failures into the first real option, so non-interactive stdin can back up configs, auto-pick template 1, or launch immediately. The main "Q" branch then writes tutti.toml and registers the workspace anyway, which contradicts the prompt text. Please surface an explicit abort from prompt_choice and have callers short-circuit before any write or launch.

Also applies to: 82-93, 111-156

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

In `@src/cli/init.rs` around lines 20 - 33, prompt_choice on StdinInput currently
treats EOF/read errors as selecting the first real option, causing
non-interactive runs to proceed and trigger side-effects like writing tutti.toml
and registering the workspace; change prompt_choice to return a Result<String,
PromptError> (or Option<String>) and on Ok return the chosen option, but on EOF
or read Err return Err/None to indicate explicit abort; update all callers of
InputSource::prompt_choice (the init flow that writes tutti.toml and registers
the workspace/launch logic) to short-circuit on Err/None before performing any
writes or launches, and ensure the "Q"/Quit branch in callers performs no
side-effects when abort is returned.
🤖 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/init.rs`:
- Around line 401-423: The removal logic in remove_agent_from_config_body stops
at "\n[[" only, so regular TOML tables like [hooks] or [env] after the agent get
swallowed; change the block_end computation (the code that uses
after_block.find("\n[[") and maps to block_end) to look for the next table
header start "\n[" (not just "\n[[") and compute the same offset from
block_start + "[[agent]]".len(), so the deletion stops at any next TOML table
header; keep the existing trim_start behavior and replace_range call.

In `@src/template/mod.rs`:
- Around line 200-208: Discovery currently appends every parsed template (via
parse_template) into the templates Vec using parsed.metadata.name which allows
duplicate names; change discovery to dedupe by template name and warn on
collisions: instead of blindly pushing into templates, track seen names (e.g.,
HashMap<String, ParsedTemplate> or a HashSet of names) when handling each parsed
result in the loop over entries, and if parsed.metadata.name already exists emit
a warning (use the existing logger) and skip adding the duplicate so only the
first occurrence is kept; ensure this same dedup logic is applied to the other
discovery block that builds templates (the code path around load_template) so
load_template continues to find an unambiguous exact-name hit.
- Around line 150-152: The functions score_template_detection and
discover_custom_templates are exposed as public but are internal helpers; make
them crate-private or convert their signatures to return a Result to comply with
the public API rule. Update the visibility of score_template_detection and
discover_custom_templates from pub to pub(crate) if they should remain internal;
otherwise change their return types to Result<usize, TuttiError> and
Result<Vec<Template>, TuttiError> (or appropriate inner types) and propagate
errors from their internals so callers can handle failures. Ensure you adjust
all call sites to match the new signatures and import TuttiError where needed.

---

Duplicate comments:
In `@src/cli/init.rs`:
- Around line 353-387: Before removing an [[agent]] block, check all workflows
in the parsed config for any steps that reference that agent (by name or by
role) and refuse the removal if any reference exists; specifically, in the "2"
branch where you call remove_agent_from_config_body(&mut parsed.config_body,
agent_name) and mutate parsed.metadata.roles, first iterate config.workflows
(and each workflow's steps/targets) to detect any step.agent == agent_name or
any step that targets the agent's role, and if any are found print a clear
blocking message (e.g., "Cannot remove agent — referenced by workflow X step
Y.") and continue without removing; only proceed to remove the [[agent]] block
and metadata.roles when no workflow references the agent.
- Around line 20-33: prompt_choice on StdinInput currently treats EOF/read
errors as selecting the first real option, causing non-interactive runs to
proceed and trigger side-effects like writing tutti.toml and registering the
workspace; change prompt_choice to return a Result<String, PromptError> (or
Option<String>) and on Ok return the chosen option, but on EOF or read Err
return Err/None to indicate explicit abort; update all callers of
InputSource::prompt_choice (the init flow that writes tutti.toml and registers
the workspace/launch logic) to short-circuit on Err/None before performing any
writes or launches, and ensure the "Q"/Quit branch in callers performs no
side-effects when abort is returned.

In `@src/state/mod.rs`:
- Around line 652-684: The public function append_run_telemetry currently
swallows serialization and IO errors with eprintln!; change it to either be
internal (pub(crate) fn append_run_telemetry) if telemetry should stay
best-effort, or update the signature to pub fn
append_run_telemetry(project_root: &Path, entry: &RunTelemetryEntry) ->
Result<(), TuttiError> and propagate failures instead of printing: return
Err(TuttiError::Serialization(...)) for serde_json::to_string errors and
Err(TuttiError::Io(...)) for create_dir_all/OpenOptions/writeln failures (or map
them to existing TuttiError variants), removing eprintln! calls so callers can
decide to downgrade to a warning or fail.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7ae00dcb-5310-4f1b-80cf-709cf7ce1e0f

📥 Commits

Reviewing files that changed from the base of the PR and between 02e2941 and 88aec03.

📒 Files selected for processing (5)
  • src/automation/mod.rs
  • src/cli/init.rs
  • src/error.rs
  • src/state/mod.rs
  • src/template/mod.rs
✅ Files skipped from review due to trivial changes (1)
  • src/error.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/automation/mod.rs

Comment thread src/cli/init.rs
Comment thread src/template/mod.rs Outdated
Comment thread src/template/mod.rs Outdated
1. init: Quit option now exits cleanly without writing files; EOF/read
   errors map to Quit (abort) instead of the first option. Added
   Save-only option [S] for writing config without launching.

2. init: Removing an agent now also removes dangling workflow steps
   that reference it, via new remove_workflow_steps_for_agent helper.

3. state: Changed append_run_telemetry from pub to pub(crate) since it
   is best-effort telemetry that swallows errors intentionally.

4. templates/node-fullstack: Added ensure_running and implement steps
   for the frontend agent so it actually participates in the workflow.

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

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

🧹 Nitpick comments (1)
templates/node-fullstack.toml (1)

130-134: Consider using cwd = "agent_worktree" instead of hard-coded path.

The hard-coded path .tutti/worktrees/backend couples this step to the agent name. Using the workflow config's built-in cwd option would be more maintainable:

♻️ Suggested improvement
 [[workflow.step]]
 id = "validate"
 type = "command"
-run = "cd .tutti/worktrees/backend && npm test --quiet"
+run = "npm test --quiet"
+cwd = "agent_worktree"
+agent = "backend"
 fail_mode = "closed"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/node-fullstack.toml` around lines 130 - 134, The workflow step with
id "validate" currently hardcodes the agent path in run ("cd
.tutti/worktrees/backend && npm test --quiet"); change this to use the workflow
step's cwd option (cwd = "agent_worktree") and simplify run to just "npm test
--quiet" so the step no longer depends on the agent name; update the
[[workflow.step]] block for id "validate" accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@templates/node-fullstack.toml`:
- Around line 130-134: The workflow step with id "validate" currently hardcodes
the agent path in run ("cd .tutti/worktrees/backend && npm test --quiet");
change this to use the workflow step's cwd option (cwd = "agent_worktree") and
simplify run to just "npm test --quiet" so the step no longer depends on the
agent name; update the [[workflow.step]] block for id "validate" accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 72c750d6-cda7-4145-84ed-a86a61a62dfa

📥 Commits

Reviewing files that changed from the base of the PR and between 88aec03 and 8f0784c.

📒 Files selected for processing (4)
  • src/cli/init.rs
  • src/config/mod.rs
  • src/state/mod.rs
  • templates/node-fullstack.toml
✅ Files skipped from review due to trivial changes (1)
  • src/cli/init.rs

- Stop agent block removal at any table header (not just [[)
- Make score_template_detection and discover_custom_templates pub(crate)
- Reject duplicate custom template names during discovery

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

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

🧹 Nitpick comments (1)
src/template/mod.rs (1)

185-188: Optional: Consider cross-platform home directory resolution for custom template discovery.

The HOME environment variable is unset on Windows; consider using the dirs or home crate for portable home directory detection. This function currently returns an empty template list on missing HOME, which is acceptable for optional discovery, but would improve Windows compatibility if it becomes a supported platform.

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

In `@src/template/mod.rs` around lines 185 - 188, The current discovery code
assigns `home` from std::env::var("HOME") and returns early when missing; update
it to use a cross‑platform home resolver (e.g., the dirs crate's
dirs::home_dir() or the home crate) instead of relying solely on the HOME env
var: add the chosen crate to Cargo.toml, replace the std::env::var("HOME") match
that produces the `home` variable with a call to the cross‑platform helper (fall
back to returning `templates` if that helper returns None), and ensure
subsequent code still uses the `home` variable unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/template/mod.rs`:
- Around line 185-188: The current discovery code assigns `home` from
std::env::var("HOME") and returns early when missing; update it to use a
cross‑platform home resolver (e.g., the dirs crate's dirs::home_dir() or the
home crate) instead of relying solely on the HOME env var: add the chosen crate
to Cargo.toml, replace the std::env::var("HOME") match that produces the `home`
variable with a call to the cross‑platform helper (fall back to returning
`templates` if that helper returns None), and ensure subsequent code still uses
the `home` variable unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 449a7ae0-4876-4a83-850e-166b47ae7f2b

📥 Commits

Reviewing files that changed from the base of the PR and between 8f0784c and 77f2408.

📒 Files selected for processing (2)
  • src/cli/init.rs
  • src/template/mod.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/cli/init.rs

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