code-data-ark 2.0.4__tar.gz → 2.0.6__tar.gz
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.
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/PKG-INFO +49 -21
- code_data_ark-2.0.6/cda/__main__.py +10 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/kernel/paths.py +36 -6
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/ui/cli.py +250 -5
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/changelog.md +26 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/pyproject.toml +1 -1
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/readme.md +48 -20
- code_data_ark-2.0.6/version +1 -0
- code_data_ark-2.0.4/version +0 -1
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/.flake8 +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/.github/workflows/ci.yml +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/.gitignore +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/bin/release.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/__init__.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/kernel/__init__.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/kernel/control_db.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/kernel/pmf_kernel.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/kernel/selfcheck.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/pipeline/__init__.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/pipeline/embed.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/pipeline/extract.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/pipeline/ingest.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/pipeline/parse_edits.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/pipeline/reconstruct.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/pipeline/watcher.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/ui/__init__.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/cda/ui/web.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/contributing.md +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/docs/architecture.md +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/docs/examples/usage.md +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/docs/pmf_kernel.md +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/docs/roadmap.md +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/license +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/makefile +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/tests/test_basic.py +0 -0
- {code_data_ark-2.0.4 → code_data_ark-2.0.6}/tests/test_selfcheck.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-data-ark
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.6
|
|
4
4
|
Summary: Code Data Ark — local observability and intelligence platform for VS Code + Copilot Chat sessions
|
|
5
5
|
Project-URL: Homepage, https://github.com/goCosmix/cda
|
|
6
6
|
Project-URL: Repository, https://github.com/goCosmix/cda.git
|
|
@@ -95,10 +95,17 @@ The runtime is managed by an embedded process kernel (PMF) that supervises the w
|
|
|
95
95
|
pip install code-data-ark
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
+
> **macOS / system Python note**: pip installs the `cda` binary to `~/Library/Python/3.x/bin/` which is not on `PATH` by default. Use the fallback below — `cda setup` will fix PATH for you automatically:
|
|
99
|
+
>
|
|
100
|
+
> ```bash
|
|
101
|
+
> python3 -m cda setup
|
|
102
|
+
> ```
|
|
103
|
+
|
|
98
104
|
### Install with pipx
|
|
99
105
|
|
|
100
106
|
```bash
|
|
101
107
|
pipx install code-data-ark
|
|
108
|
+
# pipx automatically manages PATH — `cda setup` works immediately
|
|
102
109
|
```
|
|
103
110
|
|
|
104
111
|
### Install from source
|
|
@@ -117,52 +124,73 @@ pip install -e ".[dev]"
|
|
|
117
124
|
make install-dev
|
|
118
125
|
```
|
|
119
126
|
|
|
120
|
-
> The `cda` console command is installed into your
|
|
127
|
+
> The `cda` console command is installed into your Python environment's `bin` directory. If it isn't on PATH yet, use `python3 -m cda setup` — setup patches `~/.zprofile` automatically.
|
|
121
128
|
|
|
122
129
|
## ⚡ Quick Start
|
|
123
130
|
|
|
124
|
-
1. **Install**
|
|
125
|
-
|
|
126
131
|
```bash
|
|
127
132
|
pip install code-data-ark
|
|
133
|
+
python3 -m cda setup # use this if `cda` isn't on PATH yet
|
|
128
134
|
```
|
|
129
135
|
|
|
130
|
-
|
|
136
|
+
After the first run, `cda setup` patches `~/.zprofile` so `cda` is on PATH in every new terminal.
|
|
131
137
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
138
|
+
`cda setup` runs four steps in sequence:
|
|
139
|
+
|
|
140
|
+
| Step | What it does |
|
|
141
|
+
|------|-------------|
|
|
142
|
+
| **1. Init** | Creates `~/Library/goCosmix/apps/code-data-ark/` — all app data in one organized namespace. Also patches `~/.zprofile` if `cda` isn't on PATH yet. |
|
|
143
|
+
| **2. PMF install** | Registers a macOS LaunchAgent — CDA starts automatically on every login via `cda pmf up` |
|
|
144
|
+
| **3. Sync** | Ingests all VS Code + Copilot session data into `cda.db` |
|
|
145
|
+
| **4. Up** | Starts the watcher daemon and web UI via the PMF kernel, opens browser |
|
|
135
146
|
|
|
136
|
-
|
|
147
|
+
All data lives in `~/Library/goCosmix/apps/code-data-ark/`. After setup, everything is managed by the **PMF kernel** — no terminal interaction required.
|
|
148
|
+
|
|
149
|
+
### Options
|
|
137
150
|
|
|
138
151
|
```bash
|
|
139
|
-
cda sync
|
|
152
|
+
cda setup --skip-sync # Skip initial ingest (run `cda sync` manually later)
|
|
153
|
+
cda setup --no-browser # Don't open browser when the UI starts
|
|
140
154
|
```
|
|
141
155
|
|
|
142
|
-
|
|
156
|
+
### After setup
|
|
143
157
|
|
|
144
158
|
```bash
|
|
145
|
-
cda
|
|
159
|
+
cda check # Full system health diagnostic
|
|
160
|
+
cda sync # Re-ingest after significant new session activity
|
|
161
|
+
cda pmf services # View all running services and their status
|
|
162
|
+
cda pmf uninstall # Remove the auto-start LaunchAgent registration
|
|
146
163
|
```
|
|
147
164
|
|
|
148
|
-
|
|
165
|
+
## 🔧 Process Management (PMF)
|
|
149
166
|
|
|
150
|
-
|
|
151
|
-
|
|
167
|
+
All background processes run through the embedded PMF kernel. The LaunchAgent is the entry point — nothing starts directly on the host outside of PMF.
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
launchd (login)
|
|
171
|
+
└─ cda pmf up
|
|
172
|
+
├─ PMF kernel → watcher daemon (cda.pipeline.watcher)
|
|
173
|
+
└─ PMF kernel → web UI server (cda.ui.web)
|
|
152
174
|
```
|
|
153
175
|
|
|
154
|
-
|
|
176
|
+
### PMF commands
|
|
155
177
|
|
|
156
178
|
```bash
|
|
157
|
-
cda
|
|
179
|
+
cda pmf services # List all services with status and PID
|
|
180
|
+
cda pmf start <service> # Start a service (watcher, ui, sync, reconstruct, embed-build)
|
|
181
|
+
cda pmf stop <service> # Stop a service
|
|
182
|
+
cda pmf restart <service> # Restart a service
|
|
183
|
+
cda pmf logs <service> # Tail the service log
|
|
184
|
+
cda pmf up # Start watcher + UI (opens browser) — same as launchd trigger
|
|
185
|
+
cda pmf install # Register LaunchAgent (done automatically by cda setup)
|
|
186
|
+
cda pmf uninstall # Remove LaunchAgent
|
|
158
187
|
```
|
|
159
188
|
|
|
160
189
|
## 🌐 Web UI
|
|
161
190
|
|
|
162
|
-
- **Background service
|
|
163
|
-
- **
|
|
164
|
-
- **
|
|
165
|
-
- **Foreground mode**: `cda serve`
|
|
191
|
+
- **Background service** (default after setup): managed by PMF, starts on login
|
|
192
|
+
- **Foreground mode**: `cda serve` — runs in the terminal, opens browser, Ctrl+C to stop
|
|
193
|
+
- **Access**: `http://127.0.0.1:10001`
|
|
166
194
|
|
|
167
195
|
The web UI includes:
|
|
168
196
|
|
|
@@ -5,10 +5,16 @@ CDA_HOME is the single root for all runtime state (DB, PID files, logs,
|
|
|
5
5
|
queue, PMF runtime). It is resolved exactly once at import time via:
|
|
6
6
|
|
|
7
7
|
1. CDA_HOME environment variable (absolute path)
|
|
8
|
-
2.
|
|
8
|
+
2. ~/Library/goCosmix/apps/code-data-ark/ (macOS default)
|
|
9
|
+
3. ~/.gocosmix/apps/code-data-ark/ (fallback on non-macOS)
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
All goCosmix apps share the ~/Library/goCosmix/ namespace:
|
|
12
|
+
|
|
13
|
+
~/Library/goCosmix/
|
|
14
|
+
├── apps/
|
|
15
|
+
│ ├── code-data-ark/ ← CDA_HOME
|
|
16
|
+
│ └── ... ← future goCosmix apps
|
|
17
|
+
└── system/ ← shared goCosmix infrastructure
|
|
12
18
|
"""
|
|
13
19
|
|
|
14
20
|
import os
|
|
@@ -17,17 +23,40 @@ from pathlib import Path
|
|
|
17
23
|
# ── home resolution ──────────────────────────────────────────────────────────
|
|
18
24
|
|
|
19
25
|
|
|
26
|
+
def _default_cda_home() -> Path:
|
|
27
|
+
"""Platform-appropriate default for CDA_HOME."""
|
|
28
|
+
library = Path.home() / "Library"
|
|
29
|
+
if library.exists(): # macOS
|
|
30
|
+
return library / "goCosmix" / "apps" / "code-data-ark"
|
|
31
|
+
return Path.home() / ".gocosmix" / "apps" / "code-data-ark"
|
|
32
|
+
|
|
33
|
+
|
|
20
34
|
def get_cda_home() -> Path:
|
|
21
35
|
"""Return the CDA home directory, creating it if it doesn't exist."""
|
|
22
36
|
env = os.environ.get("CDA_HOME")
|
|
23
37
|
if env:
|
|
24
38
|
home = Path(env).expanduser().resolve()
|
|
25
39
|
else:
|
|
26
|
-
home =
|
|
40
|
+
home = _default_cda_home()
|
|
27
41
|
home.mkdir(parents=True, exist_ok=True)
|
|
28
42
|
return home
|
|
29
43
|
|
|
30
44
|
|
|
45
|
+
# ── goCosmix namespace (shared across all goCosmix apps) ────────────────────
|
|
46
|
+
|
|
47
|
+
def get_gocosmix_home() -> Path:
|
|
48
|
+
"""Return ~/Library/goCosmix (macOS) or ~/.gocosmix (other)."""
|
|
49
|
+
library = Path.home() / "Library"
|
|
50
|
+
if library.exists():
|
|
51
|
+
return library / "goCosmix"
|
|
52
|
+
return Path.home() / ".gocosmix"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
GOCOSMIX_HOME = get_gocosmix_home()
|
|
56
|
+
GOCOSMIX_APPS = GOCOSMIX_HOME / "apps"
|
|
57
|
+
GOCOSMIX_SYSTEM = GOCOSMIX_HOME / "system"
|
|
58
|
+
|
|
59
|
+
|
|
31
60
|
# ── canonical paths (module-level constants, computed once) ─────────────────
|
|
32
61
|
|
|
33
62
|
CDA_HOME = get_cda_home()
|
|
@@ -49,6 +78,7 @@ RUNTIME_FILE = PMF_DIR / "runtime.json"
|
|
|
49
78
|
|
|
50
79
|
|
|
51
80
|
def ensure_dirs() -> None:
|
|
52
|
-
"""Create all runtime directories. Safe to call multiple times."""
|
|
53
|
-
for d in (
|
|
81
|
+
"""Create all runtime directories (including goCosmix namespace). Safe to call multiple times."""
|
|
82
|
+
for d in (GOCOSMIX_HOME, GOCOSMIX_APPS, GOCOSMIX_SYSTEM,
|
|
83
|
+
DATA_DIR, RUN_DIR, LOG_DIR, QUEUE_DIR, PMF_DIR, PMF_LOG_DIR, CONFIG_DIR):
|
|
54
84
|
d.mkdir(parents=True, exist_ok=True)
|
|
@@ -28,7 +28,8 @@ Commands:
|
|
|
28
28
|
cda pmf install Register as macOS LaunchAgent (auto-start on login)
|
|
29
29
|
cda pmf uninstall Remove the LaunchAgent registration
|
|
30
30
|
cda check Run a full self-diagnostic. The system checks itself.
|
|
31
|
-
cda init First-run setup — create
|
|
31
|
+
cda init First-run setup — create ~/Library/goCosmix/ and validate environment
|
|
32
|
+
cda setup Full onboarding: init → pmf install → sync → up (browser opens)
|
|
32
33
|
cda serve Start the local web UI on port 10001
|
|
33
34
|
cda sync Full re-ingest from disk (rebuilds entire DB)
|
|
34
35
|
cda reconstruct Re-run reconstruction and FTS rebuild only
|
|
@@ -80,6 +81,14 @@ import click
|
|
|
80
81
|
# Ensure runtime dirs exist on every CLI invocation
|
|
81
82
|
ensure_dirs()
|
|
82
83
|
|
|
84
|
+
|
|
85
|
+
def _pmf_warn_if_not_installed():
|
|
86
|
+
"""Emit a one-time advisory if the LaunchAgent is not registered."""
|
|
87
|
+
if not plist_path().exists():
|
|
88
|
+
click.echo(yellow(" Note: LaunchAgent not installed — services won't auto-start on login."))
|
|
89
|
+
click.echo(yellow(" Run `cda setup` to register, or `cda pmf install` to add just the plist."))
|
|
90
|
+
|
|
91
|
+
|
|
83
92
|
kernel = PMFKernel()
|
|
84
93
|
|
|
85
94
|
|
|
@@ -408,7 +417,8 @@ def _ui_is_running():
|
|
|
408
417
|
@click.option("--port", default=10001, show_default=True, help="Local port for the web UI")
|
|
409
418
|
@click.option("--no-browser", "no_browser", is_flag=True, default=False, help="Don't open browser automatically")
|
|
410
419
|
def ui_start(host, port, no_browser):
|
|
411
|
-
"""Start the web UI as a background service."""
|
|
420
|
+
"""Start the web UI as a background service (via PMF kernel)."""
|
|
421
|
+
_pmf_warn_if_not_installed()
|
|
412
422
|
try:
|
|
413
423
|
result = kernel.start_service("ui", options={"host": host, "port": port})
|
|
414
424
|
url = f"http://{host}:{port}"
|
|
@@ -788,10 +798,11 @@ def watch():
|
|
|
788
798
|
|
|
789
799
|
@watch.command("start")
|
|
790
800
|
def watch_start():
|
|
791
|
-
"""Start the live sync watcher daemon."""
|
|
801
|
+
"""Start the live sync watcher daemon (via PMF kernel)."""
|
|
802
|
+
_pmf_warn_if_not_installed()
|
|
792
803
|
try:
|
|
793
804
|
result = kernel.start_service("watcher")
|
|
794
|
-
click.echo(green(f" Watcher started
|
|
805
|
+
click.echo(green(f" Watcher started pid={result['pid']} (via PMF)"))
|
|
795
806
|
except PMFKernelError as exc:
|
|
796
807
|
click.echo(red(f" {exc}"))
|
|
797
808
|
|
|
@@ -2646,13 +2657,247 @@ def check(as_json, fail_fast):
|
|
|
2646
2657
|
sys.exit(0 if passed_all else 1)
|
|
2647
2658
|
|
|
2648
2659
|
|
|
2660
|
+
# ─────────────────────────────────────────────
|
|
2661
|
+
# SETUP
|
|
2662
|
+
# ─────────────────────────────────────────────
|
|
2663
|
+
|
|
2664
|
+
@cli.command("setup")
|
|
2665
|
+
@click.option("--skip-sync", "skip_sync", is_flag=True, default=False,
|
|
2666
|
+
help="Skip initial data ingest (run `cda sync` manually later)")
|
|
2667
|
+
@click.option("--no-browser", "no_browser", is_flag=True, default=False,
|
|
2668
|
+
help="Don't open browser when the web UI starts")
|
|
2669
|
+
def setup(skip_sync, no_browser):
|
|
2670
|
+
"""
|
|
2671
|
+
Full onboarding in four steps: init → pmf install → sync → up.
|
|
2672
|
+
|
|
2673
|
+
\b
|
|
2674
|
+
Run this once after `pip install code-data-ark`.
|
|
2675
|
+
If `cda` isn't on PATH yet, use the fallback:
|
|
2676
|
+
|
|
2677
|
+
python3 -m cda setup
|
|
2678
|
+
|
|
2679
|
+
\b
|
|
2680
|
+
What each step does:
|
|
2681
|
+
1. Init — create ~/Library/goCosmix/apps/code-data-ark/, patch PATH
|
|
2682
|
+
2. Install — register a macOS LaunchAgent so CDA starts on every login
|
|
2683
|
+
3. Sync — ingest all VS Code + Copilot session data into cda.db
|
|
2684
|
+
4. Up — start the watcher daemon and web UI via PMF, open browser
|
|
2685
|
+
|
|
2686
|
+
All processes are managed by the PMF kernel. The LaunchAgent calls
|
|
2687
|
+
`cda pmf up` on every login — no manual interaction needed after setup.
|
|
2688
|
+
"""
|
|
2689
|
+
import shutil as _shutil
|
|
2690
|
+
import os as _os
|
|
2691
|
+
from cda.kernel.paths import (
|
|
2692
|
+
CDA_HOME, DATA_DIR, RUN_DIR, LOG_DIR, QUEUE_DIR,
|
|
2693
|
+
PMF_DIR, PMF_LOG_DIR, CONFIG_DIR, POLICY_FILE,
|
|
2694
|
+
GOCOSMIX_HOME, GOCOSMIX_APPS, GOCOSMIX_SYSTEM,
|
|
2695
|
+
)
|
|
2696
|
+
|
|
2697
|
+
W = 52
|
|
2698
|
+
BAR = "═" * W
|
|
2699
|
+
bar = "─" * W
|
|
2700
|
+
host, port = "127.0.0.1", 10001
|
|
2701
|
+
url = f"http://{host}:{port}"
|
|
2702
|
+
|
|
2703
|
+
click.echo()
|
|
2704
|
+
click.echo(bold(BAR))
|
|
2705
|
+
click.echo(bold(" Code Data Ark — setup"))
|
|
2706
|
+
click.echo(bold(BAR))
|
|
2707
|
+
click.echo()
|
|
2708
|
+
click.echo(dim(" Four steps to a fully operational CDA installation:"))
|
|
2709
|
+
click.echo(dim(f" 1. Init — create {CDA_HOME}"))
|
|
2710
|
+
click.echo(dim(" 2. Install — register macOS LaunchAgent (auto-start on login)"))
|
|
2711
|
+
click.echo(dim(" 3. Sync — first-run data ingest") + (dim(" [skipped]") if skip_sync else ""))
|
|
2712
|
+
click.echo(dim(" 4. Up — start watcher + web UI via PMF, open browser"))
|
|
2713
|
+
click.echo()
|
|
2714
|
+
|
|
2715
|
+
# ── Step 1: Init ─────────────────────────────────────────────
|
|
2716
|
+
click.echo(bold(bar))
|
|
2717
|
+
click.echo(bold(" Step 1/4 — Init"))
|
|
2718
|
+
click.echo(bold(bar))
|
|
2719
|
+
click.echo()
|
|
2720
|
+
|
|
2721
|
+
# Create full goCosmix namespace + app dirs
|
|
2722
|
+
dirs = [GOCOSMIX_HOME, GOCOSMIX_APPS, GOCOSMIX_SYSTEM,
|
|
2723
|
+
DATA_DIR, RUN_DIR, LOG_DIR, QUEUE_DIR, PMF_DIR, PMF_LOG_DIR, CONFIG_DIR]
|
|
2724
|
+
for d in dirs:
|
|
2725
|
+
existed = d.exists()
|
|
2726
|
+
d.mkdir(parents=True, exist_ok=True)
|
|
2727
|
+
if not existed:
|
|
2728
|
+
click.echo(f" {green('+')} {d}")
|
|
2729
|
+
else:
|
|
2730
|
+
click.echo(f" {green('✓')} {d}")
|
|
2731
|
+
|
|
2732
|
+
if not POLICY_FILE.exists():
|
|
2733
|
+
POLICY_FILE.write_text("# CDA access policy\n# ALLOW <pattern>\n# DENY <pattern>\n")
|
|
2734
|
+
|
|
2735
|
+
# Offer migration from legacy ~/.cda/
|
|
2736
|
+
legacy = Path.home() / ".cda"
|
|
2737
|
+
if legacy.exists() and legacy != CDA_HOME:
|
|
2738
|
+
click.echo()
|
|
2739
|
+
click.echo(yellow(f" ⚠ Legacy data found at {legacy}"))
|
|
2740
|
+
click.echo(yellow(" Run `cda migrate-home` after setup to move it to the new location."))
|
|
2741
|
+
|
|
2742
|
+
# VS Code data dir check
|
|
2743
|
+
vscode_data = Path(_os.environ.get(
|
|
2744
|
+
"VSCODE_DATA_DIR",
|
|
2745
|
+
Path.home() / "Library/Application Support/Code/User",
|
|
2746
|
+
))
|
|
2747
|
+
if vscode_data.exists():
|
|
2748
|
+
click.echo(f" {green('✓')} VS Code data dir found")
|
|
2749
|
+
else:
|
|
2750
|
+
click.echo(f" {yellow('⚠')} VS Code data dir not found: {vscode_data}")
|
|
2751
|
+
click.echo(yellow(" Set VSCODE_DATA_DIR if your data is elsewhere."))
|
|
2752
|
+
|
|
2753
|
+
click.echo()
|
|
2754
|
+
click.echo(f" {green('✓')} CDA_HOME: {CDA_HOME}")
|
|
2755
|
+
click.echo()
|
|
2756
|
+
|
|
2757
|
+
# ── PATH patch ───────────────────────────────────────────────
|
|
2758
|
+
# Detect where pip placed the `cda` binary and ensure it's on PATH.
|
|
2759
|
+
# Works whether invoked as `cda setup` or `python3 -m cda setup`.
|
|
2760
|
+
cda_bin_dir = None
|
|
2761
|
+
cda_bin = _shutil.which("cda")
|
|
2762
|
+
if cda_bin:
|
|
2763
|
+
cda_bin_dir = str(Path(cda_bin).parent)
|
|
2764
|
+
else:
|
|
2765
|
+
# pip install --user puts scripts next to python executable
|
|
2766
|
+
py_bin_dir = Path(sys.executable).parent
|
|
2767
|
+
candidate = py_bin_dir / "cda"
|
|
2768
|
+
if candidate.exists():
|
|
2769
|
+
cda_bin_dir = str(py_bin_dir)
|
|
2770
|
+
|
|
2771
|
+
if cda_bin_dir and cda_bin_dir not in _os.environ.get("PATH", "").split(":"):
|
|
2772
|
+
export_line = f'export PATH="{cda_bin_dir}:$PATH"'
|
|
2773
|
+
zprofile = Path.home() / ".zprofile"
|
|
2774
|
+
existing = zprofile.read_text() if zprofile.exists() else ""
|
|
2775
|
+
if export_line not in existing:
|
|
2776
|
+
with open(zprofile, "a") as f:
|
|
2777
|
+
f.write(f"\n# goCosmix — added by cda setup\n{export_line}\n")
|
|
2778
|
+
click.echo(f" {green('+')} PATH updated in ~/.zprofile")
|
|
2779
|
+
click.echo(yellow(" Run `source ~/.zprofile` or open a new terminal to activate."))
|
|
2780
|
+
click.echo(f" {green('✓')} cda binary: {cda_bin_dir}/cda")
|
|
2781
|
+
elif cda_bin:
|
|
2782
|
+
click.echo(f" {green('✓')} cda binary on PATH: {cda_bin}")
|
|
2783
|
+
|
|
2784
|
+
click.echo()
|
|
2785
|
+
|
|
2786
|
+
# ── Step 2: PMF install ──────────────────────────────────────
|
|
2787
|
+
click.echo(bold(bar))
|
|
2788
|
+
click.echo(bold(" Step 2/4 — PMF install"))
|
|
2789
|
+
click.echo(bold(bar))
|
|
2790
|
+
click.echo()
|
|
2791
|
+
click.echo(dim(" The LaunchAgent registers CDA with macOS launchd. On every login,"))
|
|
2792
|
+
click.echo(dim(" launchd calls `cda pmf up` — starts watcher + web UI via PMF kernel."))
|
|
2793
|
+
click.echo(dim(" No terminal required after this."))
|
|
2794
|
+
click.echo()
|
|
2795
|
+
|
|
2796
|
+
pmf_ok = False
|
|
2797
|
+
try:
|
|
2798
|
+
target = install_launchd(CDA_HOME)
|
|
2799
|
+
click.echo(f" {green('✓')} LaunchAgent: {target}")
|
|
2800
|
+
click.echo(f" {green('✓')} Loaded — CDA starts automatically on every login")
|
|
2801
|
+
pmf_ok = True
|
|
2802
|
+
except PMFKernelError as exc:
|
|
2803
|
+
click.echo(f" {yellow('⚠')} LaunchAgent registration failed: {exc}")
|
|
2804
|
+
click.echo(yellow(" Fix PATH then run `cda pmf install` to retry."))
|
|
2805
|
+
click.echo()
|
|
2806
|
+
|
|
2807
|
+
# ── Step 3: Sync ─────────────────────────────────────────────
|
|
2808
|
+
click.echo(bold(bar))
|
|
2809
|
+
click.echo(bold(" Step 3/4 — Sync"))
|
|
2810
|
+
click.echo(bold(bar))
|
|
2811
|
+
click.echo()
|
|
2812
|
+
|
|
2813
|
+
if skip_sync:
|
|
2814
|
+
click.echo(f" {yellow('↳')} Skipped (--skip-sync). Run `cda sync` when ready.")
|
|
2815
|
+
click.echo()
|
|
2816
|
+
else:
|
|
2817
|
+
click.echo(dim(" Scanning VS Code workspaceStorage and building cda.db."))
|
|
2818
|
+
click.echo(dim(" First run may take a few minutes depending on session history."))
|
|
2819
|
+
click.echo()
|
|
2820
|
+
|
|
2821
|
+
sync_failed = False
|
|
2822
|
+
stages = [
|
|
2823
|
+
("cda.pipeline.ingest", "Ingest — reading VS Code storage"),
|
|
2824
|
+
("cda.pipeline.reconstruct", "Reconstruct — building exchanges + FTS"),
|
|
2825
|
+
("cda.pipeline.extract", "Extract — behavioral signals + tokens"),
|
|
2826
|
+
("cda.pipeline.embed", "Embed — semantic intelligence layer"),
|
|
2827
|
+
]
|
|
2828
|
+
for module, label in stages:
|
|
2829
|
+
click.echo(yellow(f" → {label}"))
|
|
2830
|
+
result = subprocess.run([sys.executable, "-m", module], capture_output=False)
|
|
2831
|
+
if result.returncode != 0:
|
|
2832
|
+
click.echo(red(" ✗ Failed — sync incomplete"))
|
|
2833
|
+
sync_failed = True
|
|
2834
|
+
break
|
|
2835
|
+
click.echo(green(" ✓ Done"))
|
|
2836
|
+
click.echo()
|
|
2837
|
+
|
|
2838
|
+
if not sync_failed:
|
|
2839
|
+
click.echo(green(" ✓ Sync complete"))
|
|
2840
|
+
click.echo()
|
|
2841
|
+
|
|
2842
|
+
# ── Step 4: Up ───────────────────────────────────────────────
|
|
2843
|
+
click.echo(bold(bar))
|
|
2844
|
+
click.echo(bold(" Step 4/4 — Up"))
|
|
2845
|
+
click.echo(bold(bar))
|
|
2846
|
+
click.echo()
|
|
2847
|
+
click.echo(dim(" Starting all services through the PMF kernel."))
|
|
2848
|
+
click.echo(dim(" Each process is tracked, logged, and restartable via `cda pmf`."))
|
|
2849
|
+
click.echo()
|
|
2850
|
+
|
|
2851
|
+
for svc_id, opts, label in [
|
|
2852
|
+
("watcher", None, "Watcher daemon"),
|
|
2853
|
+
("ui", {"host": host, "port": port}, f"Web UI → {url}"),
|
|
2854
|
+
]:
|
|
2855
|
+
try:
|
|
2856
|
+
result = kernel.start_service(svc_id, options=opts)
|
|
2857
|
+
click.echo(f" {green('✓')} {label} pid={result['pid']}")
|
|
2858
|
+
except PMFKernelError as exc:
|
|
2859
|
+
msg = str(exc)
|
|
2860
|
+
if "already running" in msg.lower():
|
|
2861
|
+
click.echo(f" {green('✓')} {label} (already running)")
|
|
2862
|
+
else:
|
|
2863
|
+
click.echo(f" {yellow('⚠')} {label} {msg}")
|
|
2864
|
+
|
|
2865
|
+
click.echo()
|
|
2866
|
+
|
|
2867
|
+
if not no_browser:
|
|
2868
|
+
click.echo(dim(" Waiting for web UI..."))
|
|
2869
|
+
opened = wait_for_port_and_open_browser(url, host, port)
|
|
2870
|
+
if opened:
|
|
2871
|
+
click.echo(f" {green('✓')} Browser opened: {url}")
|
|
2872
|
+
else:
|
|
2873
|
+
click.echo(f" {yellow('⚠')} Server not responding yet — visit {url} manually")
|
|
2874
|
+
click.echo()
|
|
2875
|
+
|
|
2876
|
+
# ── Done ─────────────────────────────────────────────────────
|
|
2877
|
+
click.echo(bold(BAR))
|
|
2878
|
+
click.echo(bold(" Setup complete."))
|
|
2879
|
+
click.echo(bold(BAR))
|
|
2880
|
+
click.echo()
|
|
2881
|
+
if pmf_ok:
|
|
2882
|
+
click.echo(dim(" CDA starts automatically on every login via launchd."))
|
|
2883
|
+
click.echo(dim(" The watcher daemon keeps your session data in sync automatically."))
|
|
2884
|
+
click.echo(dim(f" Visit {url} any time to explore your data."))
|
|
2885
|
+
click.echo()
|
|
2886
|
+
click.echo(dim(" Useful commands:"))
|
|
2887
|
+
click.echo(dim(" cda check — full system health diagnostic"))
|
|
2888
|
+
click.echo(dim(" cda sync — re-ingest after significant new session activity"))
|
|
2889
|
+
click.echo(dim(" cda pmf services — view running services and their status"))
|
|
2890
|
+
click.echo(dim(" cda pmf uninstall — remove the auto-start LaunchAgent"))
|
|
2891
|
+
click.echo()
|
|
2892
|
+
|
|
2893
|
+
|
|
2649
2894
|
# ─────────────────────────────────────────────
|
|
2650
2895
|
# INIT
|
|
2651
2896
|
# ─────────────────────────────────────────────
|
|
2652
2897
|
|
|
2653
2898
|
@cli.command("init")
|
|
2654
2899
|
def init():
|
|
2655
|
-
"""First-run setup — create
|
|
2900
|
+
"""First-run setup — create ~/Library/goCosmix/apps/code-data-ark/ directory structure and validate environment."""
|
|
2656
2901
|
from cda.kernel.paths import (
|
|
2657
2902
|
CDA_HOME, DATA_DIR, RUN_DIR, LOG_DIR, QUEUE_DIR,
|
|
2658
2903
|
PMF_DIR, PMF_LOG_DIR, CONFIG_DIR, POLICY_FILE,
|
|
@@ -5,6 +5,32 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.0.6] - 2026-05-11
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **`~/Library/goCosmix/` home namespace** — all goCosmix apps share a unified `~/Library/goCosmix/` directory (macOS) or `~/.gocosmix/` (other). CDA now installs to `~/Library/goCosmix/apps/code-data-ark/` instead of `~/.cda/`. Provides a clean, organized home for all future goCosmix systems.
|
|
12
|
+
- **`GOCOSMIX_HOME`, `GOCOSMIX_APPS`, `GOCOSMIX_SYSTEM`** constants in `cda.kernel.paths` — shared namespace anchors for future goCosmix apps.
|
|
13
|
+
- **Auto PATH patching in `cda setup`** — detects where pip placed the `cda` binary and patches `~/.zprofile` if the bin dir is missing from PATH. Solves the macOS system Python `command not found` blocker.
|
|
14
|
+
- **`python3 -m cda` entry point** (`cda/__main__.py`) — bootstrapping fallback so users can run `python3 -m cda setup` before PATH is configured.
|
|
15
|
+
- **Legacy migration notice** — `cda setup` detects an existing `~/.cda/` and advises running `cda migrate-home`.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- `cda.kernel.paths.get_cda_home()` default changed from `~/.cda` to `~/Library/goCosmix/apps/code-data-ark` (macOS) / `~/.gocosmix/apps/code-data-ark` (other). `CDA_HOME` env var still overrides.
|
|
19
|
+
- `ensure_dirs()` now creates the full goCosmix namespace tree in addition to app-level dirs.
|
|
20
|
+
- README quickstart updated: install command is `python3 -m cda setup` as the safe default.
|
|
21
|
+
- `cda setup` Step 1 shows `+` for new dirs and `✓` for existing ones.
|
|
22
|
+
|
|
23
|
+
## [2.0.5] - 2026-05-11
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- **`cda setup`** — master onboarding command: init → pmf install → sync → up. Replaces the four-step manual process with a single command. Idempotent, safe to re-run. Accepts `--skip-sync` and `--no-browser`.
|
|
27
|
+
- **PMF-first architecture**: all background processes (watcher, web UI) start exclusively through the PMF kernel. `cda watch start` and `cda ui start` now display an advisory if the LaunchAgent is not installed.
|
|
28
|
+
- `_pmf_warn_if_not_installed()` helper — emitted before any background service start when the LaunchAgent plist is absent.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
- README quickstart simplified to two commands: `pip install code-data-ark` + `cda setup`
|
|
32
|
+
- Added PMF architecture diagram and process management reference to README
|
|
33
|
+
|
|
8
34
|
## [2.0.4] - 2026-05-11
|
|
9
35
|
|
|
10
36
|
### Added
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "code-data-ark"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.6"
|
|
8
8
|
description = "Code Data Ark — local observability and intelligence platform for VS Code + Copilot Chat sessions"
|
|
9
9
|
readme = "readme.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -52,10 +52,17 @@ The runtime is managed by an embedded process kernel (PMF) that supervises the w
|
|
|
52
52
|
pip install code-data-ark
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
> **macOS / system Python note**: pip installs the `cda` binary to `~/Library/Python/3.x/bin/` which is not on `PATH` by default. Use the fallback below — `cda setup` will fix PATH for you automatically:
|
|
56
|
+
>
|
|
57
|
+
> ```bash
|
|
58
|
+
> python3 -m cda setup
|
|
59
|
+
> ```
|
|
60
|
+
|
|
55
61
|
### Install with pipx
|
|
56
62
|
|
|
57
63
|
```bash
|
|
58
64
|
pipx install code-data-ark
|
|
65
|
+
# pipx automatically manages PATH — `cda setup` works immediately
|
|
59
66
|
```
|
|
60
67
|
|
|
61
68
|
### Install from source
|
|
@@ -74,52 +81,73 @@ pip install -e ".[dev]"
|
|
|
74
81
|
make install-dev
|
|
75
82
|
```
|
|
76
83
|
|
|
77
|
-
> The `cda` console command is installed into your
|
|
84
|
+
> The `cda` console command is installed into your Python environment's `bin` directory. If it isn't on PATH yet, use `python3 -m cda setup` — setup patches `~/.zprofile` automatically.
|
|
78
85
|
|
|
79
86
|
## ⚡ Quick Start
|
|
80
87
|
|
|
81
|
-
1. **Install**
|
|
82
|
-
|
|
83
88
|
```bash
|
|
84
89
|
pip install code-data-ark
|
|
90
|
+
python3 -m cda setup # use this if `cda` isn't on PATH yet
|
|
85
91
|
```
|
|
86
92
|
|
|
87
|
-
|
|
93
|
+
After the first run, `cda setup` patches `~/.zprofile` so `cda` is on PATH in every new terminal.
|
|
88
94
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
95
|
+
`cda setup` runs four steps in sequence:
|
|
96
|
+
|
|
97
|
+
| Step | What it does |
|
|
98
|
+
|------|-------------|
|
|
99
|
+
| **1. Init** | Creates `~/Library/goCosmix/apps/code-data-ark/` — all app data in one organized namespace. Also patches `~/.zprofile` if `cda` isn't on PATH yet. |
|
|
100
|
+
| **2. PMF install** | Registers a macOS LaunchAgent — CDA starts automatically on every login via `cda pmf up` |
|
|
101
|
+
| **3. Sync** | Ingests all VS Code + Copilot session data into `cda.db` |
|
|
102
|
+
| **4. Up** | Starts the watcher daemon and web UI via the PMF kernel, opens browser |
|
|
92
103
|
|
|
93
|
-
|
|
104
|
+
All data lives in `~/Library/goCosmix/apps/code-data-ark/`. After setup, everything is managed by the **PMF kernel** — no terminal interaction required.
|
|
105
|
+
|
|
106
|
+
### Options
|
|
94
107
|
|
|
95
108
|
```bash
|
|
96
|
-
cda sync
|
|
109
|
+
cda setup --skip-sync # Skip initial ingest (run `cda sync` manually later)
|
|
110
|
+
cda setup --no-browser # Don't open browser when the UI starts
|
|
97
111
|
```
|
|
98
112
|
|
|
99
|
-
|
|
113
|
+
### After setup
|
|
100
114
|
|
|
101
115
|
```bash
|
|
102
|
-
cda
|
|
116
|
+
cda check # Full system health diagnostic
|
|
117
|
+
cda sync # Re-ingest after significant new session activity
|
|
118
|
+
cda pmf services # View all running services and their status
|
|
119
|
+
cda pmf uninstall # Remove the auto-start LaunchAgent registration
|
|
103
120
|
```
|
|
104
121
|
|
|
105
|
-
|
|
122
|
+
## 🔧 Process Management (PMF)
|
|
106
123
|
|
|
107
|
-
|
|
108
|
-
|
|
124
|
+
All background processes run through the embedded PMF kernel. The LaunchAgent is the entry point — nothing starts directly on the host outside of PMF.
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
launchd (login)
|
|
128
|
+
└─ cda pmf up
|
|
129
|
+
├─ PMF kernel → watcher daemon (cda.pipeline.watcher)
|
|
130
|
+
└─ PMF kernel → web UI server (cda.ui.web)
|
|
109
131
|
```
|
|
110
132
|
|
|
111
|
-
|
|
133
|
+
### PMF commands
|
|
112
134
|
|
|
113
135
|
```bash
|
|
114
|
-
cda
|
|
136
|
+
cda pmf services # List all services with status and PID
|
|
137
|
+
cda pmf start <service> # Start a service (watcher, ui, sync, reconstruct, embed-build)
|
|
138
|
+
cda pmf stop <service> # Stop a service
|
|
139
|
+
cda pmf restart <service> # Restart a service
|
|
140
|
+
cda pmf logs <service> # Tail the service log
|
|
141
|
+
cda pmf up # Start watcher + UI (opens browser) — same as launchd trigger
|
|
142
|
+
cda pmf install # Register LaunchAgent (done automatically by cda setup)
|
|
143
|
+
cda pmf uninstall # Remove LaunchAgent
|
|
115
144
|
```
|
|
116
145
|
|
|
117
146
|
## 🌐 Web UI
|
|
118
147
|
|
|
119
|
-
- **Background service
|
|
120
|
-
- **
|
|
121
|
-
- **
|
|
122
|
-
- **Foreground mode**: `cda serve`
|
|
148
|
+
- **Background service** (default after setup): managed by PMF, starts on login
|
|
149
|
+
- **Foreground mode**: `cda serve` — runs in the terminal, opens browser, Ctrl+C to stop
|
|
150
|
+
- **Access**: `http://127.0.0.1:10001`
|
|
123
151
|
|
|
124
152
|
The web UI includes:
|
|
125
153
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.0.6
|
code_data_ark-2.0.4/version
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.0.4
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|