Skip to content

feat(config): multi-layer config overlay (project .jcode + env vars + MCP trust gate) - #173

Merged
cnjack merged 5 commits into
mainfrom
feat/multi-layer-config
Jul 25, 2026
Merged

feat(config): multi-layer config overlay (project .jcode + env vars + MCP trust gate)#173
cnjack merged 5 commits into
mainfrom
feat/multi-layer-config

Conversation

@cnjack

@cnjack cnjack commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary

Complete multi-layer configuration system for jcode, combining project-level config overlays, standalone MCP discovery, environment variable overrides, and Settings UI scope badges. Supersedes #172.

Config Precedence (lowest → highest)

Layer Location
1 ~/.jcode/config.json (global)
2 <git-root>/.jcode/config.json<cwd>/.jcode/config.json (walk-up)
3 ~/.jcode/mcp.json → walk-up .jcode/mcp.json<cwd>/mcp.json
4 (highest) Environment variables (JCODE_MODEL, JCODE_CONFIG, etc.)

Features

Project Config Overlay

  • Walk-up .jcode/config.json from git root → cwd (monorepo-friendly)
  • Walk-up AGENTS.md concatenated root-first
  • Standalone mcp.json / .mcp.json (Claude Desktop / Cursor compatible)
  • Security denylist: providers, telemetry, cloud, SSH/Docker, memory, developer, auto_approve, default_mode, browser, computer

MCP Trust Gate (from review)

  • New MCP servers from project config require JCODE_MCP_TRUST_PROJECT=1 (same pattern as project hooks)
  • Dangerous env vars (LD_PRELOAD, DYLD_INSERT_LIBRARIES, NODE_OPTIONS, etc.) blocked in project MCP Env overlay
  • Existing server command/url immutable; only tuning fields mergeable

Environment Variable Overrides

Variable Overrides
JCODE_MODEL Active model
JCODE_SMALL_MODEL Small/fast model
JCODE_MAX_ITERATIONS Iteration cap
JCODE_THEME / JCODE_LANGUAGE Theme / locale
JCODE_DEFAULT_MODE Session mode (validated)
JCODE_CONFIG Config file path

Settings UI Scope Badges

  • MCP tab: accent Project chip for project-scoped servers
  • Skills tab: Project / Agents chips for non-builtin skills
  • i18n: all 5 locales (en/zh-Hans/zh-Hant/ja/ko)

Security Fixes (from CodeRabbit review)

  1. ✅ New project MCP servers gated behind JCODE_MCP_TRUST_PROJECT=1
  2. ✅ Dangerous env vars blocked in MCP Env overlay
  3. ✅ Browser/Computer moved to denylist (capability toggles + preapproved permissions)
  4. ✅ Fenced code blocks have language identifiers

Testing

  • All 32 packages pass (go test ./...)
  • golangci-lint: 0 issues
  • Pre-push hook: passed

Summary by CodeRabbit

  • New Features

    • Added project-level configuration overlays, including repository and nested-directory settings.
    • Added support for discovering and merging project MCP server definitions from mcp.json.
    • Environment variables can override supported configuration settings.
    • Project and agent-provided skills, plus project MCP servers, now display scope indicators in Settings.
    • Instructions from multiple AGENTS.md files are combined across repository directories.
  • Documentation

    • Added configuration, precedence, security, and MCP setup guidance.

Add walk-up configuration discovery inspired by codex/opencode/pi:

1. Walk-up .jcode/config.json: from git root → cwd, each directory's
   .jcode/config.json is loaded and merged (closer to cwd = higher
   precedence). Security denylist blocks providers, telemetry, cloud,
   SSH/Docker aliases, memory, developer, and auto-approve fields.

2. Walk-up AGENTS.md: from git root → cwd, each directory's AGENTS.md
   is concatenated (root-first ordering). Monorepo roots can define
   shared instructions while sub-packages add their own.

3. Standalone mcp.json: supports mcp.json/.mcp.json in ~/.jcode/,
   walk-up .jcode/ dirs, and project root. Format is compatible with
   Claude Desktop / Cursor ({ "mcpServers": { ... } }).

MCP security: existing servers' command/url cannot be overridden by
project config; new servers are allowed freely. Disabled flag is
one-way (project can disable, cannot re-enable).

All three transports (TUI, web, ACP) apply the overlay via
config.ApplyProjectOverlay() after LoadConfig(). Git root resolution
uses a single subprocess call shared across config and MCP loaders.
macOS symlink resolution (/var → /private/var) handled correctly.
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Project-level configuration, standalone MCP files, environment overrides, and walk-up AGENTS.md files are now discovered and merged. Startup paths apply the resulting configuration, while MCP and skill provenance is exposed through web APIs and settings badges.

Changes

Project Configuration Overlays

Layer / File(s) Summary
Project config discovery and secure merging
internal/config/project.go, internal/config/env.go, internal/config/config.go, internal/config/*_test.go
Git-root traversal, walk-up configuration loading, environment precedence, security-restricted field merging, and MCP tuning rules are implemented and tested.
Standalone MCP discovery and merging
internal/config/mcp_file.go, internal/config/mcp_file_test.go, site/docs/overview/mcp.md
MCP files are discovered across global and project locations, merged by server name, and documented with precedence and security constraints.
Runtime startup and task integration
internal/command/acp.go, internal/command/interactive.go, internal/command/web.go
ACP, interactive, and web initialization applies project or environment overlays before session, tool, and task construction.
Instruction and provenance integration
internal/prompts/memory.go, internal/prompts/memory_test.go, internal/skills/skills.go, internal/web/mcp.go, internal/web/skills.go, web/src/lib/types.ts
AGENTS.md files are combined from repository root to working directory, and MCP servers and skills carry source metadata.
Documentation and settings presentation
site/docs/configuration.md, web/src/components/SettingsView.tsx, web/src/i18n/locales/*
Project configuration behavior is documented and project or agent scope badges are localized and rendered in settings.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Startup
  participant ApplyProjectOverlay
  participant ProjectConfig
  participant MCPFiles
  participant SettingsAPI
  Startup->>ApplyProjectOverlay: apply working-directory configuration
  ApplyProjectOverlay->>ProjectConfig: load and merge project config
  ApplyProjectOverlay->>MCPFiles: load and merge MCP files
  ProjectConfig-->>ApplyProjectOverlay: effective project settings
  MCPFiles-->>ApplyProjectOverlay: merged MCP servers
  ApplyProjectOverlay-->>Startup: updated runtime configuration
  SettingsAPI->>SettingsAPI: attach MCP and skill provenance
Loading

Possibly related PRs

  • cnjack/jcode#172: Implements overlapping project-overlay machinery and startup integration.
  • cnjack/jcode#112: Touches memory initialization paths that consume the resulting configuration.
  • cnjack/jcode#100: Overlaps the web task construction path modified for configuration overlays.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: multi-layer config overlays, env vars, and MCP trust gating.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/multi-layer-config

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

❤️ Share

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

Add Project-Level Configuration section to configuration.md covering:
- Walk-up .jcode/config.json discovery order
- Mergeable fields and merge behavior
- Security denylist (providers, telemetry, cloud, etc.)
- Walk-up AGENTS.md for monorepos
- Monorepo example

Add Project-Level MCP Servers section to mcp.md covering:
- Standalone mcp.json/.mcp.json discovery order
- Claude Desktop / Cursor compatible format
- Merge & security rules (command/url non-overridable)
- One-way disable semantics
@cnjack cnjack changed the title feat(config): multi-layer project config overlay (walk-up config + mcp.json + AGENTS.md) feat(config): multi-layer project config overlay Jul 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
internal/config/project.go (2)

316-320: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Doc comment omits headers from the merged tuning-field list.

The comment says only "args, env, timeout, disabled" are merged, but the function below also merges Headers (lines 329-336). Update the comment to keep it accurate, especially since Headers can carry auth tokens and is relevant to the security reasoning here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/config/project.go` around lines 316 - 320, Update the comment
immediately above mergeProjectFields to include headers in the list of merged
tuning fields, while preserving the existing explanation that Command and URL
cannot be overridden and that new servers receive their full project definition.

22-40: 🩺 Stability & Availability | 🔵 Trivial | 🏗️ Heavy lift

Missing context.Context propagation across new project/MCP discovery code. Neither internal/config/project.go nor internal/config/mcp_file.go thread a context.Context through their new exported discovery functions, even though they perform subprocess exec (git) and file I/O; the shared root cause is that this whole new code path was designed without a ctx parameter.

  • internal/config/project.go#L22-L40: add a context.Context first parameter to GitRoot (and thread it through LoadProjectConfig/loadProjectConfigWithRoot/ApplyProjectOverlay) so callers can bound/cancel the git subprocess instead of relying solely on the internal 2s timeout.
  • internal/config/mcp_file.go#L49-L111: add a context.Context first parameter to LoadMCPFiles/loadMCPFilesWithRoot and pass it through to the shared GitRoot call once it accepts ctx.

As per coding guidelines, "Use context.Context as the first parameter and propagate cancellation properly."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/config/project.go` around lines 22 - 40, The discovery APIs do not
propagate caller cancellation. In internal/config/project.go lines 22-40, add
context.Context as the first parameter to GitRoot and thread it through
LoadProjectConfig, loadProjectConfigWithRoot, and ApplyProjectOverlay,
preserving the existing timeout as appropriate; in internal/config/mcp_file.go
lines 49-111, add the same parameter to LoadMCPFiles and loadMCPFilesWithRoot
and pass it to GitRoot, then update affected callers to provide the context.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/command/web.go`:
- Around line 412-414: Update the Web task agent construction flow around the
project overlay and process-wide mcpToolsPtr so MCP tools are loaded and cached
per task/project from taskCfg.MCPServers rather than reused from the startup
configuration. Apply the same per-task loading to the bootstrap task, while
preserving distinct MCP configurations across projects and the existing
local-task overlay behavior.

In `@internal/config/project.go`:
- Around line 321-346: Update mergeMCPServer so project overlays cannot fully
replace Args or Env for pre-existing MCP servers, preserving the same
immutability boundary as Command and URL. Either deny these overrides entirely
or implement a narrowly scoped additive/keyed merge that blocks dangerous
environment variables and execution-related argument flags; retain existing
behavior for unrelated fields and ensure full Args/Env control remains available
only when creating genuinely new servers.

In `@site/docs/configuration.md`:
- Line 350: Update the fenced directory-tree code block in the configuration
documentation to include the text language identifier, changing the opening
fence to specify text while preserving the block contents.

---

Nitpick comments:
In `@internal/config/project.go`:
- Around line 316-320: Update the comment immediately above mergeProjectFields
to include headers in the list of merged tuning fields, while preserving the
existing explanation that Command and URL cannot be overridden and that new
servers receive their full project definition.
- Around line 22-40: The discovery APIs do not propagate caller cancellation. In
internal/config/project.go lines 22-40, add context.Context as the first
parameter to GitRoot and thread it through LoadProjectConfig,
loadProjectConfigWithRoot, and ApplyProjectOverlay, preserving the existing
timeout as appropriate; in internal/config/mcp_file.go lines 49-111, add the
same parameter to LoadMCPFiles and loadMCPFilesWithRoot and pass it to GitRoot,
then update affected callers to provide the context.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0009cadb-59a4-466b-b6dd-d28dcc7e9faf

📥 Commits

Reviewing files that changed from the base of the PR and between 6485bdc and d96fd4d.

📒 Files selected for processing (11)
  • internal/command/acp.go
  • internal/command/interactive.go
  • internal/command/web.go
  • internal/config/mcp_file.go
  • internal/config/mcp_file_test.go
  • internal/config/project.go
  • internal/config/project_test.go
  • internal/prompts/memory.go
  • internal/prompts/memory_test.go
  • site/docs/configuration.md
  • site/docs/overview/mcp.md

Comment thread internal/command/web.go
Comment on lines +412 to +414
if exec == nil { // project config overlay (local tasks only)
config.ApplyProjectOverlay(taskCfg, taskPwd)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Project MCP files never reach Web task agents.

At Line 413, the overlay populates taskCfg.MCPServers, but agent construction reads only the process-wide mcpToolsPtr, which is initialized from the unoverlaid startup config. A project that defines only mcp.json gets no MCP tools in Web, and tasks from different projects cannot retain distinct MCP configurations. Load/cache MCP tools per task/project from taskCfg.MCPServers, including the bootstrap task.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/command/web.go` around lines 412 - 414, Update the Web task agent
construction flow around the project overlay and process-wide mcpToolsPtr so MCP
tools are loaded and cached per task/project from taskCfg.MCPServers rather than
reused from the startup configuration. Apply the same per-task loading to the
bootstrap task, while preserving distinct MCP configurations across projects and
the existing local-task overlay behavior.

Comment on lines +321 to +346
func mergeMCPServer(base, overlay *MCPServer) {
// Command and URL are intentionally NOT merged for existing servers.
if len(overlay.Args) > 0 {
base.Args = overlay.Args
}
if len(overlay.Env) > 0 {
base.Env = overlay.Env
}
if len(overlay.Headers) > 0 {
if base.Headers == nil {
base.Headers = make(map[string]string, len(overlay.Headers))
}
for k, v := range overlay.Headers {
base.Headers[k] = v
}
}
if overlay.TimeoutSeconds > 0 {
base.TimeoutSeconds = overlay.TimeoutSeconds
}
// Disabled can be set to true by project config (to suppress a global
// server in this project) but not back to false (project cannot
// re-enable a server the user globally disabled).
if overlay.Disabled {
base.Disabled = true
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

Full Args/Env replacement on existing servers undermines the Command/URL immutability guarantee.

mergeMCPServer blocks overriding Command/URL for existing servers specifically to stop a malicious project repo from redirecting a trusted server to a different binary/endpoint. But Args and Env are fully replaced (not restricted) for those same "existing" servers:

if len(overlay.Args) > 0 {
    base.Args = overlay.Args
}
if len(overlay.Env) > 0 {
    base.Env = overlay.Env
}

For a stdio-based trusted server, an attacker-controlled .jcode/config.json/mcp.json in the repo can replace Env wholesale to inject well-known code-execution vectors (LD_PRELOAD, DYLD_INSERT_LIBRARIES, NODE_OPTIONS, PYTHONPATH, PERL5LIB, GIT_SSH_COMMAND, etc.) against the fixed, trusted Command — achieving arbitrary code execution despite the binary path itself being immutable. Likewise, Args replacement can inject flags many interpreters honor for code execution (e.g. -r, -e, -c, --require) without ever changing Command. This effectively defeats the security boundary the comment at line 317 claims to provide.

Consider treating Env/Args the same way as Command/URL for pre-existing servers (deny override entirely, or only allow additive/keyed merges with a denylist of known dangerous variable/flag names), reserving full control only for genuinely new servers the project introduces.

🔒 Illustrative direction (denylist / no full override for existing servers)
 func mergeMCPServer(base, overlay *MCPServer) {
 	// Command and URL are intentionally NOT merged for existing servers.
-	if len(overlay.Args) > 0 {
-		base.Args = overlay.Args
-	}
-	if len(overlay.Env) > 0 {
-		base.Env = overlay.Env
-	}
+	// Args/Env are also security-sensitive for existing (trusted) servers:
+	// unrestricted overrides can achieve code execution via well-known
+	// interpreter env vars/flags (LD_PRELOAD, NODE_OPTIONS, -r/-e, ...)
+	// even though Command itself stays fixed. Do not allow full override
+	// here; either skip entirely or apply a strict denylist/keyed merge.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/config/project.go` around lines 321 - 346, Update mergeMCPServer so
project overlays cannot fully replace Args or Env for pre-existing MCP servers,
preserving the same immutability boundary as Command and URL. Either deny these
overrides entirely or implement a narrowly scoped additive/keyed merge that
blocks dangerous environment variables and execution-related argument flags;
retain existing behavior for unrelated fields and ensure full Args/Env control
remains available only when creating genuinely new servers.

Comment thread site/docs/configuration.md Outdated
Add provenance tracking to MCP servers and skills so the Settings UI
can display which config layer defines each entry:

Backend:
- MCPServer.Source field (json:"-", not persisted) tagged at load time
- Skill.Source field set during scan (builtin/agents/user/project)
- /api/mcp/list returns scope per server
- /api/skills returns granular source per skill

Frontend:
- MCP tab shows accent 'Project' chip for project-scoped servers
- Skills tab shows 'Project' / 'Agents' chips for non-builtin skills
- i18n keys added for all 5 locales (en/zh-Hans/zh-Hant/ja/ko)
@cnjack cnjack changed the title feat(config): multi-layer project config overlay feat(config): multi-layer project config overlay + Settings UI scope badges Jul 25, 2026
…CODE_CONFIG, etc.)

Add the highest-precedence config layer: environment variables override both
global (~/.jcode/config.json) and project-level (.jcode/config.json) settings.

Supported variables:
- JCODE_MODEL: active model (provider/model format)
- JCODE_SMALL_MODEL: small/fast model
- JCODE_MAX_ITERATIONS: agent iteration cap
- JCODE_THEME: color theme name
- JCODE_LANGUAGE: UI locale
- JCODE_DEFAULT_MODE: session mode (approval|plan|auto|full_access)
- JCODE_CONFIG: custom config file path

Key design decisions:
- Env vars MAY override DefaultMode (unlike project config denylist) because
  they are set by the user/CI directly, not an untrusted repository.
- Invalid values are logged and ignored (fail-safe).
- JCODE_CONFIG redirects both reads and writes (SaveConfig).
- Remote tasks (SSH/Docker) get env overlay even though project config is
  skipped (env vars are local process state).
- Web mode server-level config gets env overlay for provider resolution and
  startup mode.

Includes comprehensive tests and site documentation update.
@cnjack cnjack changed the title feat(config): multi-layer project config overlay + Settings UI scope badges feat(config): add environment variable override layer (JCODE_MODEL, JCODE_CONFIG, etc.) Jul 25, 2026
- Gate new project MCP servers behind JCODE_MCP_TRUST_PROJECT=1 (same
  pattern as project hooks). A hostile repo shipping a .jcode/config.json
  with a new stdio server can no longer achieve arbitrary code execution.
- Block dangerous env vars (LD_PRELOAD, DYLD_INSERT_LIBRARIES, NODE_OPTIONS,
  PYTHONPATH, etc.) in project MCP Env overlay to prevent code-execution
  vectors against immutable Command binaries.
- Move Browser/Computer to the project config denylist — these are
  capability toggles with preapproved permission lists, same escalation
  class as AutoApprove/DefaultMode.
- Fix markdownlint MD040: add language identifier to fenced code blocks.
- Update tests to cover trust-gated MCP server behavior.
@cnjack cnjack changed the title feat(config): add environment variable override layer (JCODE_MODEL, JCODE_CONFIG, etc.) feat(config): multi-layer config overlay (project .jcode + env vars + MCP trust gate) Jul 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/config/env.go`:
- Around line 39-57: Validate JCODE_MODEL, JCODE_SMALL_MODEL, JCODE_THEME, and
JCODE_LANGUAGE against their existing configuration domains before assigning
them in the environment override logic; log each rejected non-empty value via
Logger() and preserve the prior configuration. In internal/config/env_test.go
lines 44-143, add invalid-value cases for all four variables and assert that
each existing value remains unchanged.

In `@internal/web/skills.go`:
- Around line 27-33: Update the API field contract associated with the skill
source value in the skills response to document all emitted provenance values:
builtin, user, agents, and project. Keep the source-selection logic unchanged,
and prefer the existing shared type if one is already used for this field.

In `@web/src/i18n/locales/ja.ts`:
- Around line 538-541: Translate the agents scope label in
web/src/i18n/locales/ja.ts lines 538-541 to Japanese agent terminology such as
エージェント, and apply the corresponding Korean translation such as 에이전트 in
web/src/i18n/locales/ko.ts lines 538-541; update the agents entries in the scope
objects while leaving project unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3f1ffd5e-5f4b-4033-a2ae-6a461d526f8b

📥 Commits

Reviewing files that changed from the base of the PR and between d96fd4d and 13f4f84.

📒 Files selected for processing (18)
  • internal/command/web.go
  • internal/config/config.go
  • internal/config/env.go
  • internal/config/env_test.go
  • internal/config/mcp_file.go
  • internal/config/project.go
  • internal/config/project_test.go
  • internal/skills/skills.go
  • internal/web/mcp.go
  • internal/web/skills.go
  • site/docs/configuration.md
  • web/src/components/SettingsView.tsx
  • web/src/i18n/locales/en.ts
  • web/src/i18n/locales/ja.ts
  • web/src/i18n/locales/ko.ts
  • web/src/i18n/locales/zh-Hans.ts
  • web/src/i18n/locales/zh-Hant.ts
  • web/src/lib/types.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • internal/command/web.go
  • internal/config/mcp_file.go
  • internal/config/project.go
  • site/docs/configuration.md
  • internal/config/project_test.go

Comment thread internal/config/env.go
Comment on lines +39 to +57
if v := os.Getenv(EnvModel); v != "" {
cfg.Model = v
}
if v := os.Getenv(EnvSmallModel); v != "" {
cfg.SmallModel = v
}
if v := os.Getenv(EnvMaxIterations); v != "" {
if n, err := strconv.Atoi(v); err == nil && n > 0 {
cfg.MaxIterations = n
} else {
Logger().Printf("[config] ignoring invalid %s=%q (must be a positive integer)", EnvMaxIterations, v)
}
}
if v := os.Getenv(EnvTheme); v != "" {
cfg.Theme = v
}
if v := os.Getenv(EnvLanguage); v != "" {
cfg.Language = v
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Validate all environment overrides before applying them.

JCODE_MODEL, JCODE_SMALL_MODEL, JCODE_THEME, and JCODE_LANGUAGE currently replace valid configuration with any non-empty string. This violates the PR requirement that invalid environment values be logged and ignored; malformed high-precedence values can leave startup with an unusable model or invalid UI settings.

  • internal/config/env.go#L39-L57: validate each value against its existing config domain before assignment, and log rejected values through Logger().
  • internal/config/env_test.go#L44-L143: add invalid-value cases for model, small model, theme, and language, asserting the prior config remains unchanged.
📍 Affects 2 files
  • internal/config/env.go#L39-L57 (this comment)
  • internal/config/env_test.go#L44-L143
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/config/env.go` around lines 39 - 57, Validate JCODE_MODEL,
JCODE_SMALL_MODEL, JCODE_THEME, and JCODE_LANGUAGE against their existing
configuration domains before assigning them in the environment override logic;
log each rejected non-empty value via Logger() and preserve the prior
configuration. In internal/config/env_test.go lines 44-143, add invalid-value
cases for all four variables and assert that each existing value remains
unchanged.

Comment thread internal/web/skills.go
Comment on lines +27 to +33
source := sk.Source
if source == "" {
if sk.Builtin {
source = "builtin"
} else {
source = "user"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Keep the skill-source contract in sync with emitted values.

This logic can return builtin, user, agents, or project, while the API field is still documented as builtin | local. Update the contract comment (or use a shared type) so clients do not reject the new provenance values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/web/skills.go` around lines 27 - 33, Update the API field contract
associated with the skill source value in the skills response to document all
emitted provenance values: builtin, user, agents, and project. Keep the
source-selection logic unchanged, and prefer the existing shared type if one is
already used for this field.

Comment on lines +538 to +541
scope: {
project: 'プロジェクト',
agents: 'Agents',
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Translate the new agents scope label in every locale.

The new agents badge remains English in both locales:

  • web/src/i18n/locales/ja.ts#L538-L541: use Japanese agent terminology such as エージェント.
  • web/src/i18n/locales/ko.ts#L538-L541: use Korean agent terminology such as 에이전트.
📍 Affects 2 files
  • web/src/i18n/locales/ja.ts#L538-L541 (this comment)
  • web/src/i18n/locales/ko.ts#L538-L541
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/i18n/locales/ja.ts` around lines 538 - 541, Translate the agents
scope label in web/src/i18n/locales/ja.ts lines 538-541 to Japanese agent
terminology such as エージェント, and apply the corresponding Korean translation such
as 에이전트 in web/src/i18n/locales/ko.ts lines 538-541; update the agents entries
in the scope objects while leaving project unchanged.

@cnjack
cnjack merged commit dfa0b37 into main Jul 25, 2026
4 checks passed
@cnjack
cnjack deleted the feat/multi-layer-config branch July 25, 2026 12:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant