Skip to content

Commit 1b55513

Browse files
committed
feat(ai-markmap-agent): add versioning mode (continue/reset)
- Add versioning.mode config: "continue" | "reset" - Continue mode: load from latest version (vN), produce vN+1 - Reset mode: prompt to delete all versions, start fresh from baseline - Add prompt_on_reset config option - Update DESIGN_V4.md, README.md, README_zh-TW.md with documentation
1 parent e15f68b commit 1b55513

File tree

7 files changed

+273
-20
lines changed

7 files changed

+273
-20
lines changed

tools/ai-markmap-agent/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,26 @@ outputs/versions/
383383

384384
Version numbers auto-increment: `v1`, `v2`, `v3`, ...
385385

386+
### Versioning Modes
387+
388+
Configure in `config/config.yaml`:
389+
390+
```yaml
391+
output:
392+
versioning:
393+
enabled: true
394+
directory: "outputs/versions"
395+
mode: "continue" # continue | reset
396+
prompt_on_reset: true
397+
```
398+
399+
| Mode | Behavior |
400+
|------|----------|
401+
| `continue` | Load from latest version (vN), produce vN+1 |
402+
| `reset` | Delete all versions, start fresh from `input.baseline.path`, produce v1 |
403+
404+
**Reset mode** prompts for confirmation before deleting existing versions.
405+
386406
---
387407

388408
## Module Responsibilities

tools/ai-markmap-agent/README_zh-TW.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,26 @@ outputs/versions/
383383

384384
版本號自動遞增:`v1``v2``v3`...
385385

386+
### 版本控制模式
387+
388+
`config/config.yaml` 設定:
389+
390+
```yaml
391+
output:
392+
versioning:
393+
enabled: true
394+
directory: "outputs/versions"
395+
mode: "continue" # continue | reset
396+
prompt_on_reset: true
397+
```
398+
399+
| 模式 | 行為 |
400+
|------|------|
401+
| `continue` | 從最新版本 (vN) 繼續精進,產生 vN+1 |
402+
| `reset` | 刪除所有版本,從 `input.baseline.path` 重新開始,產生 v1 |
403+
404+
**Reset 模式**會在刪除前詢問確認。
405+
386406
---
387407

388408
## 模組職責

tools/ai-markmap-agent/config/config.yaml

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ experts:
128128
architect:
129129
name: "Top Software Architect"
130130
emoji: "🏗️"
131-
model: "gpt-4o"
131+
model: "gpt-5.2"
132132
persona_prompt: "prompts/experts/architect_persona.md"
133133
behavior_prompt: "prompts/experts/architect_behavior.md"
134134
temperature: 0.6
@@ -143,7 +143,7 @@ experts:
143143
professor:
144144
name: "Distinguished Algorithm Professor"
145145
emoji: "📚"
146-
model: "gpt-4o"
146+
model: "gpt-5.2"
147147
persona_prompt: "prompts/experts/professor_persona.md"
148148
behavior_prompt: "prompts/experts/professor_behavior.md"
149149
temperature: 0.5
@@ -158,7 +158,7 @@ experts:
158158
engineer:
159159
name: "Senior Principal Engineer"
160160
emoji: "⚙️"
161-
model: "gpt-4o"
161+
model: "gpt-5.2"
162162
persona_prompt: "prompts/experts/engineer_persona.md"
163163
behavior_prompt: "prompts/experts/engineer_behavior.md"
164164
temperature: 0.6
@@ -261,12 +261,12 @@ workflow:
261261
# Writer Configuration
262262
# -----------------------------------------------------------------------------
263263
writer:
264-
model: "gpt-4o" # 128K context for full markmap
264+
model: "gpt-5.2" # 128K context for full markmap
265265
persona_prompt: "prompts/writer/writer_persona.md"
266266
behavior_prompt: "prompts/writer/writer_behavior.md"
267267
format_guide: "prompts/writer/markmap_format_guide.md"
268268
temperature: 0.4
269-
max_tokens: 8192
269+
max_tokens: 12000
270270

271271
# Writer behavior settings
272272
preserve_baseline_quality: true # Don't degrade existing good content
@@ -313,7 +313,15 @@ output:
313313
versioning:
314314
enabled: true
315315
directory: "outputs/versions"
316-
# Auto-increment: v1, v2, v3, ...
316+
317+
# Execution mode:
318+
# continue - Read from latest version (vN), produce vN+1
319+
# reset - Delete all versions, start fresh from input.baseline.path, produce v1
320+
mode: "reset"
321+
322+
# When mode=reset, prompt before deleting old versions
323+
# Set to false to auto-delete without confirmation
324+
prompt_on_reset: true
317325

318326
final_dirs:
319327
markdown: "../../docs/mindmaps"

tools/ai-markmap-agent/docs/DESIGN_V4.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,19 @@ output:
497497
naming:
498498
template: "neetcode_ontology_agent_evolved_{lang}"
499499
# Produces: neetcode_ontology_agent_evolved_en.md
500+
501+
# Version history
502+
versioning:
503+
enabled: true
504+
directory: "outputs/versions"
505+
506+
# Execution mode:
507+
# continue - Load from latest version (vN), produce vN+1
508+
# reset - Delete all versions, start from baseline.path, produce v1
509+
mode: "continue"
510+
511+
# When mode=reset, prompt before deleting
512+
prompt_on_reset: true
500513

501514
# -----------------------------------------------------------------------------
502515
# Expert Configuration (Scalable)
@@ -842,6 +855,56 @@ Version history:
842855

843856
---
844857

858+
## Versioning Modes
859+
860+
### Continue Mode (預設)
861+
862+
持續精進,從最新版本繼續:
863+
864+
```yaml
865+
versioning:
866+
mode: "continue"
867+
```
868+
869+
```
870+
現有版本: v1, v2, v3
871+
872+
執行流程:
873+
1. 讀取 v3 的輸出作為 baseline
874+
2. 專家精進
875+
3. 產生 v4
876+
```
877+
878+
### Reset Mode
879+
880+
重新開始,從原始 baseline 出發:
881+
882+
```yaml
883+
versioning:
884+
mode: "reset"
885+
```
886+
887+
```
888+
現有版本: v1, v2, v3
889+
890+
執行流程:
891+
1. 程式詢問:「確定要刪除 v1, v2, v3 嗎?[Y/N]」
892+
2. Y → 刪除所有版本,從 input.baseline.path 重新開始
893+
3. N → 程式結束,不做任何事
894+
4. 產生新的 v1
895+
```
896+
897+
### 使用場景
898+
899+
| 場景 | 使用模式 |
900+
|------|---------|
901+
| 日常迭代精進 | `continue` |
902+
| 切換新的 baseline 來源 | `reset` |
903+
| 版本歷史太亂想重來 | `reset` |
904+
| 測試新的專家配置 | `reset` |
905+
906+
---
907+
845908
## Summary
846909

847910
### V4 核心設計

tools/ai-markmap-agent/main.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
request_api_keys,
3232
)
3333
from src.data_sources import DataSourcesLoader
34-
from src.graph import run_pipeline, load_baseline_markmap
34+
from src.graph import run_pipeline, load_baseline_markmap, handle_versioning_mode
3535

3636

3737
def print_banner() -> None:
@@ -178,7 +178,13 @@ def main() -> int:
178178
else:
179179
print("Skipping API key input (--no-openai and/or --no-anthropic specified)\n")
180180

181-
# Step 3: Load baseline Markmap
181+
# Step 3: Handle versioning mode (reset prompts here)
182+
print("\nChecking versioning mode...")
183+
if not handle_versioning_mode(config):
184+
# User cancelled reset
185+
return 0
186+
187+
# Step 4: Load baseline Markmap
182188
print("\nLoading baseline Markmap...")
183189
if args.baseline:
184190
baseline_path = Path(args.baseline)
@@ -201,7 +207,7 @@ def main() -> int:
201207
print(f" ⚠ {e}")
202208
baseline_markmap = ""
203209

204-
# Step 4: Load data sources
210+
# Step 5: Load data sources
205211
print("\nLoading reference data...")
206212
loader = DataSourcesLoader(config)
207213
data = loader.load_all()
@@ -212,18 +218,18 @@ def main() -> int:
212218
# Print summary
213219
print_data_summary(loader.get_summary())
214220

215-
# Step 5: If dry-run, stop here
221+
# Step 6: If dry-run, stop here
216222
if args.dry_run:
217223
print("\n[DRY RUN] Data sources loaded successfully. Exiting.")
218224
return 0
219225

220-
# Step 6: Check required API keys
226+
# Step 7: Check required API keys
221227
if not args.no_openai and not ConfigLoader.has_api_key("openai"):
222228
print("\n❌ Error: OpenAI API key is required but not provided.")
223229
print(" Use --no-openai to skip if not needed.")
224230
return 1
225231

226-
# Step 7: Build and run the LangGraph pipeline
232+
# Step 8: Build and run the LangGraph pipeline
227233
print("\n" + "=" * 60)
228234
print("Starting Markmap Refinement Pipeline")
229235
print("=" * 60)

tools/ai-markmap-agent/src/graph.py

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,15 @@
3131
get_adopted_suggestions,
3232
ConsensusResult,
3333
)
34-
from .output.html_converter import save_all_markmaps
34+
from .output.html_converter import save_all_markmaps, MarkMapHTMLConverter
35+
36+
__all__ = [
37+
"run_pipeline",
38+
"run_pipeline_async",
39+
"build_markmap_graph",
40+
"load_baseline_markmap",
41+
"handle_versioning_mode",
42+
]
3543
from .post_processing import PostProcessor
3644
from .debug_output import get_debug_manager, reset_debug_manager
3745
from .config_loader import ConfigLoader
@@ -80,6 +88,10 @@ def load_baseline_markmap(config: dict[str, Any]) -> str:
8088
"""
8189
Load the baseline Markmap from file.
8290
91+
Behavior depends on versioning mode:
92+
- continue: Load from latest version (vN) if exists, else fall back to baseline.path
93+
- reset: Load from baseline.path (original source)
94+
8395
Args:
8496
config: Configuration dictionary
8597
@@ -90,8 +102,25 @@ def load_baseline_markmap(config: dict[str, Any]) -> str:
90102
baseline_config = input_config.get("baseline", {})
91103
baseline_path = baseline_config.get("path", "neetcode_ontology_ai_en.md")
92104

93-
# Resolve path relative to docs/mindmaps/
105+
# Check versioning mode
106+
versioning = config.get("output", {}).get("versioning", {})
107+
versioning_enabled = versioning.get("enabled", False)
108+
versioning_mode = versioning.get("mode", "continue")
109+
94110
base_dir = Path(__file__).parent.parent.parent.parent # Go to neetcode root
111+
112+
# For continue mode, try to load from latest version first
113+
if versioning_enabled and versioning_mode == "continue":
114+
converter = MarkMapHTMLConverter(config)
115+
latest_path = converter._get_latest_version_path("en")
116+
117+
if latest_path and latest_path.exists():
118+
print(f" 📂 Continue mode: Loading from {latest_path.parent.name}/{latest_path.name}")
119+
return latest_path.read_text(encoding="utf-8")
120+
else:
121+
print(" 📂 Continue mode: No previous version found, using baseline")
122+
123+
# Load from configured baseline path
95124
full_path = base_dir / "docs" / "mindmaps" / baseline_path
96125

97126
if full_path.exists():
@@ -116,6 +145,39 @@ def load_baseline_markmap(config: dict[str, Any]) -> str:
116145
raise FileNotFoundError(f"Baseline Markmap not found: {full_path}")
117146

118147

148+
def handle_versioning_mode(config: dict[str, Any]) -> bool:
149+
"""
150+
Handle versioning mode before running the pipeline.
151+
152+
For reset mode, prompts user to confirm deletion of old versions.
153+
154+
Args:
155+
config: Configuration dictionary
156+
157+
Returns:
158+
True to continue, False to abort (user cancelled reset)
159+
"""
160+
versioning = config.get("output", {}).get("versioning", {})
161+
versioning_enabled = versioning.get("enabled", False)
162+
versioning_mode = versioning.get("mode", "continue")
163+
164+
if not versioning_enabled:
165+
return True
166+
167+
if versioning_mode == "reset":
168+
converter = MarkMapHTMLConverter(config)
169+
return converter.handle_reset_mode()
170+
171+
# Continue mode - just show info
172+
converter = MarkMapHTMLConverter(config)
173+
existing = converter._get_existing_versions()
174+
if existing:
175+
print(f" 📂 Continue mode: {len(existing)} existing version(s)")
176+
print(f" Latest: {existing[-1].name}")
177+
178+
return True
179+
180+
119181
def build_markmap_graph(config: dict[str, Any] | None = None) -> StateGraph:
120182
"""
121183
Build the LangGraph workflow for Markmap refinement.

0 commit comments

Comments
 (0)