up-cli 0.2.0__py3-none-any.whl → 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. up/__init__.py +1 -1
  2. up/ai_cli.py +229 -0
  3. up/cli.py +54 -9
  4. up/commands/agent.py +521 -0
  5. up/commands/bisect.py +343 -0
  6. up/commands/branch.py +350 -0
  7. up/commands/init.py +195 -6
  8. up/commands/learn.py +1392 -32
  9. up/commands/memory.py +545 -0
  10. up/commands/provenance.py +267 -0
  11. up/commands/review.py +239 -0
  12. up/commands/start.py +752 -42
  13. up/commands/status.py +173 -18
  14. up/commands/sync.py +317 -0
  15. up/commands/vibe.py +304 -0
  16. up/context.py +64 -10
  17. up/core/__init__.py +69 -0
  18. up/core/checkpoint.py +479 -0
  19. up/core/provenance.py +364 -0
  20. up/core/state.py +678 -0
  21. up/events.py +512 -0
  22. up/git/__init__.py +37 -0
  23. up/git/utils.py +270 -0
  24. up/git/worktree.py +331 -0
  25. up/learn/__init__.py +155 -0
  26. up/learn/analyzer.py +227 -0
  27. up/learn/plan.py +374 -0
  28. up/learn/research.py +511 -0
  29. up/learn/utils.py +117 -0
  30. up/memory.py +1096 -0
  31. up/parallel.py +551 -0
  32. up/templates/config/__init__.py +1 -1
  33. up/templates/docs/SKILL.md +28 -0
  34. up/templates/docs/__init__.py +341 -0
  35. up/templates/docs/standards/HEADERS.md +24 -0
  36. up/templates/docs/standards/STRUCTURE.md +18 -0
  37. up/templates/docs/standards/TEMPLATES.md +19 -0
  38. up/templates/loop/__init__.py +92 -32
  39. up/ui/__init__.py +14 -0
  40. up/ui/loop_display.py +650 -0
  41. up/ui/theme.py +137 -0
  42. {up_cli-0.2.0.dist-info → up_cli-0.5.0.dist-info}/METADATA +160 -15
  43. up_cli-0.5.0.dist-info/RECORD +55 -0
  44. up_cli-0.2.0.dist-info/RECORD +0 -23
  45. {up_cli-0.2.0.dist-info → up_cli-0.5.0.dist-info}/WHEEL +0 -0
  46. {up_cli-0.2.0.dist-info → up_cli-0.5.0.dist-info}/entry_points.txt +0 -0
up/commands/init.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """up init - Initialize up systems in existing project."""
2
2
 
3
3
  import os
4
+ import stat
4
5
  from pathlib import Path
5
6
 
6
7
  import click
@@ -27,13 +28,32 @@ console = Console()
27
28
  default=["all"],
28
29
  help="Systems to initialize",
29
30
  )
31
+ @click.option(
32
+ "--hooks/--no-hooks",
33
+ default=True,
34
+ help="Install git hooks for auto-sync (default: yes)",
35
+ )
36
+ @click.option(
37
+ "--memory/--no-memory",
38
+ default=True,
39
+ help="Build initial memory from git history (default: yes)",
40
+ )
30
41
  @click.option(
31
42
  "--force",
32
43
  is_flag=True,
33
44
  help="Overwrite existing files",
34
45
  )
35
- def init_cmd(ai: str, systems: tuple, force: bool):
36
- """Initialize up systems in the current directory."""
46
+ def init_cmd(ai: str, systems: tuple, hooks: bool, memory: bool, force: bool):
47
+ """Initialize up systems in the current directory.
48
+
49
+ Automatically:
50
+ - Installs git hooks for memory auto-sync
51
+ - Indexes existing git history to memory
52
+ - Scans project structure for context
53
+
54
+ Use --no-hooks to disable hooks.
55
+ Use --no-memory to skip initial memory build.
56
+ """
37
57
  cwd = Path.cwd()
38
58
 
39
59
  console.print(Panel.fit(
@@ -53,11 +73,177 @@ def init_cmd(ai: str, systems: tuple, force: bool):
53
73
  force=force,
54
74
  )
55
75
 
76
+ # Install git hooks automatically
77
+ hooks_installed = False
78
+ if hooks:
79
+ hooks_installed = _install_git_hooks(cwd)
80
+
81
+ # Build initial memory from existing project
82
+ memory_stats = None
83
+ if memory:
84
+ memory_stats = _build_initial_memory(cwd)
85
+
56
86
  console.print("\n[green]✓[/] Initialization complete!")
57
- _print_next_steps(systems)
87
+
88
+ if hooks_installed:
89
+ console.print("[green]✓[/] Git hooks installed for auto-sync")
90
+
91
+ if memory_stats:
92
+ console.print(f"[green]✓[/] Memory initialized ({memory_stats['total']} entries)")
93
+
94
+ _print_next_steps(systems, hooks_installed)
95
+
96
+
97
+ def _build_initial_memory(workspace: Path) -> dict:
98
+ """Build initial memory from existing project.
99
+
100
+ Indexes:
101
+ - Existing git commits (up to 50)
102
+ - Recent file changes
103
+ - Project structure metadata
104
+
105
+ Returns stats dict or None if failed.
106
+ """
107
+ try:
108
+ import os
109
+ import warnings
110
+ from up.memory import MemoryManager
111
+
112
+ # Suppress noisy warnings from tokenizers
113
+ os.environ["TOKENIZERS_PARALLELISM"] = "false"
114
+ warnings.filterwarnings("ignore", category=UserWarning)
115
+
116
+ console.print("\n[dim]Building initial memory...[/]")
117
+
118
+ manager = MemoryManager(workspace, use_vectors=False) # Use fast JSON backend
119
+
120
+ # Index existing commits
121
+ commits = manager.index_recent_commits(count=50)
122
+ console.print(f" [dim]Indexed {commits} commits[/]")
123
+
124
+ # Index recent file changes
125
+ files = manager.index_file_changes()
126
+ console.print(f" [dim]Indexed {files} files[/]")
127
+
128
+ # Record project initialization
129
+ import subprocess
130
+
131
+ # Get project info
132
+ project_name = workspace.name
133
+
134
+ # Detect languages/frameworks
135
+ languages = []
136
+ if (workspace / "pyproject.toml").exists() or (workspace / "requirements.txt").exists():
137
+ languages.append("Python")
138
+ if (workspace / "package.json").exists():
139
+ languages.append("JavaScript/TypeScript")
140
+ if (workspace / "go.mod").exists():
141
+ languages.append("Go")
142
+ if (workspace / "Cargo.toml").exists():
143
+ languages.append("Rust")
144
+
145
+ # Record initialization as a learning
146
+ if languages:
147
+ manager.record_learning(
148
+ f"Project '{project_name}' initialized with up-cli. "
149
+ f"Languages detected: {', '.join(languages)}. "
150
+ f"Indexed {commits} commits and {files} files into memory."
151
+ )
152
+
153
+ stats = manager.get_stats()
154
+ return {
155
+ "total": stats.get("total", 0),
156
+ "commits": commits,
157
+ "files": files,
158
+ }
159
+
160
+ except Exception as e:
161
+ console.print(f" [yellow]Warning: Could not build memory: {e}[/]")
162
+ return None
163
+
164
+
165
+ def _install_git_hooks(workspace: Path) -> bool:
166
+ """Install git hooks for automatic memory sync.
167
+
168
+ Returns True if hooks were installed successfully.
169
+ """
170
+ git_dir = workspace / ".git"
171
+
172
+ if not git_dir.exists():
173
+ console.print("[yellow]⚠[/] Not a git repo, skipping hooks")
174
+ return False
175
+
176
+ hooks_dir = git_dir / "hooks"
177
+ hooks_dir.mkdir(exist_ok=True)
178
+
179
+ # Post-commit hook
180
+ post_commit = hooks_dir / "post-commit"
181
+ post_commit_content = '''#!/bin/bash
182
+ # up-cli auto-sync hook (installed by up init)
183
+ # Indexes commits to memory automatically
184
+
185
+ # Run in background to not slow down commits
186
+ (
187
+ sleep 1
188
+
189
+ # Sync memory with latest commit
190
+ if command -v up &> /dev/null; then
191
+ up memory sync 2>/dev/null
192
+ elif command -v python3 &> /dev/null; then
193
+ python3 -m up.memory sync 2>/dev/null
194
+ fi
195
+ ) &
196
+
197
+ exit 0
198
+ '''
199
+
200
+ _write_hook(post_commit, post_commit_content)
201
+
202
+ # Post-checkout hook (for branch switches)
203
+ post_checkout = hooks_dir / "post-checkout"
204
+ post_checkout_content = '''#!/bin/bash
205
+ # up-cli context update hook (installed by up init)
206
+ # Updates context when switching branches
207
+
208
+ PREV_HEAD=$1
209
+ NEW_HEAD=$2
210
+ BRANCH_CHECKOUT=$3
211
+
212
+ # Only run on branch checkout, not file checkout
213
+ if [ "$BRANCH_CHECKOUT" = "1" ]; then
214
+ (
215
+ sleep 1
216
+ if command -v up &> /dev/null; then
217
+ up sync --no-memory 2>/dev/null
218
+ fi
219
+ ) &
220
+ fi
221
+
222
+ exit 0
223
+ '''
224
+
225
+ _write_hook(post_checkout, post_checkout_content)
226
+
227
+ return True
228
+
229
+
230
+ def _write_hook(path: Path, content: str):
231
+ """Write hook file with executable permissions."""
232
+ # Check for existing hook
233
+ if path.exists():
234
+ existing = path.read_text()
235
+ if "up-cli" in existing:
236
+ # Already our hook, overwrite
237
+ pass
238
+ else:
239
+ # User has custom hook, append
240
+ content = existing + "\n\n" + content
241
+
242
+ path.write_text(content)
243
+ path.chmod(path.stat().st_mode | stat.S_IEXEC)
58
244
 
59
245
 
60
- def _print_next_steps(systems: tuple):
246
+ def _print_next_steps(systems: tuple, hooks_installed: bool):
61
247
  """Print next steps after initialization."""
62
248
  console.print("\n[bold]Next steps:[/]")
63
249
 
@@ -65,7 +251,10 @@ def _print_next_steps(systems: tuple):
65
251
  console.print(" • Edit [cyan]docs/roadmap/vision/PRODUCT_VISION.md[/]")
66
252
 
67
253
  if "learn" in systems:
68
- console.print(" • Run [cyan]/learn auto[/] to analyze your project")
254
+ console.print(" • Run [cyan]up learn auto[/] to analyze your project")
69
255
 
70
256
  if "loop" in systems:
71
- console.print(" • Run [cyan]/product-loop[/] to start development")
257
+ console.print(" • Run [cyan]up start[/] to start development")
258
+
259
+ if hooks_installed:
260
+ console.print("\n[dim]Auto-sync enabled: commits will be indexed automatically[/]")