Skip to content

Enhance commit message suggestion engine and improve repo health UX#66

Merged
Princelad merged 4 commits intoPre-Usable-Release-(stabilization-+-onboarding)from
Configuration-and-persistence
Apr 1, 2026
Merged

Enhance commit message suggestion engine and improve repo health UX#66
Princelad merged 4 commits intoPre-Usable-Release-(stabilization-+-onboarding)from
Configuration-and-persistence

Conversation

@Princelad
Copy link
Copy Markdown
Owner

No description provided.

Copilot AI review requested due to automatic review settings April 1, 2026 04:22
@Princelad Princelad merged commit afd8b3d into Pre-Usable-Release-(stabilization-+-onboarding) Apr 1, 2026
3 checks passed
@Princelad Princelad deleted the Configuration-and-persistence branch April 1, 2026 04:25
Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f06b3f28f1

ℹ️ About Codex in GitHub

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

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

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main.rs
Comment on lines +293 to +295
if let Err(err) = app.store.load_from_json(wd) {
startup_diagnostics.push(format!(".forge load diagnostic: {}", err));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Abort persistence after .forge load diagnostics

When app.store.load_from_json(wd) fails here, startup only records a diagnostic and continues, but later in the same App::new flow the auto-populate path still calls save_to_json, which rewrites .forge/modules.json, .forge/developers.json, and schema.json from in-memory defaults. In repos where .forge/schema.json is malformed or from a newer version, this turns a recoverable load error into silent data loss by overwriting existing persisted project data.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds stronger startup-time configuration/persistence diagnostics and improves UX around repository “health” by making schema/migration/keybinding issues visible and providing a default keymap profile users can copy to override bindings.

Changes:

  • Aggregate startup diagnostics for .forge migration/load, settings validation, and keybindings load.
  • Introduce .forge schema manifest + migration routine and persist schema version on save.
  • Generate a default keybindings profile file and document keymap override workflow.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/main.rs Collects and surfaces startup diagnostics; adds explicit settings JSON schema validation.
src/key_handler.rs Tightens keybindings TOML parsing, writes a default keymap profile, and adds tests.
src/data.rs Adds .forge schema manifest versioning/migration and tests migration behavior.
README.md Documents keymap overrides via .forge/keybindings.default.toml.forge/keybindings.toml.
PROGRESS.md Marks configuration/persistence tasks as completed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/key_handler.rs
Comment on lines +108 to +113
format!(
"Invalid keybindings schema in {}: {}\nHint: use [bindings] table with action = \"Key\" entries",
path.display(),
err
),
)
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The keybindings parse error message includes a newline (\nHint: ...). Since this message is later surfaced in the single-line status bar, the newline can break or truncate the UI rendering. Consider keeping the error string single-line (e.g., replace the newline with a | Hint: ... suffix) or emitting the hint separately.

Copilot uses AI. Check for mistakes.
Comment thread src/main.rs
Comment on lines +287 to +320
match data::Store::migrate_forge_schema(wd) {
Ok(Some(msg)) => startup_diagnostics.push(msg),
Ok(None) => {}
Err(err) => startup_diagnostics
.push(format!(".forge migration diagnostic: {}", err)),
}
if let Err(err) = app.store.load_from_json(wd) {
startup_diagnostics.push(format!(".forge load diagnostic: {}", err));
}
match app.load_settings_from(wd) {
Ok(Some(settings)) => {
app.settings = settings;
}
Ok(None) => {}
Err(err) => {
startup_diagnostics
.push(format!("settings schema diagnostic: {}", err));
}
}

if let Err(err) = key_handler::ensure_default_keybindings_profile(wd) {
startup_diagnostics
.push(format!("default keymap profile diagnostic: {}", err));
}

if let Err(err) = app.key_handler.load_keybindings_from(wd) {
let msg = error(&format!("Failed to load keybindings: {}", err));
startup_diagnostics.push(format!("keybindings schema diagnostic: {}", err));
}

if !startup_diagnostics.is_empty() {
let msg = error(&format!(
"Startup configuration diagnostics | {}",
startup_diagnostics.join(" | ")
));
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

startup_diagnostics mixes successful diagnostics (e.g., a schema migration message) with actual failures, but the combined message is always wrapped with error(...). This will present successful migrations as an error in the status bar. Consider using info(...)/success(...) for non-error diagnostics, or separating warnings/errors from informational startup notes.

Copilot uses AI. Check for mistakes.
Comment thread src/data.rs
use std::io::Read;

let dir = workdir.join(".forge");
let _ = Self::migrate_forge_schema(workdir)?;
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

Forge schema migration is invoked twice on startup: once explicitly in App::new and again inside Store::load_from_json (which currently discards the migration message). This duplicates work and makes it harder to reason about when/where migration messaging should be surfaced. Consider performing migration in only one place (e.g., have load_from_json return the migration message, or remove the internal call and keep the startup-level call).

Suggested change
let _ = Self::migrate_forge_schema(workdir)?;

Copilot uses AI. Check for mistakes.
Comment thread src/main.rs
Comment on lines +2716 to +2727
if !object
.get("notifications")
.is_some_and(serde_json::Value::is_boolean)
{
errors.push("notifications must be a boolean".to_string());
}

if !object
.get("autosync")
.is_some_and(serde_json::Value::is_boolean)
{
errors.push("autosync must be a boolean".to_string());
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

When notifications/autosync are missing from settings.json, the validation error currently says they "must be a boolean", which is misleading compared to the more specific "missing required field" used for theme. Consider distinguishing between "missing" vs "wrong type" for these fields to make diagnostics actionable.

Suggested change
if !object
.get("notifications")
.is_some_and(serde_json::Value::is_boolean)
{
errors.push("notifications must be a boolean".to_string());
}
if !object
.get("autosync")
.is_some_and(serde_json::Value::is_boolean)
{
errors.push("autosync must be a boolean".to_string());
match object.get("notifications") {
Some(value) if value.is_boolean() => {}
Some(_) => errors.push("notifications must be a boolean".to_string()),
None => errors.push("missing required field: notifications".to_string()),
}
match object.get("autosync") {
Some(value) if value.is_boolean() => {}
Some(_) => errors.push("autosync must be a boolean".to_string()),
None => errors.push("missing required field: autosync".to_string()),

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants