diff --git a/CHANGELOG.md b/CHANGELOG.md index 27afa409..a7e2f1a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Pending-input preview rows now label delivery mode explicitly as steer pending, rejected steer, or queued follow-up, with wrapped continuation rows aligned under the label so busy-turn input state is easier to read (#2054). +- Auto-generated project instructions now reuse the bounded Project Context + Pack data instead of running an unbounded summary/tree scan when no + `.codewhale/instructions.md` file exists. The fallback keeps later + top-level folders visible in noisy large workspaces while the dynamic + `` marker remains controlled by its own setting + (#697, #1827). ### Community @@ -86,7 +92,10 @@ HarmonyOS/OpenHarmony port and MatePad Edge validation trail (#2634), **@idling11** for the PlanArtifact direction in Plan mode (#2733) and the dense tool-call transcript collapse direction (#2738, #2692), and **@h3c-hexin** for the tool-agent model inheritance and configured -`skills_dir` fixes (#2736, #2737). +`skills_dir` fixes (#2736, #2737). Thanks also to **@NASLXTO** and +**@wuxixing** for the large-workspace startup reports (#697, #1827), and to +**@linzhiqin2003** and **@merchloubna70-dot** for earlier context-cap and +startup-diagnosis work that shaped this bounded fallback. ## [0.8.53] - 2026-06-03 diff --git a/crates/tui/src/project_context.rs b/crates/tui/src/project_context.rs index affd746f..c4b80624 100644 --- a/crates/tui/src/project_context.rs +++ b/crates/tui/src/project_context.rs @@ -359,6 +359,22 @@ struct ReadmePack { /// sorted entries, bounded README text, and sorted JSON object fields. It does /// not include timestamps, random ids, absolute temp paths, or live git state. pub fn generate_project_context_pack(workspace: &Path) -> Option { + let pack = build_project_context_pack(workspace)?; + let json = serde_json::to_string_pretty(&pack).ok()?; + Some(format!( + "## Project Context Pack\n\n\n{json}\n" + )) +} + +fn generate_bounded_project_overview(workspace: &Path) -> Option { + let pack = build_project_context_pack(workspace)?; + let json = serde_json::to_string_pretty(&pack).ok()?; + Some(format!( + "## Bounded Project Overview\n\n```json\n{json}\n```" + )) +} + +fn build_project_context_pack(workspace: &Path) -> Option { let mut entries = Vec::new(); collect_pack_entries(workspace, workspace, 0, &mut entries); sort_pack_paths(&mut entries); @@ -386,7 +402,7 @@ pub fn generate_project_context_pack(workspace: &Path) -> Option { counts.insert("directory_entries".to_string(), entries.len()); counts.insert("key_source_files".to_string(), key_source_files.len()); - let pack = ProjectContextPack { + Some(ProjectContextPack { project_name: workspace .file_name() .and_then(|name| name.to_str()) @@ -397,12 +413,7 @@ pub fn generate_project_context_pack(workspace: &Path) -> Option { config_files, key_source_files, counts, - }; - - let json = serde_json::to_string_pretty(&pack).ok()?; - Some(format!( - "## Project Context Pack\n\n\n{json}\n" - )) + }) } fn collect_pack_entries(root: &Path, dir: &Path, depth: usize, out: &mut Vec) { @@ -704,7 +715,7 @@ fn load_project_context_with_parents_and_home( } } - // Auto-generate .deepseek/instructions.md when no context file exists anywhere. + // Auto-generate .codewhale/instructions.md when no context file exists anywhere. // This avoids the per-turn filesystem scan fallback in prompts.rs that // breaks KV prefix cache stability. if !ctx.has_instructions() @@ -823,15 +834,13 @@ fn auto_generate_context(workspace: &Path) -> Option { return None; } - let summary = crate::utils::summarize_project(workspace); - let tree = crate::utils::project_tree(workspace, 2); + let overview = generate_bounded_project_overview(workspace)?; let content = format!( - "# Project Structure (Auto-generated)\n\n\ + "# Project Context (Auto-generated)\n\n\ > This file was automatically generated by CodeWhale.\n\ > You can edit or delete it at any time.\n\n\ - **Summary:** {summary}\n\n\ - **Tree:**\n```\n{tree}\n```" + {overview}" ); // Create .codewhale/ directory @@ -1379,6 +1388,52 @@ mod tests { ); } + #[test] + fn auto_generated_context_is_bounded_for_many_file_workspace() { + let workspace = tempdir().expect("workspace tempdir"); + let home = tempdir().expect("home tempdir"); + let noisy = workspace.path().join("aaa-many-files"); + fs::create_dir_all(&noisy).expect("mkdir noisy"); + for i in 0..1000 { + fs::write(noisy.join(format!("file-{i:04}.rs")), "fn noisy() {}").expect("write noisy"); + } + fs::create_dir_all(workspace.path().join("zzz-important")).expect("mkdir important"); + fs::write( + workspace.path().join("zzz-important").join("main.rs"), + "fn important() {}", + ) + .expect("write important"); + + let start = std::time::Instant::now(); + let ctx = load_project_context_with_parents_and_home(workspace.path(), Some(home.path())); + let elapsed = start.elapsed(); + assert!( + elapsed < std::time::Duration::from_secs(2), + "auto-generated context should stay bounded, took {elapsed:?}" + ); + assert!(ctx.has_instructions()); + + let generated_path = workspace.path().join(".codewhale").join("instructions.md"); + assert_eq!(ctx.source_path.as_deref(), Some(generated_path.as_path())); + let generated = fs::read_to_string(&generated_path).expect("read generated"); + assert!(generated.contains("Project Context (Auto-generated)")); + assert!(generated.contains("Bounded Project Overview")); + assert!(!generated.contains("")); + assert!( + generated.contains("\"zzz-important/\""), + "later top-level project areas should remain visible:\n{generated}" + ); + let noisy_count = generated.matches("aaa-many-files/file-").count(); + assert!( + noisy_count < 300, + "generated context should not list the whole noisy directory; saw {noisy_count}" + ); + assert!( + !generated.contains("file-0999.rs"), + "bounded context should omit the tail of the noisy directory" + ); + } + #[test] fn project_context_pack_sort_is_cross_platform_and_priority_aware() { let mut unix_paths = vec![ @@ -1657,7 +1712,7 @@ mod tests { ctx.instructions .as_ref() .unwrap() - .contains("Project Structure (Auto-generated)") + .contains("Project Context (Auto-generated)") ); } } diff --git a/docs/V0_9_0_EXECUTION_MAP.md b/docs/V0_9_0_EXECUTION_MAP.md index 6a90463c..f9aeed2b 100644 --- a/docs/V0_9_0_EXECUTION_MAP.md +++ b/docs/V0_9_0_EXECUTION_MAP.md @@ -9,9 +9,9 @@ PR is harvested, superseded, deferred, or closed. ## Live Counts - Actual open issues: 446 -- Open PRs: 56 -- Repo API open issue count: 502, because GitHub includes PRs in that total -- Open issues labeled `v0.9.0`: 133 +- Open PRs: 57 +- Repo API open issue count: 503, because GitHub includes PRs in that total +- Open issues labeled `v0.9.0`: 119 - Open issues without a milestone: 102 ## Execution Order @@ -51,6 +51,7 @@ harvest/stewardship commits: | #2737 configured `skills_dir` discovery | Locally harvested with explicit-config precedence. | The system prompt now unions workspace-discovered skills and configured `skills_dir` skills instead of treating the configured directory as a fallback. Explicit configured skills are inserted before global defaults so they are not lost behind a large global skill library. Credit @h3c-hexin; comment/close the original after the integration branch is public. | | #2738 dense tool-call transcript collapse | Locally harvested with expansion, cache-key, and safety fixes. | Successful read/search/list-style tool runs collapse by default once they cross the density threshold; failures, running cells, shell/exec, patch/write/edit/delete, diff preview, plan update, and review cells stay visible. Users can expand a group with Enter/Space/mouse and can set `tool_collapse = "compact" | "expanded" | "calm"`. Credit @idling11 and issue #2692; comment/close the original after the integration branch is public. | | #2532 pending-input delivery-mode labels | Locally re-harvested for #2054. | Pending-input preview rows now label steer-pending, rejected-steer, and queued-follow-up delivery modes, and wrapped continuation rows align under the label. `cargo test -p codewhale-tui --bin codewhale-tui --locked pending_input_preview -- --nocapture` passed. Credit @cyq1017; #2054 remains open for cancel/edit-mode affordance clarity. | +| #697/#1827 bounded auto-generated project context | Locally implemented from the stabilization audit. | When no project instructions exist, startup now writes `.codewhale/instructions.md` from the bounded Project Context Pack data instead of an unbounded summary/tree scan. The generated file avoids the dynamic `` marker when that setting is disabled, keeps later top-level folders visible, and omits noisy directory tails. `cargo test -p codewhale-tui --bin codewhale-tui --locked auto_generated_context_is_bounded_for_many_file_workspace -- --nocapture` and `cargo test -p codewhale-tui --bin codewhale-tui --locked project_context_pack -- --nocapture` passed. Credit reporters @NASLXTO and @wuxixing, plus earlier context-cap/startup work from @linzhiqin2003 and @merchloubna70-dot; leave #697/#1827 open pending real massive-repo/manual startup verification. | | #2636 project-context mtime cache | Defer direct merge; harvest only after cache key/signature is widened. | Must include constitution changes, auto-generated context deletion, canonical path equivalence, and overwrite detection before landing. | | #2634 HarmonyOS port | Locally harvested with additional Nix-chain clearance; keep credited and do not close until the integration branch is public. | User-supplied MatePad Edge demo (`https://bilibili.com/video/av116689597368905`) confirms real-device interest. Added env-driven OpenHarmony SDK setup, OHOS platform guards/fallbacks, self-update disablement, and OHOS target gating for Starlark execpolicy parsing plus PTY support so published OHOS builds do not pull `nix` 0.28 through `rustyline` or `portable-pty`. `cargo check --workspace --all-features --locked`, focused PTY/clipboard tests, and `cargo tree --locked -p codewhale-tui --target aarch64-unknown-linux-ohos -i nix@0.28.0` passed; full OHOS target check is blocked on this host because `OHOS_NATIVE_SDK`/target CC/sysroot are not configured and `ring` cannot find `assert.h`. | | #2687 append-only mode/approval prompt | Defer direct merge; draft has compile failures and Plan-mode prompt correctness risks. | Any future harvest must keep stable `message[0]` genuinely mode-agnostic, preserve mode/approval suffixes after capacity replans, and distinguish external overrides from persisted generated prompts. | @@ -71,7 +72,7 @@ v0.9 branch so the remaining Windows/manual checks are explicit. | Windows IME/input recovery (#1835) | Partially fixed, still release-blocking. | Current branch has Windows IME recovery and char-routing tests, but the issue remains open with Windows/WSL reports. Needs a real Windows Terminal IME smoke for focus loss, idle, mode switch, first keystroke, and Esc recovery. | | Windows width/resize (#2708, #582 class) | Partially fixed on this branch. | #2708 is cherry-picked plus the fanout-card cache invalidation follow-up. `cargo test -p codewhale-tui --bin codewhale-tui --locked terminal_size -- --nocapture` passed. Still needs a real Windows Terminal resize smoke for #582 before #2721 closes. | | Windows shell descendant hangs (#2498, #1812 class) | Partially fixed and already harvested. | Foreground orphan-pipe regression passed locally with `cargo test -p codewhale-tui --all-features --locked foreground_shell_does_not_block_on_orphaned_subprocess_pipe -- --nocapture`. PR #2498 should close as harvested, but #1812 remains open for broader input-poll freeze modes and Windows CI/manual confirmation. | -| Large-repo context startup (#697/#1827 class) | Partially covered. | Project-context pack ordering/budget/noise tests passed with `cargo test -p codewhale-tui --bin codewhale-tui --locked project_context_pack -- --nocapture`. Still missing a synthetic many-file startup smoke that exercises first-turn latency end to end. | +| Large-repo context startup (#697/#1827 class) | Partially covered. | Project-context pack ordering/budget/noise tests passed, and the auto-generated fallback now has a synthetic 1000-file startup smoke with `cargo test -p codewhale-tui --bin codewhale-tui --locked auto_generated_context_is_bounded_for_many_file_workspace -- --nocapture`. Still needs a real massive-repo/manual startup benchmark before closing #697 or #1827. | | Sub-agent timeout and trust model (#1806, #719) | Fixed or covered in current branch. | `heartbeat_timeout_secs` clamp/default test passed, and `agent_open_description_explains_fresh_vs_forked_context_and_trust_model` asserts that sub-agent results are self-reports. | | Sub-agent checkpoint/resume (#2029) | Still release-blocking. | Session projection/transcript handles exist, but no checkpoint/continue status or resume contract has landed. Needs a child checkpoint/timeout/resume test that preserves policy and completes. | | Live shell/session liveness (#1786) | Partially fixed, still release-blocking. | Shell containment and turn-liveness tests exist, but orphaned PID/session-load reaping and long-running shell LIVE-state recovery remain open. Needs stale PID reaping and live-state regression coverage. |