Conversation
Add PRE_TOOL_USE hook that checks cumulative cost against configurable session and round budgets. Three actions on exceed: block, warn, or terminate. Progressive warnings at configurable thresholds. Thread-safe via threading.Lock on all BudgetState mutations. 74 tests covering happy path, adversarial inputs, and concurrency. Addresses #781, related to #994.
- Add Google-style docstring to __init__ with param descriptions - Narrow thread test exception catch to specific types (BLE001)
… refinement guard; try personas; prompt improvmeent there
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (100)
📒 Files selected for processing (11)
📝 WalkthroughWalkthroughBumps package version and adds checkpoint and prompt-improver coordination fields; introduces workspace path-rewriting/scrubbing utilities and MCP result stringifier; rotates coordination path tokens; expands CLI step-mode persistence and WebUI/TUI/server event/state features; numerous docs and config updates. Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 3 | ❌ 3❌ Failed checks (2 warnings, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
feat: Modernize webui
feat: add RoundBudgetGuardHook for cost enforcement
There was a problem hiding this comment.
Actionable comments posted: 16
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
massgen/cli.py (2)
11739-11750:⚠️ Potential issue | 🟠 MajorPreserve existing query params when adding
v=2.When
auto_urlalready containspromptand/orconfig, appending"/?v=2"produces malformed URLs like...?config=.../?v=2. That breaks auto-open for the common--web --config ... "question"path and can drop the seeded prompt/config entirely.🐛 Proposed fix
- browser_url = auto_url if auto_url else f"http://{args.web_host}:{args.web_port}" - # Remove trailing slash to avoid double slashes - browser_url = browser_url.rstrip("/") - - # Default to v2 UI; --quickstart opens the wizard overlay, - # --setup opens the setup overlay in v2. - if getattr(args, "setup", False): - browser_url += "/?v=2&setup=open" - elif getattr(args, "quickstart", False): - browser_url += "/?v=2&wizard=open" - else: - browser_url += "/?v=2" + from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit + + browser_url = auto_url if auto_url else f"http://{args.web_host}:{args.web_port}/" + parts = urlsplit(browser_url) + query = dict(parse_qsl(parts.query, keep_blank_values=True)) + query["v"] = "2" + if getattr(args, "setup", False): + query["setup"] = "open" + elif getattr(args, "quickstart", False): + query["wizard"] = "open" + browser_url = urlunsplit( + ( + parts.scheme, + parts.netloc, + parts.path or "/", + urlencode(query), + parts.fragment, + ) + )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/cli.py` around lines 11739 - 11750, The current logic appends "/?v=2" blindly to browser_url (built from auto_url or f"http://{args.web_host}:{args.web_port}") which corrupts existing query params; update the code that builds browser_url to parse the URL (e.g., using urllib.parse.urlparse / parse_qsl), merge or inject the v=2 parameter and optionally setup=open or wizard=open based on getattr(args, "setup") / getattr(args, "quickstart"), then rebuild the URL with urlunparse so existing prompt/config params are preserved instead of creating ".../?v=2" after an existing query string.
10065-10084:⚠️ Potential issue | 🟠 MajorDon't let step-mode finalization write an unsanitized second copy of the answer.
save_step_mode_output()now getsstale_workspace_paths, butmassgen/orchestrator.py:4208-4251writesself._step_action_data["answer_text"]straight intofinal/answer.txtduringfinalize_step_mode()and never applies the same rewrite. That makes the newfinal/artifact diverge from the scrubbed step artifact and can reintroduce dead workspace paths for replay/viewer consumers.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/cli.py` around lines 10065 - 10084, The finalize_step_mode() implementation currently writes self._step_action_data["answer_text"] directly into final/answer.txt, producing an unsanitized duplicate that can diverge from the scrubbed output saved by save_step_mode_output(); modify finalize_step_mode (or the related orchestration flow) to write the already-sanitized answer instead — either by having save_step_mode_output return the sanitized text (and using that), by reading the scrubbed artifact that save_step_mode_output produced, or by invoking the same sanitizer/rewriter used there before writing final/answer.txt — ensuring no raw self._step_action_data["answer_text"] is written to final/.
🧹 Nitpick comments (12)
massgen/backend/codex.py (1)
2128-2160: Minor edge case: empty string results fall through to JSON serialization.The condition
isinstance(text, str) and texton line 2146 treats empty strings as falsy, causing them to fall through tojson.dumpsinstead of returning the empty string directly. If MCP tools can legitimately return empty string results, this may produce unexpected output like{"content": [{"type": "text", "text": ""}], ...}instead of"".If empty strings are valid results, consider:
🔧 Suggested fix
- if isinstance(text, str) and text: + if isinstance(text, str): return textOtherwise, if the current behavior is intentional (showing full structure for empty results), a brief comment would clarify the design choice.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/backend/codex.py` around lines 2128 - 2160, The _stringify_mcp_result function currently treats empty strings as falsy and falls through to JSON serialization; update the logic in _stringify_mcp_result (inside the loop over content_list) to return the text whenever isinstance(text, str) (i.e., allow empty string "" to be returned directly) instead of requiring truthiness, so a {"type":"text","text":""} yields ""—also add a short comment explaining this decision or, if you prefer the original behavior, add a clarifying comment and a test to assert the intended output.massgen/filesystem_manager/_path_rewriter.py (2)
182-200: Consider handling potential rename collisions.If two files contain different agent IDs but would map to the same anonymous ID (e.g.,
task_agent_a.mdandtask_agent_b.mdboth mapping totask_agent_0.md), the second rename would fail on Windows or silently overwrite on Unix.While this is unlikely in practice, adding a collision check would make the code more robust:
Suggested defensive check
if new_name != file_path.name: new_path = file_path.parent / new_name + if new_path.exists(): + logger.debug( + "[PathRewriter] Skipping rename %s -> %s: target exists", + file_path, + new_path, + ) + continue try: file_path.rename(new_path)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/filesystem_manager/_path_rewriter.py` around lines 182 - 200, The current rename pass can produce collisions when multiple original names map to the same anonymous name; update the loop that constructs renamed_files (iterating over target_files and using ordered) to detect collisions before calling file_path.rename by checking if new_path already exists on disk or is already a target in renamed_files.values(), and on collision either generate a unique fallback name (e.g., append a numeric suffix) or skip and log a clear warning via logger.debug/logger.warning; ensure modified is only incremented on a successful rename and preserve existing exception handling around file_path.rename.
138-158: Minor: Consider clarifying the return value semantics in the docstring.The return value counts both renames and content modifications separately, so a file that is both renamed and content-modified will contribute 2 to the count. The current phrasing "Count of files renamed or content-modified" could be interpreted as counting unique files. Consider clarifying:
Returns: - Count of files renamed or content-modified. + Total count of modifications (file renames + content replacements). + A file that is both renamed and content-modified counts twice.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/filesystem_manager/_path_rewriter.py` around lines 138 - 158, The docstring for scrub_agent_ids_in_snapshot is ambiguous about the return count; update the Returns section to state explicitly that the function returns the total number of operations (each rename and each content modification counted separately), so a single file that is both renamed and modified contributes 2 to the returned count; edit the Returns text in the scrub_agent_ids_in_snapshot docstring to reflect this semantics and mention that the count is the sum of renames and content-modifications rather than unique files.massgen/filesystem_manager/_filesystem_manager.py (1)
2342-2345: Consider adding.claudeto_WORKSPACE_METADATA_DIRSfor consistency.The new
_snapshot_exclude_dirsincludes.claude, but_WORKSPACE_METADATA_DIRS(line 127) doesn't. If the Claude backend creates a.claude/config directory in the workspace,has_meaningful_content()won't exclude it, potentially causing the final snapshot to copy a near-empty workspace instead of falling back tosnapshot_storagewith real deliverables.Additionally, consider defining
_snapshot_exclude_dirsas a module-level constant (like_WORKSPACE_METADATA_DIRS) to avoid recreating the set on every method call.Suggested changes
At line 127, update
_WORKSPACE_METADATA_DIRS:-_WORKSPACE_METADATA_DIRS = frozenset({".git", ".codex", ".gemini", ".massgen", "memory"}) +_WORKSPACE_METADATA_DIRS = frozenset({".git", ".codex", ".gemini", ".claude", ".massgen", "memory"})And consider moving
_snapshot_exclude_dirsto module level near_WORKSPACE_METADATA_DIRS:+# Framework metadata dirs to exclude when copying snapshots to temp workspace. +# Agents don't need these for evaluating others' work. +_SNAPSHOT_EXCLUDE_DIRS = frozenset({".massgen", ".codex", ".gemini", ".claude", ".git"})Based on learnings: "Backends that create config directories in the workspace (e.g.,
.codex/for Codex) must add those directory names to the_metadata_dirsset inFilesystemManager.save_snapshot()'shas_meaningful_content()helper."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/filesystem_manager/_filesystem_manager.py` around lines 2342 - 2345, Add the ".claude" entry to the existing _WORKSPACE_METADATA_DIRS set and promote the per-call _snapshot_exclude_dirs to a module-level constant (e.g. _SNAPSHOT_EXCLUDE_DIRS) so it isn’t rebuilt on each call; then update FilesystemManager.save_snapshot()'s has_meaningful_content() to reference the module-level _SNAPSHOT_EXCLUDE_DIRS (and/or merge it with _WORKSPACE_METADATA_DIRS if appropriate) so Claude-created .claude/ directories are consistently treated as metadata and excluded from snapshot content checks.massgen/frontend/displays/textual_widgets/tab_bar.py (1)
127-130: Use Google-style docstrings on the newupdate_improved_promptmethods.Both setters are newly introduced but only have one-line docstrings, which is inconsistent with the repo’s Python docstring rule.
As per coding guidelines,
**/*.py: For new or changed functions, include Google-style docstrings.Also applies to: 436-439
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/displays/textual_widgets/tab_bar.py` around lines 127 - 130, Replace the one-line docstring on update_improved_prompt with a Google-style docstring: start with a short description, then an Args section documenting improved_prompt: Optional[str] (what it represents), and a Returns section specifying None; ensure the docstring follows the project's Google-style formatting (triple-quoted, parameter types and descriptions). Apply the same Google-style docstring pattern to the other newly added setter in this file so both setters consistently use Google-style docstrings.massgen/frontend/displays/web_display.py (1)
124-151: Use full Google-style docstrings for newly added methods.Several new/changed methods have short docstrings but omit standard Google-style sections (notably
Args:), which makes generated/internal docs less consistent.As per coding guidelines "
**/*.py: For new or changed functions, include Google-style docstrings".Also applies to: 343-392, 611-623
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/displays/web_display.py` around lines 124 - 151, The two new methods _register_event_listener and _on_structured_event have short one-line docstrings; update both to full Google-style docstrings including a brief description, an Args: section documenting parameters (e.g., event: Any for _on_structured_event), a Returns: section (None), and a Raises: section if they can raise exceptions (or note that exceptions are swallowed). Ensure the docstring format matches other files (Google style) so generated docs are consistent.massgen/frontend/displays/textual_terminal_display.py (2)
1226-1230: Use Google-style docstrings for the new pre-collab helpers.These new/changed methods take parameters and encode retry behavior, but the current one-line docstrings don't document that surface. Please add
Args:sections, andReturns:where helpful, while the flow is still fresh.As per coding guidelines
**/*.py: For new or changed functions, include Google-style docstrings.Also applies to: 6454-6565, 7924-7927
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/displays/textual_terminal_display.py` around lines 1226 - 1230, The one-line docstring for notify_prompt_improved is missing a Google-style docstring; update the function (and the other affected functions in the same diff ranges) to use a full Google-style docstring that documents parameters and return values (e.g., an "Args:" section describing improved_prompt: str and any behavior like early-return when self._app is falsy, and a "Returns:" section if applicable, or state that it returns None). Locate notify_prompt_improved and the other changed methods referenced (around lines 6454-6565 and 7924-7927) and replace their single-line docstrings with proper Google-style docstrings including Args: and Returns: entries.
6496-6527: Factor the friendly parallel pre-collab model-building into one helper.Both the auto-open path and the
Ctrl+Ufallback hand-build the sameSubagentDisplayDatacopies. That duplication is easy to drift the next time the model or tab metadata changes.Also applies to: 8180-8215
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/displays/textual_terminal_display.py` around lines 6496 - 6527, Extract the repeated logic that builds a friendly SubagentDisplayData copy into a single helper (e.g., _build_precollab_subagent_display or make_precollab_display) and call it from both places (the auto-open path and the Ctrl+U fallback) instead of duplicating the field-by-field construction; the helper should accept the subagent id (sid) and the stored state (state or state.data) and use _PRECOLLAB_DISPLAY_NAMES, SubagentDisplayData, and the same fields (task, status, progress_percent, elapsed_seconds, timeout_seconds, workspace_path, workspace_file_count, last_log_line, error, answer_preview, log_path, subagent_type) so both call sites (_parallel_precollab_expected/_precollab_subagents handling and the alternate block referenced around 8180-8215) simply call the helper and append the returned SubagentDisplayData to subagents.massgen/frontend/displays/textual_widgets/subagent_screen.py (4)
127-133: Bare exception withpassswallows errors silently.The
try-except-passpattern here can hide issues during development and debugging. Consider logging the exception using the existingtui_loghelper for consistency with other error handling in this file.🔧 Suggested improvement
def set_multi(self, multi: bool) -> None: """Mark this header as part of a multi-tab view.""" self._multi = multi try: self.query_one("#header_title", Static).update(self._build_title()) - except Exception: - pass + except Exception as e: + tui_log(f"[SubagentHeader] set_multi failed: {e}")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/displays/textual_widgets/subagent_screen.py` around lines 127 - 133, The set_multi method currently swallows all exceptions with a bare except/pass when updating the header title; instead catch Exception as e and log the error via the existing tui_log helper so failures in query_one("#header_title", Static).update(self._build_title()) are visible during debugging. Update set_multi to replace the silent except with an explicit exception handler that calls tui_log (e.g., tui_log.error or tui_log.exception) including the exception and a brief context message referencing set_multi/_build_title/header_title.
1127-1135: Duplicate persona extraction logic should be extracted to a helper method.The same persona label parsing logic appears here and again at lines 1836-1845 in
_switch_subagent(). Extract this to a private helper to improve maintainability and reduce duplication.♻️ Suggested refactor
Add a helper method to the class:
def _extract_persona_labels(self) -> dict[str, str]: """Extract evaluator persona labels from agent system prompts.""" persona_labels: dict[str, str] = {} for aid, prompt in self._inner_agent_system_prompts.items(): if "Evaluator Persona:" in prompt: label = prompt.split("Evaluator Persona:")[1].split("\n")[0].strip() if label: persona_labels[aid] = label return persona_labelsThen replace both occurrences with:
- persona_labels = {} - for aid, prompt in self._inner_agent_system_prompts.items(): - if "Evaluator Persona:" in prompt: - label = prompt.split("Evaluator Persona:")[1].split("\n")[0].strip() - persona_labels[aid] = label - if persona_labels: - self._inner_tab_bar.set_agent_personas(persona_labels) + persona_labels = self._extract_persona_labels() + if persona_labels and self._inner_tab_bar: + self._inner_tab_bar.set_agent_personas(persona_labels)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/displays/textual_widgets/subagent_screen.py` around lines 1127 - 1135, Extract the duplicated evaluator persona parsing into a private helper on the class (e.g. def _extract_persona_labels(self) -> dict[str, str]) that iterates self._inner_agent_system_prompts, looks for "Evaluator Persona:", pulls the first line after that, strips it, and returns a dict of aid->label (only when label non-empty); then replace the inline parsing blocks in the shown method and in _switch_subagent() with a single call to self._extract_persona_labels() and pass the returned dict to self._inner_tab_bar.set_agent_personas where needed.
1487-1491: Redundant status check on Line 1490.Line 1488 already ensures no subagent (including
self._subagent) is running/pending. The check on line 1490 is redundant sinceself._subagentis always part ofself._all_subagents.♻️ Simplification
# When multiple subagents exist, wait for ALL to finish if any(sa.status in ("running", "pending") for sa in self._all_subagents): return - if self._subagent.status in ("running", "pending"): - return if not self._has_final_answer_content(): return🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/displays/textual_widgets/subagent_screen.py` around lines 1487 - 1491, The second check is redundant because self._subagent is included in self._all_subagents; remove the if block that checks self._subagent.status in ("running", "pending") and rely solely on the any(...) check over self._all_subagents (located near the code handling subagent status in the subagent_screen class/method using self._all_subagents and self._subagent).
1648-1663: Usedataclasses.replace()instead of field-by-field reconstruction.
SubagentDisplayDatais a dataclass. The manual field-by-field reconstruction at lines 1648–1663 is fragile—any new fields added to the class in the future will be silently dropped. Usedataclasses.replace(new_data, subagent_type=sa.subagent_type)instead:Suggested fix
from dataclasses import replace # In _poll_updates() at line 1649: if not getattr(new_data, "subagent_type", None) and getattr(sa, "subagent_type", None): new_data = replace(new_data, subagent_type=sa.subagent_type)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/displays/textual_widgets/subagent_screen.py` around lines 1648 - 1663, Replace the fragile manual reconstruction of SubagentDisplayData with dataclasses.replace to preserve future fields: inside _poll_updates where you check if not getattr(new_data, "subagent_type", None) and getattr(sa, "subagent_type", None), call replace(new_data, subagent_type=sa.subagent_type) instead of re-creating SubagentDisplayData with explicit fields so any added fields on SubagentDisplayData are retained.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/modules/step_mode.md`:
- Line 80: Several fenced code blocks in the Step Mode documentation are missing
language identifiers; find each triple-backtick block (``` ) in the Step Mode
section referenced by this review and add an explicit language token (use text
for plain text, bash for shell/CLI examples, json for JSON snippets) so
markdownlint MD040 is satisfied—replace occurrences of ``` with ```text,
```bash, or ```json as appropriate.
In `@massgen/agent_config.py`:
- Around line 220-222: AgentConfig currently drops new coordination flags on
serialization; update AgentConfig.to_dict (and complementary
from_dict/constructor) to include the full coordination_config
fields—specifically ensure prompt_improver (PromptImproverConfig) and
enable_evaluator_personas are serialized into the dict and restored on load.
Locate the AgentConfig.to_dict method and add entries for
coordination_config.prompt_improver (or the whole coordination_config sub-dict)
and coordination_config.enable_evaluator_personas, and update the
deserialization path that reconstructs AgentConfig to read these keys back into
coordination_config so saved configs preserve these flags.
In `@massgen/cli.py`:
- Around line 10085-10086: The docstring for save_step_mode_output incorrectly
says "Also writes last_action.json at the session root"; update it to state that
last_action.json is written per-agent at agents/<agent_id>/last_action.json (the
same path referenced by the CLI STATUS output and the implementation in
save_step_mode_output) and mention that this per-agent placement avoids race
conditions between agents as noted in the inline comment.
In `@massgen/configs/features/round_evaluator_example.yaml`:
- Around line 66-73: The inline checklist example under
checklist_criteria_inline currently shows categories "should" and "could" which
are actually coerced to "must" at runtime; update the example so all entries use
category: must to reflect real behavior, or alternatively add a short comment
next to checklist_criteria_inline explaining that non-"must" categories are
promoted/coerced to "must" at runtime; reference the checklist_criteria_inline
key and the category values ("must"/"should"/"could") when making the change.
In `@massgen/evaluation_criteria_generator.py`:
- Around line 1044-1063: The current code only tries the single newest file from
find_precollab_artifact and bails if it's unreadable; instead, obtain the full
set of matching candidates under "criteria_generation" (e.g., via an existing
finder that returns all matches or by listing the directory), sort them
newest-first, then loop over each candidate file (the variable currently named
criteria_file), attempt to read_text() and call _parse_criteria_response on
each, return the first successful criteria, and only after all candidates fail
return None; on per-file failures keep the logger.debug(f"Failed to parse
{criteria_file}: {e}") behavior so truncated/temp files are skipped but
recorded.
In `@massgen/frontend/displays/textual_terminal_display.py`:
- Around line 6624-6635: The guard using state.auto_opened prevents reopening
when a pre-collab subagent is reused; modify update_runtime_subagent_card (the
code that clears call_id) to also reset state.auto_opened = False whenever a
subagent's call_id is cleared or its lifecycle ends, so the next run will hit
the auto-open logic in textual_terminal_display (the block that checks
state.auto_opened and calls
_auto_open_precollab_screen/_try_open_unified_precollab_screen); ensure you only
reset auto_opened for pre-collab subagents (e.g., those in
_PARALLEL_PRECOLLAB_IDS or the "task_decomposition" id) to avoid reopening
unrelated screens.
In `@massgen/frontend/displays/textual_widgets/tab_bar.py`:
- Around line 436-439: The setter update_improved_prompt currently forwards
improved_prompt only to self._session_info_widget and drops the value if that
child isn't yet composed; add a local field (e.g. self._improved_prompt) on
AgentTabBar, set it inside update_improved_prompt, and still call
self._session_info_widget.update_improved_prompt(improved_prompt) when
_session_info_widget exists; also ensure wherever the SessionInfoWidget is
instantiated or attached it reads/initializes its state from
AgentTabBar._improved_prompt so the improved prompt state persists and the
indicator/modal appears even if update_improved_prompt fired before composition.
In `@massgen/frontend/displays/web_display.py`:
- Around line 109-110: The code appends every event to self._event_history
causing unbounded memory growth; change _event_history to a bounded container
and enforce retention when adding events: replace the current list with a
collections.deque(maxlen=N) or implement a fixed-cap policy in the method that
calls self._event_history.append (referencing _event_history and the append site
in WebDisplay) so older events are dropped automatically (choose a sensible N,
e.g., config-driven) and preserve thread-safety if needed when mutating the
history.
- Around line 83-85: The EventEmitter listener registered by
WebDisplay._register_event_listener() is not removed, causing listener
accumulation; update WebDisplay.cleanup() to call
emitter.remove_listener(self._event_listener) (using the same EventEmitter
instance and the _event_listener attribute the registration created) so the
callback is unregistered during teardown and prevents retained references to
closed WebDisplay instances.
In `@massgen/frontend/web/server.py`:
- Around line 2369-2418: The delete handler currently removes displays, tasks,
orchestrators, and registry entries but must also clear websocket state: remove
any entries for session_id from manager.active_connections and from
workspace_manager.workspace_connections (if present); for each websocket found,
close/terminate the socket (e.g., call .close() or await .close() as
appropriate) before deleting the mapping entry to ensure no further broadcasts
reach that session, and then delete the keys from both mappings so the session
is no longer considered active.
- Around line 907-930: This route reads an arbitrary path into config_path and
only checks backend.get("model"), which bypasses the guarded loader used by
/api/config/content and misses models stored in backend_params.model; update
this handler to resolve and validate the incoming path using the same guarded
loader function used elsewhere (e.g., the resolve/load config helper used by the
/api/config/content endpoint) instead of directly constructing Path(path), and
when building agents_result check both backend.get("model") and
backend.get("backend_params", {}).get("model") (falling back appropriately)
while keeping the existing type guards on agent_cfg and backend and returning
JSONResponse(404) on unresolved/unauthorized paths.
- Around line 1769-1790: The handler is returning the expanded/resolved config
to the browser (resolved_yaml and config) which can expose secrets; change the
return so only the un-expanded/raw metadata is sent. Specifically, stop
including "resolved_yaml" and "config" in the response and ensure
"original_yaml" is produced from the raw/unprocessed config metadata (use the
raw_config_for_metadata produced by load_config_file if available) before
calling _apply_mode_overrides; keep calling _apply_mode_overrides(config,
mode_overrides) locally but do not return the mutated config or its YAML to the
client.
- Around line 4763-4797: The code falls back to the process-global
get_log_session_dir() when display.log_session_dir is not yet set, causing wrong
workspace exposure and caching that wrong value in log_session_dir; remove the
fallback call to get_log_session_dir() and only use
manager.get_display(session_id) / getattr(display, "log_session_dir", None) as
the source of current_log_dir, and only assign to the cached log_session_dir
when that value came from the display (i.e., don't cache if it would have come
from get_log_session_dir()); update the block around
current_log_dir/log_session_dir and the subsequent call into
_resolve_watch_session_workspaces(...) accordingly so the websocket shows no
workspace until the real display.log_session_dir is available.
- Around line 693-704: The registry.register_session call is persisting the
transient WebUI UUID (session_id) instead of the real log-session id used by
_save_session_metadata and _read_events_jsonl; change the code to persist the
log-backed session id (the "log_*" id) — e.g., obtain the log_session_id
returned or set by _save_session_metadata (or call _save_session_metadata first)
and pass that log_session_id into SessionRegistry.register_session (keep the
same config_path/description/status/source parameters) so history/replay paths
align with logs_root and _read_events_jsonl.
- Around line 5791-5799: The plan_mode handling currently only sets planning
flags when overrides["plan_mode"] is "spec" or "analyze" and never clears them
for "normal"; update the logic around
overrides.get("plan_mode")/orch.setdefault("coordination", {}) so that when
overrides["plan_mode"] == "normal" (or falsy) you explicitly reset/clear the
coordination flags (enable_agent_task_planning, task_planning_filesystem_mode,
spec_mode, analysis_mode) — either set them to False or remove the keys from
coord — while keeping the existing setting behavior for "spec" and "analyze";
look for the variables/keys overrides, orch, coord, and plan_mode in this block
to implement the reset.
- Around line 2351-2356: The sort key currently in _sort_key returns mixed types
(float from mark_session_completed's time.time() and ISO string from
replayed/reloaded sessions) causing TypeError; update _sort_key to normalize
timestamps to a single comparable type before returning (e.g., parse ISO strings
to epoch floats or format floats to ISO strings) and handle missing/invalid
values, then call sessions.sort(key=_sort_key, reverse=True) and slice as
before; reference _sort_key, mark_session_completed, and sessions.sort when
locating the change.
---
Outside diff comments:
In `@massgen/cli.py`:
- Around line 11739-11750: The current logic appends "/?v=2" blindly to
browser_url (built from auto_url or f"http://{args.web_host}:{args.web_port}")
which corrupts existing query params; update the code that builds browser_url to
parse the URL (e.g., using urllib.parse.urlparse / parse_qsl), merge or inject
the v=2 parameter and optionally setup=open or wizard=open based on
getattr(args, "setup") / getattr(args, "quickstart"), then rebuild the URL with
urlunparse so existing prompt/config params are preserved instead of creating
".../?v=2" after an existing query string.
- Around line 10065-10084: The finalize_step_mode() implementation currently
writes self._step_action_data["answer_text"] directly into final/answer.txt,
producing an unsanitized duplicate that can diverge from the scrubbed output
saved by save_step_mode_output(); modify finalize_step_mode (or the related
orchestration flow) to write the already-sanitized answer instead — either by
having save_step_mode_output return the sanitized text (and using that), by
reading the scrubbed artifact that save_step_mode_output produced, or by
invoking the same sanitizer/rewriter used there before writing final/answer.txt
— ensuring no raw self._step_action_data["answer_text"] is written to final/.
---
Nitpick comments:
In `@massgen/backend/codex.py`:
- Around line 2128-2160: The _stringify_mcp_result function currently treats
empty strings as falsy and falls through to JSON serialization; update the logic
in _stringify_mcp_result (inside the loop over content_list) to return the text
whenever isinstance(text, str) (i.e., allow empty string "" to be returned
directly) instead of requiring truthiness, so a {"type":"text","text":""} yields
""—also add a short comment explaining this decision or, if you prefer the
original behavior, add a clarifying comment and a test to assert the intended
output.
In `@massgen/filesystem_manager/_filesystem_manager.py`:
- Around line 2342-2345: Add the ".claude" entry to the existing
_WORKSPACE_METADATA_DIRS set and promote the per-call _snapshot_exclude_dirs to
a module-level constant (e.g. _SNAPSHOT_EXCLUDE_DIRS) so it isn’t rebuilt on
each call; then update FilesystemManager.save_snapshot()'s
has_meaningful_content() to reference the module-level _SNAPSHOT_EXCLUDE_DIRS
(and/or merge it with _WORKSPACE_METADATA_DIRS if appropriate) so Claude-created
.claude/ directories are consistently treated as metadata and excluded from
snapshot content checks.
In `@massgen/filesystem_manager/_path_rewriter.py`:
- Around line 182-200: The current rename pass can produce collisions when
multiple original names map to the same anonymous name; update the loop that
constructs renamed_files (iterating over target_files and using ordered) to
detect collisions before calling file_path.rename by checking if new_path
already exists on disk or is already a target in renamed_files.values(), and on
collision either generate a unique fallback name (e.g., append a numeric suffix)
or skip and log a clear warning via logger.debug/logger.warning; ensure modified
is only incremented on a successful rename and preserve existing exception
handling around file_path.rename.
- Around line 138-158: The docstring for scrub_agent_ids_in_snapshot is
ambiguous about the return count; update the Returns section to state explicitly
that the function returns the total number of operations (each rename and each
content modification counted separately), so a single file that is both renamed
and modified contributes 2 to the returned count; edit the Returns text in the
scrub_agent_ids_in_snapshot docstring to reflect this semantics and mention that
the count is the sum of renames and content-modifications rather than unique
files.
In `@massgen/frontend/displays/textual_terminal_display.py`:
- Around line 1226-1230: The one-line docstring for notify_prompt_improved is
missing a Google-style docstring; update the function (and the other affected
functions in the same diff ranges) to use a full Google-style docstring that
documents parameters and return values (e.g., an "Args:" section describing
improved_prompt: str and any behavior like early-return when self._app is falsy,
and a "Returns:" section if applicable, or state that it returns None). Locate
notify_prompt_improved and the other changed methods referenced (around lines
6454-6565 and 7924-7927) and replace their single-line docstrings with proper
Google-style docstrings including Args: and Returns: entries.
- Around line 6496-6527: Extract the repeated logic that builds a friendly
SubagentDisplayData copy into a single helper (e.g.,
_build_precollab_subagent_display or make_precollab_display) and call it from
both places (the auto-open path and the Ctrl+U fallback) instead of duplicating
the field-by-field construction; the helper should accept the subagent id (sid)
and the stored state (state or state.data) and use _PRECOLLAB_DISPLAY_NAMES,
SubagentDisplayData, and the same fields (task, status, progress_percent,
elapsed_seconds, timeout_seconds, workspace_path, workspace_file_count,
last_log_line, error, answer_preview, log_path, subagent_type) so both call
sites (_parallel_precollab_expected/_precollab_subagents handling and the
alternate block referenced around 8180-8215) simply call the helper and append
the returned SubagentDisplayData to subagents.
In `@massgen/frontend/displays/textual_widgets/subagent_screen.py`:
- Around line 127-133: The set_multi method currently swallows all exceptions
with a bare except/pass when updating the header title; instead catch Exception
as e and log the error via the existing tui_log helper so failures in
query_one("#header_title", Static).update(self._build_title()) are visible
during debugging. Update set_multi to replace the silent except with an explicit
exception handler that calls tui_log (e.g., tui_log.error or tui_log.exception)
including the exception and a brief context message referencing
set_multi/_build_title/header_title.
- Around line 1127-1135: Extract the duplicated evaluator persona parsing into a
private helper on the class (e.g. def _extract_persona_labels(self) -> dict[str,
str]) that iterates self._inner_agent_system_prompts, looks for "Evaluator
Persona:", pulls the first line after that, strips it, and returns a dict of
aid->label (only when label non-empty); then replace the inline parsing blocks
in the shown method and in _switch_subagent() with a single call to
self._extract_persona_labels() and pass the returned dict to
self._inner_tab_bar.set_agent_personas where needed.
- Around line 1487-1491: The second check is redundant because self._subagent is
included in self._all_subagents; remove the if block that checks
self._subagent.status in ("running", "pending") and rely solely on the any(...)
check over self._all_subagents (located near the code handling subagent status
in the subagent_screen class/method using self._all_subagents and
self._subagent).
- Around line 1648-1663: Replace the fragile manual reconstruction of
SubagentDisplayData with dataclasses.replace to preserve future fields: inside
_poll_updates where you check if not getattr(new_data, "subagent_type", None)
and getattr(sa, "subagent_type", None), call replace(new_data,
subagent_type=sa.subagent_type) instead of re-creating SubagentDisplayData with
explicit fields so any added fields on SubagentDisplayData are retained.
In `@massgen/frontend/displays/textual_widgets/tab_bar.py`:
- Around line 127-130: Replace the one-line docstring on update_improved_prompt
with a Google-style docstring: start with a short description, then an Args
section documenting improved_prompt: Optional[str] (what it represents), and a
Returns section specifying None; ensure the docstring follows the project's
Google-style formatting (triple-quoted, parameter types and descriptions). Apply
the same Google-style docstring pattern to the other newly added setter in this
file so both setters consistently use Google-style docstrings.
In `@massgen/frontend/displays/web_display.py`:
- Around line 124-151: The two new methods _register_event_listener and
_on_structured_event have short one-line docstrings; update both to full
Google-style docstrings including a brief description, an Args: section
documenting parameters (e.g., event: Any for _on_structured_event), a Returns:
section (None), and a Raises: section if they can raise exceptions (or note that
exceptions are swallowed). Ensure the docstring format matches other files
(Google style) so generated docs are consistent.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e5d1fb32-09ae-4d46-88cb-21b0698f88eb
⛔ Files ignored due to path filters (109)
massgen/frontend/web/static/assets/_baseUniq-DHPGDDgx.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/_baseUniq-DHPGDDgx.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/arc-CokCsZM6.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/arc-CokCsZM6.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/architectureDiagram-VXUJARFQ-CFWMw_rK.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/architectureDiagram-VXUJARFQ-CFWMw_rK.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/base-80a1f760-0bJi2RFl.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/base-80a1f760-0bJi2RFl.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/blockDiagram-VD42YOAC-Co5-MpGL.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/blockDiagram-VD42YOAC-Co5-MpGL.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/c4Diagram-YG6GDRKO-DYPuNmEF.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/c4Diagram-YG6GDRKO-DYPuNmEF.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/channel-D1dpymym.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/channel-D1dpymym.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/channel-DTOQwt0x.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-4BX2VUAB-CebFxQ-R.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-4BX2VUAB-CebFxQ-R.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-55IACEB6-DiNHxzzY.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-55IACEB6-DiNHxzzY.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-B4BG7PRW-CoPQlgSP.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-B4BG7PRW-CoPQlgSP.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-DI55MBZ5-BtSW5YBQ.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-DI55MBZ5-BtSW5YBQ.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-FMBD7UC4-wkPVgmHa.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-FMBD7UC4-wkPVgmHa.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-QN33PNHL-CZNl_8Ek.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-QN33PNHL-CZNl_8Ek.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-QZHKN3VN-BwbdsYhL.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-QZHKN3VN-BwbdsYhL.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-TZMSLE5B-CxyG-zuc.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-TZMSLE5B-CxyG-zuc.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/classDiagram-2ON5EDUG--rHFO9II.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/classDiagram-2ON5EDUG-CqUIDWJ9.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/classDiagram-2ON5EDUG-CqUIDWJ9.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/classDiagram-v2-WZHVMYZB--rHFO9II.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/classDiagram-v2-WZHVMYZB-CqUIDWJ9.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/classDiagram-v2-WZHVMYZB-CqUIDWJ9.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/clone-Cs1GzyJB.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/clone-r7v9nELZ.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/clone-r7v9nELZ.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/consoleHook-59e792cb-CJy5coaP.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/consoleHook-59e792cb-CJy5coaP.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/cose-bilkent-S5V4N54A-TTlzxN-U.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/cose-bilkent-S5V4N54A-TTlzxN-U.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/dagre-6UL2VRFP-BxPbgi2q.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/dagre-6UL2VRFP-BxPbgi2q.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/diagram-PSM6KHXK-d1E9v6HU.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/diagram-PSM6KHXK-d1E9v6HU.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/diagram-QEK2KX5R-BrdW4vHb.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/diagram-QEK2KX5R-BrdW4vHb.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/diagram-S2PKOQOG-Dl5n2kz6.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/diagram-S2PKOQOG-Dl5n2kz6.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/erDiagram-Q2GNP2WA-DoTyzorr.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/erDiagram-Q2GNP2WA-DoTyzorr.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/flowDiagram-NV44I4VS-BaelXQjr.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/flowDiagram-NV44I4VS-BaelXQjr.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/ganttDiagram-JELNMOA3-BfHDONdS.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/ganttDiagram-JELNMOA3-BfHDONdS.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/gitGraphDiagram-NY62KEGX--ygv52PS.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/gitGraphDiagram-NY62KEGX--ygv52PS.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/graph-BB7zubDf.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/graph-BB7zubDf.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/index-599aeaf7-Beoqm9RB.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/index-599aeaf7-Beoqm9RB.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/index-BXbvd5or.cssis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/index-C2qniOIu.cssis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/index-CGMkk2HX.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/index-CGMkk2HX.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/index-CoEp30O1.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/index-CoEp30O1.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/index-DBXMMTf0.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/index-DBXMMTf0.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/index-JoaRpYIu.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/infoDiagram-WHAUD3N6-C29jQaQb.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/infoDiagram-WHAUD3N6-C29jQaQb.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/journeyDiagram-XKPGCS4Q-Bm72xyLG.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/journeyDiagram-XKPGCS4Q-Bm72xyLG.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/kanban-definition-3W4ZIXB7-CTKr6jqq.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/kanban-definition-3W4ZIXB7-CTKr6jqq.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/layout-bA2TPHVZ.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/layout-bA2TPHVZ.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/linear-97fYS-uu.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/linear-97fYS-uu.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/min-De6IWHqk.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/min-De6IWHqk.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/mindmap-definition-VGOIOE7T-DJMLKmyE.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/mindmap-definition-VGOIOE7T-DJMLKmyE.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/pieDiagram-ADFJNKIX-C6vPU95a.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/pieDiagram-ADFJNKIX-C6vPU95a.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/quadrantDiagram-AYHSOK5B-BPAyAJBT.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/quadrantDiagram-AYHSOK5B-BPAyAJBT.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/requirementDiagram-UZGBJVZJ-CQUDmrBe.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/requirementDiagram-UZGBJVZJ-CQUDmrBe.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/sankeyDiagram-TZEHDZUN-Bypvbwc1.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/sankeyDiagram-TZEHDZUN-Bypvbwc1.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/sequenceDiagram-WL72ISMW-CLtEGs2b.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/sequenceDiagram-WL72ISMW-CLtEGs2b.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/stateDiagram-FKZM4ZOC-Cwn7jp1i.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/stateDiagram-FKZM4ZOC-Cwn7jp1i.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/stateDiagram-v2-4FDKWEC3-BTZICaqL.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/stateDiagram-v2-4FDKWEC3-BhsNILxt.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/stateDiagram-v2-4FDKWEC3-BhsNILxt.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/timeline-definition-IT6M3QCI-Cuuo442X.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/timeline-definition-IT6M3QCI-Cuuo442X.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/treemap-KMMF4GRG-CvlYEM91.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/treemap-KMMF4GRG-CvlYEM91.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/xychartDiagram-PRI3JC2R-g0uoLKrB.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/xychartDiagram-PRI3JC2R-g0uoLKrB.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapwebui/package-lock.jsonis excluded by!**/package-lock.json,!**/package-lock.json
📒 Files selected for processing (147)
AGENTS.mdCLAUDE.mddocs/modules/step_mode.mdmassgen/agent_config.pymassgen/backend/codex.pymassgen/cli.pymassgen/configs/features/round_evaluator_example.yamlmassgen/coordination_tracker.pymassgen/evaluation_criteria_generator.pymassgen/events.pymassgen/filesystem_manager/__init__.pymassgen/filesystem_manager/_filesystem_manager.pymassgen/filesystem_manager/_path_rewriter.pymassgen/frontend/displays/textual_terminal_display.pymassgen/frontend/displays/textual_widgets/subagent_screen.pymassgen/frontend/displays/textual_widgets/tab_bar.pymassgen/frontend/displays/web_display.pymassgen/frontend/web/server.pymassgen/frontend/web/static/index.htmlmassgen/mcp_tools/budget_guard.pymassgen/mcp_tools/checklist_tools_server.pymassgen/message_templates.pymassgen/orchestrator.pymassgen/persona_generator.pymassgen/precollab_utils.pymassgen/prompt_improver.pymassgen/step_mode.pymassgen/subagent/manager.pymassgen/subagent/models.pymassgen/subagent_types/regression_guard/SUBAGENT.mdmassgen/subagent_types/round_evaluator/SUBAGENT.mdmassgen/system_message_builder.pymassgen/system_prompt_sections.pymassgen/task_decomposer.pymassgen/tests/frontend/test_subagent_screen_input.pymassgen/tests/frontend/test_subagent_screen_wiring.pymassgen/tests/integration/test_orchestrator_hooks_broadcast_subagents.pymassgen/tests/test_answer_count_increment.pymassgen/tests/test_budget_guard.pymassgen/tests/test_claude_code_context_sharing.pymassgen/tests/test_codex_mcp_tool_visibility.pymassgen/tests/test_decomposition_mode.pymassgen/tests/test_evaluator_personas.pymassgen/tests/test_path_rewriter.pymassgen/tests/test_precollab_utils.pymassgen/tests/test_prompt_improver.pymassgen/tests/test_round_evaluator_loop.pymassgen/tests/test_specialized_subagents.pymassgen/tests/test_step_mode.pymassgen/tests/test_step_mode_live.pymassgen/tests/test_subagent_docker_logs.pymassgen/tests/test_unified_precollab.pymassgen/tests/test_web_mode_overrides.pymassgen/tests/test_web_quickstart_cli.pymassgen/tests/test_web_setup_status_api.pymassgen/tests/test_web_workspace_connection.pymassgen/tests/test_write_mode_scratch.pymassgen/tests/unit/test_coordination_tracker.pymassgen/tests/unit/test_orchestrator_unit.pywebui/index.htmlwebui/package.jsonwebui/src/App.tsxwebui/src/components/InlineArtifactPreview.tsxwebui/src/components/setup/ApiKeysSection.tsxwebui/src/components/setup/DockerSection.tsxwebui/src/components/setup/SkillsSection.tsxwebui/src/components/v2/channel/AgentChannel.tsxwebui/src/components/v2/channel/FinalAnswerSection.tsxwebui/src/components/v2/channel/ModeBar.test.tsxwebui/src/components/v2/channel/ModeBar.tsxwebui/src/components/v2/channel/StreamingIndicator.tsxwebui/src/components/v2/channel/TaskPlanPanel.test.tsxwebui/src/components/v2/channel/TaskPlanPanel.tsxwebui/src/components/v2/channel/messages/AnswerMessageView.test.tsxwebui/src/components/v2/channel/messages/AnswerMessageView.tsxwebui/src/components/v2/channel/messages/BroadcastMessageView.tsxwebui/src/components/v2/channel/messages/CompletionMessageView.tsxwebui/src/components/v2/channel/messages/ContentMessageView.tsxwebui/src/components/v2/channel/messages/MessageRenderer.tsxwebui/src/components/v2/channel/messages/RoundDividerView.tsxwebui/src/components/v2/channel/messages/StatusMessageView.tsxwebui/src/components/v2/channel/messages/SubagentMessageView.tsxwebui/src/components/v2/channel/messages/ToolBatchView.test.tsxwebui/src/components/v2/channel/messages/ToolBatchView.tsxwebui/src/components/v2/channel/messages/ToolCallMessageView.tsxwebui/src/components/v2/channel/messages/VoteMessageView.test.tsxwebui/src/components/v2/channel/messages/VoteMessageView.tsxwebui/src/components/v2/layout/AgentMentionAutocomplete.tsxwebui/src/components/v2/layout/AppShell.test.tsxwebui/src/components/v2/layout/AppShell.tsxwebui/src/components/v2/layout/ConfigViewerModal.tsxwebui/src/components/v2/layout/FinalAnswerOverlay.tsxwebui/src/components/v2/layout/GlobalInputBar.test.tsxwebui/src/components/v2/layout/GlobalInputBar.tsxwebui/src/components/v2/layout/LaunchIndicator.test.tsxwebui/src/components/v2/layout/LaunchIndicator.tsxwebui/src/components/v2/layout/ModeConfigBar.test.tsxwebui/src/components/v2/layout/ModeConfigBar.tsxwebui/src/components/v2/layout/V2QuickstartWizard.test.tsxwebui/src/components/v2/layout/V2QuickstartWizard.tsxwebui/src/components/v2/layout/V2SetupOverlay.test.tsxwebui/src/components/v2/layout/V2SetupOverlay.tsxwebui/src/components/v2/sidebar/ChannelSection.tsxwebui/src/components/v2/sidebar/QuickAccessSection.tsxwebui/src/components/v2/sidebar/SessionSection.tsxwebui/src/components/v2/sidebar/Sidebar.tsxwebui/src/components/v2/sidebar/SidebarFooter.tsxwebui/src/components/v2/sidebar/SidebarHeader.tsxwebui/src/components/v2/sidebar/ThreadSection.tsxwebui/src/components/v2/tiles/EmptyState.tsxwebui/src/components/v2/tiles/FileViewerTile.tsxwebui/src/components/v2/tiles/OrientationToggle.tsxwebui/src/components/v2/tiles/PromptBanner.tsxwebui/src/components/v2/tiles/SubagentTile.tsxwebui/src/components/v2/tiles/TileContainer.test.tsxwebui/src/components/v2/tiles/TileContainer.tsxwebui/src/components/v2/tiles/TileDragContext.tsxwebui/src/components/v2/tiles/TileDragHandle.tsxwebui/src/components/v2/tiles/TileWrapper.tsxwebui/src/components/v2/tiles/TimelineTile.tsxwebui/src/components/v2/tiles/V2TimelineView.tsxwebui/src/components/v2/tiles/VoteResultsTile.tsxwebui/src/components/v2/tiles/WorkspaceBrowserTile.test.tsxwebui/src/components/v2/tiles/WorkspaceBrowserTile.tsxwebui/src/hooks/useV2KeyboardShortcuts.tswebui/src/hooks/useWebSocket.test.tsxwebui/src/hooks/useWebSocket.tswebui/src/hooks/useWorkspaceConnection.test.tsxwebui/src/hooks/useWorkspaceConnection.tswebui/src/main.tsxwebui/src/pages/SetupPage.tsxwebui/src/stores/agentStore.tswebui/src/stores/setupStore.tswebui/src/stores/v2/messageStore.test.tswebui/src/stores/v2/messageStore.tswebui/src/stores/v2/modeStore.test.tswebui/src/stores/v2/modeStore.tswebui/src/stores/v2/tileStore.test.tswebui/src/stores/v2/tileStore.tswebui/src/stores/wizardStore.tswebui/src/styles/globals.csswebui/src/test/setup.tswebui/src/types/index.tswebui/src/utils/broadcastTargets.test.tswebui/src/utils/broadcastTargets.tswebui/tailwind.config.jswebui/vite.config.ts
✅ Files skipped from review due to trivial changes (3)
- AGENTS.md
- massgen/events.py
- CLAUDE.md
There was a problem hiding this comment.
Actionable comments posted: 7
♻️ Duplicate comments (7)
massgen/frontend/web/server.py (7)
2381-2435:⚠️ Potential issue | 🟠 MajorDelete flow should also close and remove websocket connections.
This handler removes session/task/orchestrator state but leaves
manager.active_connectionsandworkspace_manager.workspace_connectionsintact, so deleted sessions may still appear active and receive broadcasts.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/web/server.py` around lines 2381 - 2435, The delete_session handler currently removes session state but does not close or remove WebSocket entries; update the delete_session function to iterate and close any websockets for the session in manager.active_connections and workspace_manager.workspace_connections (call close on each WebSocket and await/handle exceptions), remove those entries from both containers, and ensure any related per-connection cleanup (cancelling tasks tied to those sockets) is done before returning; reference the delete_session handler, manager.active_connections, and workspace_manager.workspace_connections to locate where to add this cleanup.
1756-1807:⚠️ Potential issue | 🔴 CriticalDo not return resolved/expanded config content to the browser.
At Lines 1803-1807, returning
resolved_yamlandconfigcan expose secrets after config resolution/expansion. This endpoint should only return raw/unexpanded metadata-safe content.Suggested fix
- config, _ = load_config_file(str(resolved_path)) + config, raw_config_for_metadata = load_config_file(str(resolved_path)) original_yaml = yaml.dump( - copy.deepcopy(config), + copy.deepcopy(raw_config_for_metadata or config), default_flow_style=False, sort_keys=False, allow_unicode=True, ) _apply_mode_overrides(config, mode_overrides) - resolved_yaml = yaml.dump( - config, - default_flow_style=False, - sort_keys=False, - allow_unicode=True, - ) - return { "original_yaml": original_yaml, - "resolved_yaml": resolved_yaml, - "config": config, }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/web/server.py` around lines 1756 - 1807, The preview_config handler currently applies mode overrides (_apply_mode_overrides) and returns resolved_yaml and config which can expose secrets; change it to only return the raw/unexpanded metadata-safe content: stop applying _apply_mode_overrides in preview_config (or apply it only server-side without exposing results) and remove resolved_yaml and config from the response, returning only original_yaml (and any non-sensitive metadata fields). Update references to resolved_yaml and config in preview_config and ensure _apply_mode_overrides is not invoked prior to constructing the public response.
696-707:⚠️ Potential issue | 🟠 MajorPersist the log-backed session id instead of the transient WebUI UUID.
At Line 702,
register_session()still storessession_id=session_id(WebUI UUID), which can create duplicate/unreplayable session entries when log-backed IDs (log_*) are also registered later.Suggested fix
registry = SessionRegistry() + log_session_dir = self.session_log_dirs.get(session_id) + persisted_session_id = ( + log_session_dir.name if isinstance(log_session_dir, Path) else session_id + ) registry.register_session( - session_id=session_id, + session_id=persisted_session_id, config_path=config, description=question[:100] if question else None, status="completed", source="webui", )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/web/server.py` around lines 696 - 707, The call to SessionRegistry.register_session is persisting the transient WebUI UUID (session_id) which can conflict with later log-backed IDs; change the value passed to register_session in massgen/frontend/web/server.py to the persistent log-backed session id (e.g., use the variable that holds the "log_*" id from your logging/recorder flow instead of session_id) so registry.register_session(session_id=LOG_SESSION_ID, ...) stores the durable id; update the call site around registry.register_session and any surrounding code that constructs description/status/source to use that log-backed id variable (keep SessionRegistry and registry.register_session unchanged).
906-957:⚠️ Potential issue | 🟠 MajorHarden
/api/config/agentspath handling and model extraction.At Line 910 this route reads arbitrary filesystem paths without the guarded allowlist flow used elsewhere, and at Line 932 it only reads
backend.model, missing configs where model is inbackend_params.model.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/web/server.py` around lines 906 - 957, The get_config_agents handler currently reads arbitrary filesystem paths via Path(path) (config_path) without using the application's allowlist/whitelist logic and only checks backend["model"], missing models stored under backend_params; update get_config_agents to validate the incoming path against the same allowlist/safe-resolve flow used elsewhere in the app (reject or return 404 for disallowed paths) before opening the file, and change the model extraction logic in the agents loop to resolve model = backend.get("model") or backend.get("backend_params", {}) .get("model") (falling back to None) so both formats are supported; keep existing error handling and return shapes.
2369-2373:⚠️ Potential issue | 🟠 MajorNormalize timestamp types before sorting sessions.
At Line 2370,
_sort_key()can return bothfloat(time.time()) andstr(ISO timestamps), which can raiseTypeErrorduring sort when mixed entries exist.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/web/server.py` around lines 2369 - 2373, The _sort_key function can return mixed types (float and str) causing TypeError during sessions.sort; update _sort_key to normalize both s.get("start_time") and s.get("completed_at") to a single comparable type (e.g., convert ISO timestamp strings to epoch floats using datetime.fromisoformat()/timestamp(), handle None and parse errors with fallbacks like 0), and ensure sessions.sort(key=_sort_key, reverse=True) always receives the same type; locate and modify the _sort_key function and any callers that rely on its return value.
4780-4798:⚠️ Potential issue | 🟠 MajorAvoid process-global log-dir fallback in
watch_session.At Lines 4790-4794, falling back to
get_log_session_dir()can bind this websocket to another live session’s logs and cache the wrong directory for future requests.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/web/server.py` around lines 4780 - 4798, The code in watch_session uses a process-global fallback get_log_session_dir() and then caches it into the connection-scoped log_session_dir, which can bind this websocket to another active session's logs; remove or restrict that fallback: only use manager.get_display(session_id) (via manager.get_display and getattr(display, "log_session_dir")) to resolve current_log_dir for this session, and either drop the get_log_session_dir() branch entirely or, if you must call get_log_session_dir(), validate that the returned directory belongs to the requested session_id before using it and do NOT assign it back into the connection-scoped log_session_dir variable (so only session-specific directories resolved from manager.get_display are cached).
5830-5838:⚠️ Potential issue | 🟠 Major
plan_mode="normal"must explicitly clear planning flags.At Lines 5831-5838, this block only sets flags for
spec/analyzeand never resets them fornormal, so planning behavior can remain sticky across mode changes.Suggested fix
- if overrides.get("plan_mode") and overrides["plan_mode"] != "normal": - coord = orch.setdefault("coordination", {}) - coord["enable_agent_task_planning"] = True - coord["task_planning_filesystem_mode"] = True - if overrides["plan_mode"] == "spec": - coord["spec_mode"] = True - if overrides["plan_mode"] == "analyze": - coord["analysis_mode"] = True + if "plan_mode" in overrides: + coord = orch.setdefault("coordination", {}) + plan_mode = overrides["plan_mode"] + coord["enable_agent_task_planning"] = plan_mode != "normal" + coord["task_planning_filesystem_mode"] = plan_mode != "normal" + coord["spec_mode"] = plan_mode == "spec" + coord["analysis_mode"] = plan_mode == "analyze"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/web/server.py` around lines 5830 - 5838, The plan_mode handling currently only sets planning flags for non-"normal" modes and doesn't clear them when overrides["plan_mode"] == "normal", causing sticky behavior; update the block that uses orch.setdefault("coordination", {}) so that when overrides.get("plan_mode") == "normal" you explicitly clear or set to False the keys "enable_agent_task_planning", "task_planning_filesystem_mode", "spec_mode", and "analysis_mode" on the coord dict (or remove them) and only set spec_mode/analysis_mode to True for the respective modes, ensuring coord is created via orch.setdefault("coordination", {}) before modifying keys.
🧹 Nitpick comments (3)
massgen/cli.py (1)
3478-3595: Update this changed parser helper's docstring to Google style.This function now owns prompt-improver, evaluator-persona, and checkpoint parsing, but its docstring still doesn't document args/return shape in the repository's preferred format.
As per coding guidelines,
**/*.py: For new or changed functions, include Google-style docstrings.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/cli.py` around lines 3478 - 3595, The parser helper that builds and returns a CoordinationConfig (referencing CoordinationConfig, PersonaGeneratorConfig, EvaluationCriteriaGeneratorConfig, PromptImproverConfig, TaskDecomposerConfig, SubagentOrchestratorConfig) needs its docstring converted to Google style: update the function-level docstring to include Args (describe coord_cfg dict and any expected keys like persona_generator, prompt_improver, evaluation_criteria_generator, task_decomposer, subagent_orchestrator, checkpoint_*), Returns (the CoordinationConfig instance and its salient fields), and any Raises (e.g., invalid config formats); explicitly document new owned fields prompt_improver, enable_evaluator_personas/checkpoint_enabled/checkpoint_mode/checkpoint_guidance/checkpoint_gated_patterns and the shapes/defaults for those entries so callers know expected keys and return structure.massgen/config_validator.py (1)
469-471: Move checkpoint validation tovalidate_configfor consistency.Checkpoint is a top-level config key, similar to
orchestrator,ui, andmemory, which are all validated directly invalidate_config(lines 251-264). Placing checkpoint validation inside_validate_agentsbreaks this pattern.♻️ Suggested refactor
Move the checkpoint validation call to
validate_configmethod (after line 264, before the return):# Check for warnings (best practices, deprecations, etc.) self._check_warnings(config, result) + # Validate checkpoint (if present at top level) + if "checkpoint" in config: + self._validate_checkpoint_config(config["checkpoint"], result) + return resultAnd remove lines 469-471 from
_validate_agents.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/config_validator.py` around lines 469 - 471, Move the top-level "checkpoint" validation out of _validate_agents and into validate_config to keep consistency with other top-level keys; specifically, call self._validate_checkpoint_config(config["checkpoint"], result) from validate_config (after the existing orchestrator/ui/memory validations and before returning) and remove the checkpoint handling lines from _validate_agents so checkpoint is only validated in validate_config.massgen/frontend/web/server.py (1)
123-149: Use Google-style docstrings for newly added helper functions.Several new/changed helpers include docstrings but omit Google-style
Args/Returnssections required by repo rules.As per coding guidelines,
**/*.py: For new or changed functions, include Google-style docstrings.Also applies to: 152-223, 225-331, 430-559
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@massgen/frontend/web/server.py` around lines 123 - 149, Update the docstring for the helper function _find_latest_attempt to follow the repo's Google-style format: add an "Args" section describing the log_dir parameter (type Path and meaning) and a "Returns" section describing the return value (Path or None and what it represents). Apply the same Google-style docstring pattern to the other new/changed helpers referenced (the functions in the ranges noted) so each docstring contains explicit Args and Returns descriptions matching their parameter and return types.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@CHANGELOG.md`:
- Around line 23-35: The CHANGELOG.md release entry for version 0.1.67 is
missing required categories and file-path traceability; update the release block
in CHANGELOG.md by adding the headings "Changed", "Fixed", and
"Documentations/Configurations/Resources" (use "- None" under any empty
section), ensure each bullet under "Added" and the new categories includes
affected file paths and PR/issue references (e.g., include paths like
src/webui/... or docs/...), and keep the existing "Technical Details" section
intact while listing PR numbers and contributors as shown.
In `@docs/announcements/github-release-v0.1.67.md`:
- Around line 1-3: The H2/H3 hierarchy is incorrect: change the "### 🖥️
[Modernized WebUI](https://docs.massgen.ai/en/latest/user_guide/webui.html)"
heading to use `##` (i.e., convert the "Modernized WebUI" heading from H3 to H2)
so it follows the top-level H1 and satisfies MD001; ensure any following section
headings under "Modernized WebUI" remain one level deeper than this updated `##`
heading to keep the section hierarchy consistent.
In `@massgen/cli.py`:
- Around line 11758-11765: The browser_url concatenation in the block that
checks getattr(args, "setup", False) and getattr(args, "quickstart", False)
blindly appends "/?v=2..." which breaks URLs that already contain queries (e.g.,
?prompt= or &config=). Fix by detecting whether browser_url already contains a
'?' and then append parameters with '&v=2...' (or '?v=2...' when no existing
query), and avoid injecting an extra slash; update the three branches that set
browser_url to build the query string correctly while preserving existing
path/trailing-slash semantics.
- Around line 3966-3975: The main_agent detection logic is only applied in the
history flow, so Orchestrator instances created elsewhere (e.g.,
run_single_question and the textual/TUI runner) never get main_agent set; after
every Orchestrator(...) construction in this file call the same setup: grab
agents_config from the kwargs (or reuse raw_agents_for_checkpoint logic),
iterate its items looking for a dict with "main_agent" == True, extract its
"id", verify the id exists in the current agents dict, and call
orchestrator.set_main_agent(main_agent_id); use the same symbols shown
(agents_config / raw_agents_for_checkpoint, agents, Orchestrator,
set_main_agent) to locate where to insert this helper call.
In `@massgen/config_validator.py`:
- Around line 473-509: The _validate_checkpoint_config method currently skips
validation of the "enabled" and "guidance" keys; update
_validate_checkpoint_config (which accepts checkpoint_config: dict[str, Any] and
result: ValidationResult) to validate that if "enabled" is present it is a
boolean and if "guidance" is present it is a string, adding appropriate
result.add_error calls (use the same error pattern and property paths
"checkpoint.enabled" and "checkpoint.guidance") and return early only on
non-dict checkpoint_config as currently implemented.
In `@massgen/frontend/web/server.py`:
- Around line 205-206: Replace the four broad "except Exception: continue"
swallowers in the replay/log parsing paths with explicit logging of the
exception before continuing: catch the exception as "except Exception as e" and
call the module logger (e.g., logger.debug or logger.exception) including a
concise context message about which replay/log entry failed and pass exc_info or
the exception to capture stacktrace, then continue; update all four occurrences
so failures are logged (retain the continue behavior after logging).
In `@README_PYPI.md`:
- Around line 1246-1250: The release notes list for v0.1.67 contains entries
"Modernized WebUI", "RoundBudgetGuardHook", "Unified Pre-Collab", and
"Regression Guard" with PR references (`#1016`, `#1013`) that must be verified
against the v0.1.67 tag; check the git tag v0.1.67 and confirm each PR (PR `#1016`
and PR `#1013`) was merged into that release, then update README_PYPI.md entries
to only include items actually shipped in v0.1.67 or correct the PR
numbers/descriptions (edit the lines mentioning Modernized WebUI,
RoundBudgetGuardHook, Unified Pre-Collab, Regression Guard and the associated PR
links) so the release-to-PR mapping is exact.
---
Duplicate comments:
In `@massgen/frontend/web/server.py`:
- Around line 2381-2435: The delete_session handler currently removes session
state but does not close or remove WebSocket entries; update the delete_session
function to iterate and close any websockets for the session in
manager.active_connections and workspace_manager.workspace_connections (call
close on each WebSocket and await/handle exceptions), remove those entries from
both containers, and ensure any related per-connection cleanup (cancelling tasks
tied to those sockets) is done before returning; reference the delete_session
handler, manager.active_connections, and workspace_manager.workspace_connections
to locate where to add this cleanup.
- Around line 1756-1807: The preview_config handler currently applies mode
overrides (_apply_mode_overrides) and returns resolved_yaml and config which can
expose secrets; change it to only return the raw/unexpanded metadata-safe
content: stop applying _apply_mode_overrides in preview_config (or apply it only
server-side without exposing results) and remove resolved_yaml and config from
the response, returning only original_yaml (and any non-sensitive metadata
fields). Update references to resolved_yaml and config in preview_config and
ensure _apply_mode_overrides is not invoked prior to constructing the public
response.
- Around line 696-707: The call to SessionRegistry.register_session is
persisting the transient WebUI UUID (session_id) which can conflict with later
log-backed IDs; change the value passed to register_session in
massgen/frontend/web/server.py to the persistent log-backed session id (e.g.,
use the variable that holds the "log_*" id from your logging/recorder flow
instead of session_id) so registry.register_session(session_id=LOG_SESSION_ID,
...) stores the durable id; update the call site around
registry.register_session and any surrounding code that constructs
description/status/source to use that log-backed id variable (keep
SessionRegistry and registry.register_session unchanged).
- Around line 906-957: The get_config_agents handler currently reads arbitrary
filesystem paths via Path(path) (config_path) without using the application's
allowlist/whitelist logic and only checks backend["model"], missing models
stored under backend_params; update get_config_agents to validate the incoming
path against the same allowlist/safe-resolve flow used elsewhere in the app
(reject or return 404 for disallowed paths) before opening the file, and change
the model extraction logic in the agents loop to resolve model =
backend.get("model") or backend.get("backend_params", {}) .get("model") (falling
back to None) so both formats are supported; keep existing error handling and
return shapes.
- Around line 2369-2373: The _sort_key function can return mixed types (float
and str) causing TypeError during sessions.sort; update _sort_key to normalize
both s.get("start_time") and s.get("completed_at") to a single comparable type
(e.g., convert ISO timestamp strings to epoch floats using
datetime.fromisoformat()/timestamp(), handle None and parse errors with
fallbacks like 0), and ensure sessions.sort(key=_sort_key, reverse=True) always
receives the same type; locate and modify the _sort_key function and any callers
that rely on its return value.
- Around line 4780-4798: The code in watch_session uses a process-global
fallback get_log_session_dir() and then caches it into the connection-scoped
log_session_dir, which can bind this websocket to another active session's logs;
remove or restrict that fallback: only use manager.get_display(session_id) (via
manager.get_display and getattr(display, "log_session_dir")) to resolve
current_log_dir for this session, and either drop the get_log_session_dir()
branch entirely or, if you must call get_log_session_dir(), validate that the
returned directory belongs to the requested session_id before using it and do
NOT assign it back into the connection-scoped log_session_dir variable (so only
session-specific directories resolved from manager.get_display are cached).
- Around line 5830-5838: The plan_mode handling currently only sets planning
flags for non-"normal" modes and doesn't clear them when overrides["plan_mode"]
== "normal", causing sticky behavior; update the block that uses
orch.setdefault("coordination", {}) so that when overrides.get("plan_mode") ==
"normal" you explicitly clear or set to False the keys
"enable_agent_task_planning", "task_planning_filesystem_mode", "spec_mode", and
"analysis_mode" on the coord dict (or remove them) and only set
spec_mode/analysis_mode to True for the respective modes, ensuring coord is
created via orch.setdefault("coordination", {}) before modifying keys.
---
Nitpick comments:
In `@massgen/cli.py`:
- Around line 3478-3595: The parser helper that builds and returns a
CoordinationConfig (referencing CoordinationConfig, PersonaGeneratorConfig,
EvaluationCriteriaGeneratorConfig, PromptImproverConfig, TaskDecomposerConfig,
SubagentOrchestratorConfig) needs its docstring converted to Google style:
update the function-level docstring to include Args (describe coord_cfg dict and
any expected keys like persona_generator, prompt_improver,
evaluation_criteria_generator, task_decomposer, subagent_orchestrator,
checkpoint_*), Returns (the CoordinationConfig instance and its salient fields),
and any Raises (e.g., invalid config formats); explicitly document new owned
fields prompt_improver,
enable_evaluator_personas/checkpoint_enabled/checkpoint_mode/checkpoint_guidance/checkpoint_gated_patterns
and the shapes/defaults for those entries so callers know expected keys and
return structure.
In `@massgen/config_validator.py`:
- Around line 469-471: Move the top-level "checkpoint" validation out of
_validate_agents and into validate_config to keep consistency with other
top-level keys; specifically, call
self._validate_checkpoint_config(config["checkpoint"], result) from
validate_config (after the existing orchestrator/ui/memory validations and
before returning) and remove the checkpoint handling lines from _validate_agents
so checkpoint is only validated in validate_config.
In `@massgen/frontend/web/server.py`:
- Around line 123-149: Update the docstring for the helper function
_find_latest_attempt to follow the repo's Google-style format: add an "Args"
section describing the log_dir parameter (type Path and meaning) and a "Returns"
section describing the return value (Path or None and what it represents). Apply
the same Google-style docstring pattern to the other new/changed helpers
referenced (the functions in the ranges noted) so each docstring contains
explicit Args and Returns descriptions matching their parameter and return
types.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9d46bd85-b119-4c6d-bd96-746d9503a4db
⛔ Files ignored due to path filters (101)
massgen/frontend/web/static/assets/_baseUniq-ax-eQWFQ.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/_baseUniq-ax-eQWFQ.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/arc-oNlponkH.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/arc-oNlponkH.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/architectureDiagram-VXUJARFQ--A7VyuIt.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/architectureDiagram-VXUJARFQ--A7VyuIt.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/base-80a1f760-Eos10Ji7.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/base-80a1f760-Eos10Ji7.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/blockDiagram-VD42YOAC-BWkpsym9.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/blockDiagram-VD42YOAC-BWkpsym9.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/c4Diagram-YG6GDRKO-BtewRLbI.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/c4Diagram-YG6GDRKO-BtewRLbI.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/channel-Csb-i_q-.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/channel-Csb-i_q-.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-4BX2VUAB-DtzQJyc_.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-4BX2VUAB-DtzQJyc_.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-55IACEB6-BJC1ZIiO.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-55IACEB6-BJC1ZIiO.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-B4BG7PRW-wtDXT2Va.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-B4BG7PRW-wtDXT2Va.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-DI55MBZ5-DAWTJC2Y.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-DI55MBZ5-DAWTJC2Y.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-FMBD7UC4-BNENioD3.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-FMBD7UC4-BNENioD3.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-QN33PNHL-Cgi6g8LY.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-QN33PNHL-Cgi6g8LY.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-QZHKN3VN-CMKxhBN0.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-QZHKN3VN-CMKxhBN0.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/chunk-TZMSLE5B-DyATf70e.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/chunk-TZMSLE5B-DyATf70e.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/classDiagram-2ON5EDUG-C6Pl7ng-.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/classDiagram-2ON5EDUG-C6Pl7ng-.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/classDiagram-v2-WZHVMYZB-C6Pl7ng-.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/classDiagram-v2-WZHVMYZB-C6Pl7ng-.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/clone-CJJ3eBc0.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/clone-CJJ3eBc0.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/consoleHook-59e792cb-C_HazgOc.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/consoleHook-59e792cb-C_HazgOc.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/cose-bilkent-S5V4N54A-CAnnwnDF.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/cose-bilkent-S5V4N54A-CAnnwnDF.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/dagre-6UL2VRFP-iay_dBOx.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/dagre-6UL2VRFP-iay_dBOx.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/diagram-PSM6KHXK-t6S-e3K1.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/diagram-PSM6KHXK-t6S-e3K1.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/diagram-QEK2KX5R-CYRG7vUz.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/diagram-QEK2KX5R-CYRG7vUz.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/diagram-S2PKOQOG-CYfSKONo.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/diagram-S2PKOQOG-CYfSKONo.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/erDiagram-Q2GNP2WA-B3WmcFzW.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/erDiagram-Q2GNP2WA-B3WmcFzW.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/flowDiagram-NV44I4VS-QRXL62eI.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/flowDiagram-NV44I4VS-QRXL62eI.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/ganttDiagram-JELNMOA3-B1JLxgS5.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/ganttDiagram-JELNMOA3-B1JLxgS5.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/gitGraphDiagram-NY62KEGX-DuJzSADy.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/gitGraphDiagram-NY62KEGX-DuJzSADy.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/graph-DtMB5Lvu.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/graph-DtMB5Lvu.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/index-599aeaf7-Dk4Bs35a.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/index-599aeaf7-Dk4Bs35a.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/index-BM6NvD1F.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/index-BM6NvD1F.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/index-BbyFWA-j.cssis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/index-BtBJ9d7B.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/index-BtBJ9d7B.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/index-wkg1rac0.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/index-wkg1rac0.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/infoDiagram-WHAUD3N6-CzsE9m_O.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/infoDiagram-WHAUD3N6-CzsE9m_O.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/journeyDiagram-XKPGCS4Q-CoaeJ4qm.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/journeyDiagram-XKPGCS4Q-CoaeJ4qm.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/kanban-definition-3W4ZIXB7-BjBmaTsI.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/kanban-definition-3W4ZIXB7-BjBmaTsI.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/layout-Bzr9dczJ.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/layout-Bzr9dczJ.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/linear-C_mErMu4.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/linear-C_mErMu4.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/min-ClhnVqwb.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/min-ClhnVqwb.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/mindmap-definition-VGOIOE7T-D4fQItkj.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/mindmap-definition-VGOIOE7T-D4fQItkj.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/pieDiagram-ADFJNKIX-D10BN-st.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/pieDiagram-ADFJNKIX-D10BN-st.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/quadrantDiagram-AYHSOK5B-Ch8f8eoz.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/quadrantDiagram-AYHSOK5B-Ch8f8eoz.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/requirementDiagram-UZGBJVZJ-CLc0M0LB.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/requirementDiagram-UZGBJVZJ-CLc0M0LB.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/sankeyDiagram-TZEHDZUN-CYEF3I71.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/sankeyDiagram-TZEHDZUN-CYEF3I71.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/sequenceDiagram-WL72ISMW-AusnPUtB.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/sequenceDiagram-WL72ISMW-AusnPUtB.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/stateDiagram-FKZM4ZOC-8AChZsFT.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/stateDiagram-FKZM4ZOC-8AChZsFT.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/stateDiagram-v2-4FDKWEC3-DGP22zIt.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/stateDiagram-v2-4FDKWEC3-DGP22zIt.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/timeline-definition-IT6M3QCI-B9_YzWnq.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/timeline-definition-IT6M3QCI-B9_YzWnq.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/treemap-KMMF4GRG-CwdTRIi5.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/treemap-KMMF4GRG-CwdTRIi5.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.mapmassgen/frontend/web/static/assets/xychartDiagram-PRI3JC2R-7krJX7mF.jsis excluded by!massgen/frontend/web/static/assets/**massgen/frontend/web/static/assets/xychartDiagram-PRI3JC2R-7krJX7mF.js.mapis excluded by!**/*.map,!massgen/frontend/web/static/assets/**,!**/*.map
📒 Files selected for processing (51)
.gitignoreCHANGELOG.mdCONTRIBUTING.mdREADME.mdREADME_PYPI.mdROADMAP.mdROADMAP_v0.1.68.mddocs/announcements/archive/v0.1.66.mddocs/announcements/current-release.mddocs/announcements/feature-highlights.mddocs/announcements/github-release-v0.1.66.mddocs/announcements/github-release-v0.1.67.mddocs/source/index.rstmassgen/agent_config.pymassgen/api_params_handler/_api_params_handler_base.pymassgen/backend/base.pymassgen/cli.pymassgen/config_validator.pymassgen/configs/README.mdmassgen/coordination_tracker.pymassgen/filesystem_manager/_constants.pymassgen/frontend/web/server.pymassgen/frontend/web/static/index.htmlmassgen/mcp_tools/checkpoint/__init__.pymassgen/mcp_tools/checkpoint/_checkpoint_mcp_server.pymassgen/mcp_tools/hooks.pymassgen/orchestrator.pymassgen/system_prompt_sections.pymassgen/tests/integration/test_checkpoint_integration.pymassgen/tool/workflow_toolkits/__init__.pymassgen/tool/workflow_toolkits/base.pymassgen/tool/workflow_toolkits/checkpoint.pymassgen/tool/workflow_toolkits/new_answer.pywebui/src/components/v2/channel/AgentChannel.tsxwebui/src/components/v2/channel/StreamingIndicator.tsxwebui/src/components/v2/layout/AppShell.test.tsxwebui/src/components/v2/layout/AppShell.tsxwebui/src/components/v2/layout/GlobalInputBar.tsxwebui/src/components/v2/layout/ModeConfigBar.test.tsxwebui/src/components/v2/layout/ModeConfigBar.tsxwebui/src/components/v2/layout/V2QuickstartWizard.tsxwebui/src/components/v2/sidebar/SessionSection.tsxwebui/src/components/v2/tiles/PromptBanner.tsxwebui/src/components/v2/tiles/TileContainer.test.tsxwebui/src/components/v2/tiles/TileContainer.tsxwebui/src/stores/v2/messageStore.tswebui/src/stores/v2/modeStore.test.tswebui/src/stores/v2/modeStore.tswebui/src/stores/v2/tileStore.tswebui/src/styles/globals.csswebui/src/types/index.ts
💤 Files with no reviewable changes (1)
- docs/announcements/github-release-v0.1.66.md
✅ Files skipped from review due to trivial changes (13)
- .gitignore
- docs/announcements/feature-highlights.md
- massgen/api_params_handler/_api_params_handler_base.py
- massgen/filesystem_manager/_constants.py
- ROADMAP_v0.1.68.md
- docs/source/index.rst
- massgen/backend/base.py
- docs/announcements/archive/v0.1.66.md
- CONTRIBUTING.md
- docs/announcements/current-release.md
- README.md
- massgen/configs/README.md
- ROADMAP.md
🚧 Files skipped from review as they are similar to previous changes (2)
- massgen/coordination_tracker.py
- massgen/agent_config.py
PR Title Format
Your PR title must follow the format:
<type>: <brief description>Valid types:
fix:- Bug fixesfeat:- New featuresbreaking:- Breaking changesdocs:- Documentation updatesrefactor:- Code refactoringtest:- Test additions/modificationschore:- Maintenance tasksperf:- Performance improvementsstyle:- Code style changesci:- CI/CD configuration changesExamples:
fix: resolve memory leak in data processingfeat: add export to CSV functionalitybreaking: change API response formatdocs: update installation guideDescription
Brief description of the changes in this PR
Type of change
fix:) - Non-breaking change which fixes an issuefeat:) - Non-breaking change which adds functionalitybreaking:) - Fix or feature that would cause existing functionality to not work as expecteddocs:) - Documentation updatesrefactor:) - Code changes that neither fix a bug nor add a featuretest:) - Adding missing tests or correcting existing testschore:) - Maintenance tasks, dependency updates, etc.perf:) - Code changes that improve performancestyle:) - Changes that do not affect the meaning of the code (formatting, missing semi-colons, etc.)ci:) - Changes to CI/CD configuration files and scriptsChecklist
Pre-commit status
How to Test
Add test method for this PR.
Test CLI Command
Write down the test bash command. If there is pre-requests, please emphasize.
Expected Results
Description/screenshots of expected results.
Additional context
Add any other context about the PR here.
Summary by CodeRabbit
Chores
New Features
Filesystem
Documentation