@qelos/aidev 0.1.15 → 0.1.16

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.
@@ -1,3 +1,8 @@
1
+ # AIDEV_ENV_EXTEND: path to a shared/global env file loaded as the base for this file.
2
+ # Values in this file override the global one. Useful for sharing API keys across projects.
3
+ # Can also be set as a shell export (e.g. in ~/.zshrc) instead.
4
+ # AIDEV_ENV_EXTEND=~/.aidev.global
5
+
1
6
  # PROVIDER: clickup | jira
2
7
  PROVIDER=clickup
3
8
 
package/README.md CHANGED
@@ -102,6 +102,36 @@ aidev schedule set "*/30 * * * *"
102
102
 
103
103
  Run `aidev init` for an interactive setup, or create `.env.aidev` manually using `.env.aidev.example` as a template.
104
104
 
105
+ ### Global env file (`AIDEV_ENV_EXTEND`)
106
+
107
+ If you work across multiple projects, you can keep shared settings (API keys, agent list, etc.) in a single global file and reference it from each project's `.env.aidev`:
108
+
109
+ ```bash
110
+ # ~/.aidev.global
111
+ CLICKUP_API_KEY=pk_...
112
+ CLICKUP_TEAM_ID=123456
113
+ AGENTS=claude,cursor
114
+ ```
115
+
116
+ ```bash
117
+ # my-project/.env.aidev — project-specific values override the global ones
118
+ AIDEV_ENV_EXTEND=~/.aidev.global
119
+ CLICKUP_TAG=my-project
120
+ ```
121
+
122
+ **Priority order (highest → lowest):**
123
+
124
+ 1. Shell environment variables (e.g. set in `~/.zshrc`) — never overwritten
125
+ 2. Local `.env.aidev` values
126
+ 3. `AIDEV_ENV_EXTEND` file values (global base)
127
+
128
+ `AIDEV_ENV_EXTEND` can be set in two ways:
129
+
130
+ - **Per-project** — add `AIDEV_ENV_EXTEND=/path/to/file` inside `.env.aidev`
131
+ - **Shell-wide** — `export AIDEV_ENV_EXTEND=~/.aidev.global` in `~/.zshrc` (applies to every project automatically)
132
+
133
+ `aidev init` will ask for this path and pre-fill it if the variable is already in your shell environment.
134
+
105
135
  ### ClickUp
106
136
 
107
137
  | Variable | Default | Description |
@@ -127,6 +157,7 @@ Run `aidev init` for an interactive setup, or create `.env.aidev` manually using
127
157
 
128
158
  | Variable | Default | Description |
129
159
  |---|---|---|
160
+ | `AIDEV_ENV_EXTEND` | — | Path to a global env file loaded as the base for this project (see above) |
130
161
  | `AGENTS` | `claude,cursor` | Comma-separated list of agents in priority order |
131
162
  | `DEV_NOTES_MODE` | `smart` | When to ask for clarification (`smart` or `always`) |
132
163
  | `AIDEV_TRIGGER_WORD` | `aidev-continue` | Comment containing this word re-triggers a skipped task |
package/aidev.log CHANGED
@@ -2041,3 +2041,251 @@ hint: or --ff-only on the command line to override the configured default per
2041
2041
  hint: invocation.
2042
2042
  fatal: Need to specify how to reconcile divergent branches.
2043
2043
 
2044
+ 2026-03-08T11:33:24.688Z [warn] No aidev schedules found
2045
+ 2026-03-08T11:33:24.689Z [info] Use "aidev schedule set" to configure one.
2046
+ 2026-03-08T11:46:59.801Z [success] Launch Agent scheduled: */15 * * * *
2047
+ 2026-03-08T11:46:59.802Z [info] Plist: /Users/davidmeirlevy/Library/LaunchAgents/com.aidev.run.ba0bfc4f.plist
2048
+
2049
+ ────────────────────────────────────────────────────────────
2050
+ 2026-03-08T12:01:59.880Z [run] started
2051
+ ────────────────────────────────────────────────────────────
2052
+ 2026-03-08T12:01:59.930Z [info] Fetching tasks (filter: all)...
2053
+ 2026-03-08T12:02:00.273Z [info] Found 0 tagged task(s)
2054
+ 2026-03-08T12:02:00.273Z [success] Done. Processed: 0, Skipped: 0
2055
+
2056
+ ────────────────────────────────────────────────────────────
2057
+ 2026-03-08T12:17:00.424Z [run] started
2058
+ ────────────────────────────────────────────────────────────
2059
+ 2026-03-08T12:17:00.468Z [info] Fetching tasks (filter: all)...
2060
+ 2026-03-08T12:17:00.801Z [info] Found 0 tagged task(s)
2061
+ 2026-03-08T12:17:00.802Z [success] Done. Processed: 0, Skipped: 0
2062
+
2063
+ ────────────────────────────────────────────────────────────
2064
+ 2026-03-08T12:32:00.955Z [run] started
2065
+ ────────────────────────────────────────────────────────────
2066
+ 2026-03-08T12:32:00.993Z [info] Fetching tasks (filter: all)...
2067
+ 2026-03-08T12:32:01.263Z [info] Found 0 tagged task(s)
2068
+ 2026-03-08T12:32:01.264Z [success] Done. Processed: 0, Skipped: 0
2069
+
2070
+ ────────────────────────────────────────────────────────────
2071
+ 2026-03-08T12:47:01.399Z [run] started
2072
+ ────────────────────────────────────────────────────────────
2073
+ 2026-03-08T12:47:01.442Z [info] Fetching tasks (filter: all)...
2074
+ 2026-03-08T12:47:01.790Z [info] Found 0 tagged task(s)
2075
+ 2026-03-08T12:47:01.791Z [success] Done. Processed: 0, Skipped: 0
2076
+ 2026-03-08T12:51:24.133Z [info] Scheduled aidev jobs:
2077
+ 2026-03-08T13:00:20.831Z [warn] cursor clarification check failed — trying next runner
2078
+ 2026-03-08T13:00:20.833Z [warn] cursor clarification check failed — trying next runner
2079
+ 2026-03-08T13:00:20.833Z [warn] windsurf clarification check failed — trying next runner
2080
+ 2026-03-08T13:00:20.833Z [warn] Clarification check failed for all runners — proceeding without clarification
2081
+ 2026-03-08T13:00:20.833Z [warn] No AI runner available — skipping clarification check
2082
+ 2026-03-08T13:00:21.044Z [error] Cannot create branch "task123/fix-bug": expected to be on "main" but currently on "some-other-branch"
2083
+ 2026-03-08T13:00:21.208Z [error] Refusing to commit: expected branch "task123/fix-bug" but currently on "wrong-branch"
2084
+ 2026-03-08T13:00:21.252Z [error] Refusing to commit directly to protected branch "main"
2085
+ 2026-03-08T13:00:21.395Z [error] Refusing to push directly to protected branch "main"
2086
+ 2026-03-08T13:00:21.491Z [error] Refusing to push: current branch "task123/fix-bug" does not match target branch "task456/other-task"
2087
+ 2026-03-08T13:00:23.019Z [error] git pull failed: From /var/folders/88/xzz9sxx15s13cmqq5_1k0t480000gn/T/aidev-bare-Fx3IV1
2088
+ * branch main -> FETCH_HEAD
2089
+ hint: You have divergent branches and need to specify how to reconcile them.
2090
+ hint: You can do so by running one of the following commands sometime before
2091
+ hint: your next pull:
2092
+ hint:
2093
+ hint: git config pull.rebase false # merge
2094
+ hint: git config pull.rebase true # rebase
2095
+ hint: git config pull.ff only # fast-forward only
2096
+ hint:
2097
+ hint: You can replace "git config" with "git config --global" to set a default
2098
+ hint: preference for all repositories. You can also pass --rebase, --no-rebase,
2099
+ hint: or --ff-only on the command line to override the configured default per
2100
+ hint: invocation.
2101
+ fatal: Need to specify how to reconcile divergent branches.
2102
+
2103
+ 2026-03-08T13:00:30.556Z [warn] cursor clarification check failed — trying next runner
2104
+ 2026-03-08T13:00:30.557Z [warn] cursor clarification check failed — trying next runner
2105
+ 2026-03-08T13:00:30.557Z [warn] windsurf clarification check failed — trying next runner
2106
+ 2026-03-08T13:00:30.558Z [warn] Clarification check failed for all runners — proceeding without clarification
2107
+ 2026-03-08T13:00:30.558Z [warn] No AI runner available — skipping clarification check
2108
+ 2026-03-08T13:00:30.746Z [error] Cannot create branch "task123/fix-bug": expected to be on "main" but currently on "some-other-branch"
2109
+ 2026-03-08T13:00:30.914Z [error] Refusing to commit: expected branch "task123/fix-bug" but currently on "wrong-branch"
2110
+ 2026-03-08T13:00:30.958Z [error] Refusing to commit directly to protected branch "main"
2111
+ 2026-03-08T13:00:31.094Z [error] Refusing to push directly to protected branch "main"
2112
+ 2026-03-08T13:00:31.183Z [error] Refusing to push: current branch "task123/fix-bug" does not match target branch "task456/other-task"
2113
+ 2026-03-08T13:00:32.681Z [error] git pull failed: From /var/folders/88/xzz9sxx15s13cmqq5_1k0t480000gn/T/aidev-bare-Udss4C
2114
+ * branch main -> FETCH_HEAD
2115
+ hint: You have divergent branches and need to specify how to reconcile them.
2116
+ hint: You can do so by running one of the following commands sometime before
2117
+ hint: your next pull:
2118
+ hint:
2119
+ hint: git config pull.rebase false # merge
2120
+ hint: git config pull.rebase true # rebase
2121
+ hint: git config pull.ff only # fast-forward only
2122
+ hint:
2123
+ hint: You can replace "git config" with "git config --global" to set a default
2124
+ hint: preference for all repositories. You can also pass --rebase, --no-rebase,
2125
+ hint: or --ff-only on the command line to override the configured default per
2126
+ hint: invocation.
2127
+ fatal: Need to specify how to reconcile divergent branches.
2128
+
2129
+ 2026-03-08T13:01:38.349Z [warn] cursor clarification check failed — trying next runner
2130
+ 2026-03-08T13:01:38.351Z [warn] cursor clarification check failed — trying next runner
2131
+ 2026-03-08T13:01:38.351Z [warn] windsurf clarification check failed — trying next runner
2132
+ 2026-03-08T13:01:38.351Z [warn] Clarification check failed for all runners — proceeding without clarification
2133
+ 2026-03-08T13:01:38.352Z [warn] No AI runner available — skipping clarification check
2134
+ 2026-03-08T13:01:38.550Z [error] Cannot create branch "task123/fix-bug": expected to be on "main" but currently on "some-other-branch"
2135
+ 2026-03-08T13:01:38.711Z [error] Refusing to commit: expected branch "task123/fix-bug" but currently on "wrong-branch"
2136
+ 2026-03-08T13:01:38.758Z [error] Refusing to commit directly to protected branch "main"
2137
+ 2026-03-08T13:01:38.911Z [error] Refusing to push directly to protected branch "main"
2138
+ 2026-03-08T13:01:39.009Z [error] Refusing to push: current branch "task123/fix-bug" does not match target branch "task456/other-task"
2139
+ 2026-03-08T13:01:40.543Z [error] git pull failed: From /var/folders/88/xzz9sxx15s13cmqq5_1k0t480000gn/T/aidev-bare-f1BjS2
2140
+ * branch main -> FETCH_HEAD
2141
+ hint: You have divergent branches and need to specify how to reconcile them.
2142
+ hint: You can do so by running one of the following commands sometime before
2143
+ hint: your next pull:
2144
+ hint:
2145
+ hint: git config pull.rebase false # merge
2146
+ hint: git config pull.rebase true # rebase
2147
+ hint: git config pull.ff only # fast-forward only
2148
+ hint:
2149
+ hint: You can replace "git config" with "git config --global" to set a default
2150
+ hint: preference for all repositories. You can also pass --rebase, --no-rebase,
2151
+ hint: or --ff-only on the command line to override the configured default per
2152
+ hint: invocation.
2153
+ fatal: Need to specify how to reconcile divergent branches.
2154
+
2155
+
2156
+ ────────────────────────────────────────────────────────────
2157
+ 2026-03-08T13:02:01.936Z [run] started
2158
+ ────────────────────────────────────────────────────────────
2159
+ 2026-03-08T13:02:01.975Z [info] Fetching tasks (filter: all)...
2160
+ 2026-03-08T13:02:02.460Z [info] Found 0 tagged task(s)
2161
+ 2026-03-08T13:02:02.461Z [success] Done. Processed: 0, Skipped: 0
2162
+ 2026-03-08T13:06:52.004Z [warn] cursor clarification check failed — trying next runner
2163
+ 2026-03-08T13:06:52.005Z [warn] cursor clarification check failed — trying next runner
2164
+ 2026-03-08T13:06:52.005Z [warn] windsurf clarification check failed — trying next runner
2165
+ 2026-03-08T13:06:52.005Z [warn] Clarification check failed for all runners — proceeding without clarification
2166
+ 2026-03-08T13:06:52.006Z [warn] No AI runner available — skipping clarification check
2167
+ 2026-03-08T13:06:52.208Z [error] Cannot create branch "task123/fix-bug": expected to be on "main" but currently on "some-other-branch"
2168
+ 2026-03-08T13:06:52.392Z [error] Refusing to commit: expected branch "task123/fix-bug" but currently on "wrong-branch"
2169
+ 2026-03-08T13:06:52.435Z [error] Refusing to commit directly to protected branch "main"
2170
+ 2026-03-08T13:06:52.577Z [error] Refusing to push directly to protected branch "main"
2171
+ 2026-03-08T13:06:52.672Z [error] Refusing to push: current branch "task123/fix-bug" does not match target branch "task456/other-task"
2172
+ 2026-03-08T13:06:54.196Z [error] git pull failed: From /var/folders/88/xzz9sxx15s13cmqq5_1k0t480000gn/T/aidev-bare-1gQyz2
2173
+ * branch main -> FETCH_HEAD
2174
+ hint: You have divergent branches and need to specify how to reconcile them.
2175
+ hint: You can do so by running one of the following commands sometime before
2176
+ hint: your next pull:
2177
+ hint:
2178
+ hint: git config pull.rebase false # merge
2179
+ hint: git config pull.rebase true # rebase
2180
+ hint: git config pull.ff only # fast-forward only
2181
+ hint:
2182
+ hint: You can replace "git config" with "git config --global" to set a default
2183
+ hint: preference for all repositories. You can also pass --rebase, --no-rebase,
2184
+ hint: or --ff-only on the command line to override the configured default per
2185
+ hint: invocation.
2186
+ fatal: Need to specify how to reconcile divergent branches.
2187
+
2188
+ 2026-03-08T13:07:58.188Z [warn] cursor clarification check failed — trying next runner
2189
+ 2026-03-08T13:07:58.192Z [warn] cursor clarification check failed — trying next runner
2190
+ 2026-03-08T13:07:58.192Z [warn] windsurf clarification check failed — trying next runner
2191
+ 2026-03-08T13:07:58.192Z [warn] Clarification check failed for all runners — proceeding without clarification
2192
+ 2026-03-08T13:07:58.192Z [warn] No AI runner available — skipping clarification check
2193
+ 2026-03-08T13:07:58.447Z [error] Cannot create branch "task123/fix-bug": expected to be on "main" but currently on "some-other-branch"
2194
+ 2026-03-08T13:07:58.630Z [error] Refusing to commit: expected branch "task123/fix-bug" but currently on "wrong-branch"
2195
+ 2026-03-08T13:07:58.675Z [error] Refusing to commit directly to protected branch "main"
2196
+ 2026-03-08T13:07:58.822Z [error] Refusing to push directly to protected branch "main"
2197
+ 2026-03-08T13:07:58.924Z [error] Refusing to push: current branch "task123/fix-bug" does not match target branch "task456/other-task"
2198
+ 2026-03-08T13:08:00.510Z [error] git pull failed: From /var/folders/88/xzz9sxx15s13cmqq5_1k0t480000gn/T/aidev-bare-J0Too3
2199
+ * branch main -> FETCH_HEAD
2200
+ hint: You have divergent branches and need to specify how to reconcile them.
2201
+ hint: You can do so by running one of the following commands sometime before
2202
+ hint: your next pull:
2203
+ hint:
2204
+ hint: git config pull.rebase false # merge
2205
+ hint: git config pull.rebase true # rebase
2206
+ hint: git config pull.ff only # fast-forward only
2207
+ hint:
2208
+ hint: You can replace "git config" with "git config --global" to set a default
2209
+ hint: preference for all repositories. You can also pass --rebase, --no-rebase,
2210
+ hint: or --ff-only on the command line to override the configured default per
2211
+ hint: invocation.
2212
+ fatal: Need to specify how to reconcile divergent branches.
2213
+
2214
+ 2026-03-08T13:10:00.581Z [warn] cursor clarification check failed — trying next runner
2215
+ 2026-03-08T13:10:00.583Z [warn] cursor clarification check failed — trying next runner
2216
+ 2026-03-08T13:10:00.583Z [warn] windsurf clarification check failed — trying next runner
2217
+ 2026-03-08T13:10:00.583Z [warn] Clarification check failed for all runners — proceeding without clarification
2218
+ 2026-03-08T13:10:00.583Z [warn] No AI runner available — skipping clarification check
2219
+ 2026-03-08T13:10:00.793Z [error] Cannot create branch "task123/fix-bug": expected to be on "main" but currently on "some-other-branch"
2220
+ 2026-03-08T13:10:00.959Z [error] Refusing to commit: expected branch "task123/fix-bug" but currently on "wrong-branch"
2221
+ 2026-03-08T13:10:01.003Z [error] Refusing to commit directly to protected branch "main"
2222
+ 2026-03-08T13:10:01.137Z [error] Refusing to push directly to protected branch "main"
2223
+ 2026-03-08T13:10:01.232Z [error] Refusing to push: current branch "task123/fix-bug" does not match target branch "task456/other-task"
2224
+ 2026-03-08T13:10:02.708Z [error] git pull failed: From /var/folders/88/xzz9sxx15s13cmqq5_1k0t480000gn/T/aidev-bare-3syyjI
2225
+ * branch main -> FETCH_HEAD
2226
+ hint: You have divergent branches and need to specify how to reconcile them.
2227
+ hint: You can do so by running one of the following commands sometime before
2228
+ hint: your next pull:
2229
+ hint:
2230
+ hint: git config pull.rebase false # merge
2231
+ hint: git config pull.rebase true # rebase
2232
+ hint: git config pull.ff only # fast-forward only
2233
+ hint:
2234
+ hint: You can replace "git config" with "git config --global" to set a default
2235
+ hint: preference for all repositories. You can also pass --rebase, --no-rebase,
2236
+ hint: or --ff-only on the command line to override the configured default per
2237
+ hint: invocation.
2238
+ fatal: Need to specify how to reconcile divergent branches.
2239
+
2240
+ 2026-03-08T13:10:09.408Z [warn] cursor clarification check failed — trying next runner
2241
+ 2026-03-08T13:10:09.410Z [warn] cursor clarification check failed — trying next runner
2242
+ 2026-03-08T13:10:09.410Z [warn] windsurf clarification check failed — trying next runner
2243
+ 2026-03-08T13:10:09.410Z [warn] Clarification check failed for all runners — proceeding without clarification
2244
+ 2026-03-08T13:10:09.410Z [warn] No AI runner available — skipping clarification check
2245
+ 2026-03-08T13:10:09.619Z [error] Cannot create branch "task123/fix-bug": expected to be on "main" but currently on "some-other-branch"
2246
+ 2026-03-08T13:10:09.791Z [error] Refusing to commit: expected branch "task123/fix-bug" but currently on "wrong-branch"
2247
+ 2026-03-08T13:10:09.842Z [error] Refusing to commit directly to protected branch "main"
2248
+ 2026-03-08T13:10:09.991Z [error] Refusing to push directly to protected branch "main"
2249
+ 2026-03-08T13:10:10.084Z [error] Refusing to push: current branch "task123/fix-bug" does not match target branch "task456/other-task"
2250
+ 2026-03-08T13:10:11.637Z [error] git pull failed: From /var/folders/88/xzz9sxx15s13cmqq5_1k0t480000gn/T/aidev-bare-acG5Yx
2251
+ * branch main -> FETCH_HEAD
2252
+ hint: You have divergent branches and need to specify how to reconcile them.
2253
+ hint: You can do so by running one of the following commands sometime before
2254
+ hint: your next pull:
2255
+ hint:
2256
+ hint: git config pull.rebase false # merge
2257
+ hint: git config pull.rebase true # rebase
2258
+ hint: git config pull.ff only # fast-forward only
2259
+ hint:
2260
+ hint: You can replace "git config" with "git config --global" to set a default
2261
+ hint: preference for all repositories. You can also pass --rebase, --no-rebase,
2262
+ hint: or --ff-only on the command line to override the configured default per
2263
+ hint: invocation.
2264
+ fatal: Need to specify how to reconcile divergent branches.
2265
+
2266
+ 2026-03-08T13:10:21.197Z [warn] cursor clarification check failed — trying next runner
2267
+ 2026-03-08T13:10:21.198Z [warn] cursor clarification check failed — trying next runner
2268
+ 2026-03-08T13:10:21.198Z [warn] windsurf clarification check failed — trying next runner
2269
+ 2026-03-08T13:10:21.198Z [warn] Clarification check failed for all runners — proceeding without clarification
2270
+ 2026-03-08T13:10:21.199Z [warn] No AI runner available — skipping clarification check
2271
+ 2026-03-08T13:10:21.387Z [error] Cannot create branch "task123/fix-bug": expected to be on "main" but currently on "some-other-branch"
2272
+ 2026-03-08T13:10:21.547Z [error] Refusing to commit: expected branch "task123/fix-bug" but currently on "wrong-branch"
2273
+ 2026-03-08T13:10:21.589Z [error] Refusing to commit directly to protected branch "main"
2274
+ 2026-03-08T13:10:21.724Z [error] Refusing to push directly to protected branch "main"
2275
+ 2026-03-08T13:10:21.812Z [error] Refusing to push: current branch "task123/fix-bug" does not match target branch "task456/other-task"
2276
+ 2026-03-08T13:10:23.269Z [error] git pull failed: From /var/folders/88/xzz9sxx15s13cmqq5_1k0t480000gn/T/aidev-bare-EpYZOl
2277
+ * branch main -> FETCH_HEAD
2278
+ hint: You have divergent branches and need to specify how to reconcile them.
2279
+ hint: You can do so by running one of the following commands sometime before
2280
+ hint: your next pull:
2281
+ hint:
2282
+ hint: git config pull.rebase false # merge
2283
+ hint: git config pull.rebase true # rebase
2284
+ hint: git config pull.ff only # fast-forward only
2285
+ hint:
2286
+ hint: You can replace "git config" with "git config --global" to set a default
2287
+ hint: preference for all repositories. You can also pass --rebase, --no-rebase,
2288
+ hint: or --ff-only on the command line to override the configured default per
2289
+ hint: invocation.
2290
+ fatal: Need to specify how to reconcile divergent branches.
2291
+
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,272 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const node_test_1 = require("node:test");
40
+ const strict_1 = __importDefault(require("node:assert/strict"));
41
+ const node_child_process_1 = require("node:child_process");
42
+ const fs = __importStar(require("node:fs"));
43
+ const os = __importStar(require("node:os"));
44
+ const path = __importStar(require("node:path"));
45
+ const config_1 = require("../config");
46
+ // ─── mergeNullDelimited ────────────────────────────────────────────────────────
47
+ (0, node_test_1.describe)('mergeNullDelimited', () => {
48
+ (0, node_test_1.beforeEach)(() => {
49
+ delete process.env['__TEST_MERGE_A'];
50
+ delete process.env['__TEST_MERGE_B'];
51
+ delete process.env['__TEST_MERGE_EXISTING'];
52
+ });
53
+ (0, node_test_1.afterEach)(() => {
54
+ delete process.env['__TEST_MERGE_A'];
55
+ delete process.env['__TEST_MERGE_B'];
56
+ delete process.env['__TEST_MERGE_EXISTING'];
57
+ });
58
+ (0, node_test_1.it)('sets new variables from null-delimited env output', () => {
59
+ (0, config_1.mergeNullDelimited)('__TEST_MERGE_A=hello\0__TEST_MERGE_B=world\0');
60
+ strict_1.default.equal(process.env['__TEST_MERGE_A'], 'hello');
61
+ strict_1.default.equal(process.env['__TEST_MERGE_B'], 'world');
62
+ });
63
+ (0, node_test_1.it)('does not overwrite variables already in process.env', () => {
64
+ process.env['__TEST_MERGE_EXISTING'] = 'original';
65
+ (0, config_1.mergeNullDelimited)('__TEST_MERGE_EXISTING=overwritten\0');
66
+ strict_1.default.equal(process.env['__TEST_MERGE_EXISTING'], 'original');
67
+ });
68
+ (0, node_test_1.it)('handles values containing = signs', () => {
69
+ (0, config_1.mergeNullDelimited)('__TEST_MERGE_A=a=b=c\0');
70
+ strict_1.default.equal(process.env['__TEST_MERGE_A'], 'a=b=c');
71
+ });
72
+ (0, node_test_1.it)('skips entries with no = sign', () => {
73
+ (0, config_1.mergeNullDelimited)('NOEQUALS\0__TEST_MERGE_A=ok\0');
74
+ strict_1.default.equal(process.env['__TEST_MERGE_A'], 'ok');
75
+ });
76
+ (0, node_test_1.it)('handles empty string without throwing', () => {
77
+ strict_1.default.doesNotThrow(() => (0, config_1.mergeNullDelimited)(''));
78
+ });
79
+ });
80
+ // ─── sourceShellProfile ────────────────────────────────────────────────────────
81
+ // These tests only run on POSIX (macOS / Linux) since Windows uses PowerShell + registry.
82
+ const itPosix = process.platform === 'win32' ? node_test_1.it.skip : node_test_1.it;
83
+ (0, node_test_1.describe)('sourceShellProfile', () => {
84
+ let tmpDir;
85
+ const testKey = '__AIDEV_PROFILE_TEST';
86
+ const testKey2 = '__AIDEV_PROFILE_TEST2';
87
+ (0, node_test_1.beforeEach)(() => {
88
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'aidev-profile-test-'));
89
+ delete process.env[testKey];
90
+ delete process.env[testKey2];
91
+ });
92
+ (0, node_test_1.afterEach)(() => {
93
+ fs.rmSync(tmpDir, { recursive: true, force: true });
94
+ delete process.env[testKey];
95
+ delete process.env[testKey2];
96
+ });
97
+ itPosix('picks up an exported variable from the profile', () => {
98
+ const rc = path.join(tmpDir, '.testrc');
99
+ fs.writeFileSync(rc, `export ${testKey}=from_profile\n`);
100
+ (0, config_1.sourceShellProfile)([rc]);
101
+ strict_1.default.equal(process.env[testKey], 'from_profile');
102
+ });
103
+ itPosix('profile with alias definitions does not break env sourcing', () => {
104
+ // Aliases are shell-internal and won't appear in process.env, but their
105
+ // presence must not prevent exported variables from being captured.
106
+ const rc = path.join(tmpDir, '.testrc');
107
+ fs.writeFileSync(rc, `alias gst='git status'\nexport ${testKey}=alongside_alias\n`);
108
+ (0, config_1.sourceShellProfile)([rc]);
109
+ strict_1.default.equal(process.env[testKey], 'alongside_alias');
110
+ // Aliases are not environment variables — they must not leak into process.env
111
+ strict_1.default.equal(process.env['gst'], undefined);
112
+ });
113
+ itPosix('does not overwrite an already-set variable', () => {
114
+ process.env[testKey] = 'existing';
115
+ const rc = path.join(tmpDir, '.testrc');
116
+ fs.writeFileSync(rc, `export ${testKey}=from_profile\n`);
117
+ (0, config_1.sourceShellProfile)([rc]);
118
+ strict_1.default.equal(process.env[testKey], 'existing');
119
+ });
120
+ itPosix('sources multiple profile files in order', () => {
121
+ const rc1 = path.join(tmpDir, '.rc1');
122
+ const rc2 = path.join(tmpDir, '.rc2');
123
+ fs.writeFileSync(rc1, `export ${testKey}=from_rc1\n`);
124
+ fs.writeFileSync(rc2, `export ${testKey2}=from_rc2\n`);
125
+ (0, config_1.sourceShellProfile)([rc1, rc2]);
126
+ strict_1.default.equal(process.env[testKey], 'from_rc1');
127
+ strict_1.default.equal(process.env[testKey2], 'from_rc2');
128
+ });
129
+ itPosix('silently ignores non-existent profile files', () => {
130
+ const missing = path.join(tmpDir, 'does_not_exist');
131
+ const rc = path.join(tmpDir, '.testrc');
132
+ fs.writeFileSync(rc, `export ${testKey}=still_works\n`);
133
+ strict_1.default.doesNotThrow(() => (0, config_1.sourceShellProfile)([missing, rc]));
134
+ strict_1.default.equal(process.env[testKey], 'still_works');
135
+ });
136
+ itPosix('exported variable propagates to child processes after sourcing', () => {
137
+ const rc = path.join(tmpDir, '.testrc');
138
+ fs.writeFileSync(rc, `export ${testKey}=child_test_value\n`);
139
+ (0, config_1.sourceShellProfile)([rc]);
140
+ strict_1.default.equal(process.env[testKey], 'child_test_value');
141
+ // Simulate how aidev spawns AI runners (claude, cursor, etc.) — they inherit process.env
142
+ const child = (0, node_child_process_1.spawnSync)(process.execPath, // node
143
+ ['-e', `process.stdout.write(process.env['${testKey}'] || 'NOT_FOUND')`], { encoding: 'utf8', env: process.env });
144
+ strict_1.default.equal(child.stdout, 'child_test_value');
145
+ });
146
+ itPosix('variable with special characters in value is captured correctly', () => {
147
+ const rc = path.join(tmpDir, '.testrc');
148
+ fs.writeFileSync(rc, `export ${testKey}="hello=world:path/to/thing"\n`);
149
+ (0, config_1.sourceShellProfile)([rc]);
150
+ strict_1.default.equal(process.env[testKey], 'hello=world:path/to/thing');
151
+ });
152
+ });
153
+ // ─── applyEnvFiles (AIDEV_ENV_EXTEND) ─────────────────────────────────────────
154
+ const EXT_A = '__AIDEV_EXT_A';
155
+ const EXT_B = '__AIDEV_EXT_B';
156
+ const EXT_C = '__AIDEV_EXT_C';
157
+ const EXT_ALL = [EXT_A, EXT_B, EXT_C, 'AIDEV_ENV_EXTEND'];
158
+ (0, node_test_1.describe)('applyEnvFiles', () => {
159
+ let tmpDir;
160
+ (0, node_test_1.beforeEach)(() => {
161
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'aidev-envfiles-'));
162
+ EXT_ALL.forEach((k) => delete process.env[k]);
163
+ });
164
+ (0, node_test_1.afterEach)(() => {
165
+ fs.rmSync(tmpDir, { recursive: true, force: true });
166
+ EXT_ALL.forEach((k) => delete process.env[k]);
167
+ });
168
+ (0, node_test_1.it)('loads variables from a local env file', () => {
169
+ const local = path.join(tmpDir, '.env.aidev');
170
+ fs.writeFileSync(local, `${EXT_A}=from_local\n`);
171
+ (0, config_1.applyEnvFiles)(local);
172
+ strict_1.default.equal(process.env[EXT_A], 'from_local');
173
+ });
174
+ (0, node_test_1.it)('loads global extend file values as base', () => {
175
+ const global = path.join(tmpDir, '.aidev.global');
176
+ fs.writeFileSync(global, `${EXT_A}=from_global\n${EXT_B}=global_only\n`);
177
+ const local = path.join(tmpDir, '.env.aidev');
178
+ fs.writeFileSync(local, `${EXT_A}=from_local\n`);
179
+ (0, config_1.applyEnvFiles)(local, global);
180
+ // local wins over global for EXT_A
181
+ strict_1.default.equal(process.env[EXT_A], 'from_local');
182
+ // global-only key is still loaded
183
+ strict_1.default.equal(process.env[EXT_B], 'global_only');
184
+ });
185
+ (0, node_test_1.it)('local .env.aidev AIDEV_ENV_EXTEND entry is used when no explicit path given', () => {
186
+ const global = path.join(tmpDir, '.aidev.global');
187
+ fs.writeFileSync(global, `${EXT_B}=from_global_via_local_ref\n`);
188
+ const local = path.join(tmpDir, '.env.aidev');
189
+ fs.writeFileSync(local, `AIDEV_ENV_EXTEND=${global}\n${EXT_A}=local_val\n`);
190
+ (0, config_1.applyEnvFiles)(local);
191
+ strict_1.default.equal(process.env[EXT_A], 'local_val');
192
+ strict_1.default.equal(process.env[EXT_B], 'from_global_via_local_ref');
193
+ });
194
+ (0, node_test_1.it)('process.env variables override both local and global', () => {
195
+ process.env[EXT_A] = 'shell_value';
196
+ const global = path.join(tmpDir, '.aidev.global');
197
+ fs.writeFileSync(global, `${EXT_A}=global_value\n`);
198
+ const local = path.join(tmpDir, '.env.aidev');
199
+ fs.writeFileSync(local, `${EXT_A}=local_value\n`);
200
+ (0, config_1.applyEnvFiles)(local, global);
201
+ strict_1.default.equal(process.env[EXT_A], 'shell_value');
202
+ });
203
+ (0, node_test_1.it)('explicit envExtend arg overrides AIDEV_ENV_EXTEND entry inside local file', () => {
204
+ const globalA = path.join(tmpDir, 'global_a');
205
+ fs.writeFileSync(globalA, `${EXT_A}=from_global_a\n`);
206
+ const globalB = path.join(tmpDir, 'global_b');
207
+ fs.writeFileSync(globalB, `${EXT_B}=from_global_b\n`);
208
+ const local = path.join(tmpDir, '.env.aidev');
209
+ // local points to globalA via AIDEV_ENV_EXTEND, but caller passes globalB explicitly
210
+ fs.writeFileSync(local, `AIDEV_ENV_EXTEND=${globalA}\n`);
211
+ (0, config_1.applyEnvFiles)(local, globalB);
212
+ // globalB was used (explicit wins)
213
+ strict_1.default.equal(process.env[EXT_B], 'from_global_b');
214
+ // globalA was NOT used
215
+ strict_1.default.equal(process.env[EXT_A], undefined);
216
+ });
217
+ (0, node_test_1.it)('silently skips a missing global file', () => {
218
+ const missing = path.join(tmpDir, 'does_not_exist');
219
+ const local = path.join(tmpDir, '.env.aidev');
220
+ fs.writeFileSync(local, `${EXT_A}=still_works\n`);
221
+ strict_1.default.doesNotThrow(() => (0, config_1.applyEnvFiles)(local, missing));
222
+ strict_1.default.equal(process.env[EXT_A], 'still_works');
223
+ });
224
+ (0, node_test_1.it)('works when no local file exists', () => {
225
+ const global = path.join(tmpDir, '.aidev.global');
226
+ fs.writeFileSync(global, `${EXT_A}=global_only\n`);
227
+ (0, config_1.applyEnvFiles)(undefined, global);
228
+ strict_1.default.equal(process.env[EXT_A], 'global_only');
229
+ });
230
+ (0, node_test_1.it)('vars loaded from global file propagate to child processes', () => {
231
+ const global = path.join(tmpDir, '.aidev.global');
232
+ fs.writeFileSync(global, `${EXT_C}=child_sees_this\n`);
233
+ (0, config_1.applyEnvFiles)(undefined, global);
234
+ strict_1.default.equal(process.env[EXT_C], 'child_sees_this');
235
+ const child = (0, node_child_process_1.spawnSync)(process.execPath, ['-e', `process.stdout.write(process.env['${EXT_C}'] || 'NOT_FOUND')`], { encoding: 'utf8', env: process.env });
236
+ strict_1.default.equal(child.stdout, 'child_sees_this');
237
+ });
238
+ (0, node_test_1.it)('resolves AIDEV_ENV_EXTEND relative path against local file directory', () => {
239
+ // global file sits alongside .env.aidev
240
+ const global = path.join(tmpDir, '.aidev.global');
241
+ fs.writeFileSync(global, `${EXT_B}=relative_global\n`);
242
+ const local = path.join(tmpDir, '.env.aidev');
243
+ // stored as a relative path in the local file
244
+ fs.writeFileSync(local, `AIDEV_ENV_EXTEND=.aidev.global\n${EXT_A}=local_val\n`);
245
+ (0, config_1.applyEnvFiles)(local);
246
+ strict_1.default.equal(process.env[EXT_A], 'local_val');
247
+ strict_1.default.equal(process.env[EXT_B], 'relative_global');
248
+ });
249
+ });
250
+ // ─── resolveEnvPath ────────────────────────────────────────────────────────────
251
+ (0, node_test_1.describe)('resolveEnvPath', () => {
252
+ (0, node_test_1.it)('returns absolute paths unchanged', () => {
253
+ strict_1.default.equal((0, config_1.resolveEnvPath)('/etc/aidev.global', '/any/base'), '/etc/aidev.global');
254
+ });
255
+ (0, node_test_1.it)('expands ~ to the home directory', () => {
256
+ const result = (0, config_1.resolveEnvPath)('~/.aidev.global', '/any/base');
257
+ strict_1.default.equal(result, path.join(os.homedir(), '.aidev.global'));
258
+ });
259
+ (0, node_test_1.it)('expands ~/subdir correctly', () => {
260
+ const result = (0, config_1.resolveEnvPath)('~/conf/aidev.global', '/any/base');
261
+ strict_1.default.equal(result, path.join(os.homedir(), 'conf/aidev.global'));
262
+ });
263
+ (0, node_test_1.it)('resolves relative paths against the supplied base', () => {
264
+ const result = (0, config_1.resolveEnvPath)('.aidev.global', '/projects/myapp');
265
+ strict_1.default.equal(result, '/projects/myapp/.aidev.global');
266
+ });
267
+ (0, node_test_1.it)('resolves ../ relative paths correctly', () => {
268
+ const result = (0, config_1.resolveEnvPath)('../shared/aidev.global', '/projects/myapp');
269
+ strict_1.default.equal(result, '/projects/shared/aidev.global');
270
+ });
271
+ });
272
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":"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"}
@@ -86,6 +86,7 @@ const baseAnswers = {
86
86
  devNotesMode: 'smart',
87
87
  triggerWord: 'aidev-continue',
88
88
  thinkingTag: '',
89
+ aidevEnvExtend: '',
89
90
  };
90
91
  (0, node_test_1.describe)('renderEnv', () => {
91
92
  (0, node_test_1.it)('writes non-empty values', () => {
@@ -116,6 +117,22 @@ const baseAnswers = {
116
117
  const out = (0, init_1.renderEnv)({ ...baseAnswers, githubRepo: '' });
117
118
  strict_1.default.ok(!out.includes('GITHUB_REPO'));
118
119
  });
120
+ (0, node_test_1.it)('omits AIDEV_ENV_EXTEND when empty', () => {
121
+ const out = (0, init_1.renderEnv)({ ...baseAnswers, aidevEnvExtend: '' });
122
+ strict_1.default.ok(!out.includes('AIDEV_ENV_EXTEND'));
123
+ });
124
+ (0, node_test_1.it)('includes AIDEV_ENV_EXTEND at the top when set', () => {
125
+ const out = (0, init_1.renderEnv)({ ...baseAnswers, aidevEnvExtend: '/home/user/.aidev.global' });
126
+ strict_1.default.ok(out.includes('AIDEV_ENV_EXTEND=/home/user/.aidev.global'));
127
+ // must appear before provider config
128
+ const extIdx = out.indexOf('AIDEV_ENV_EXTEND');
129
+ const provIdx = out.indexOf('PROVIDER=');
130
+ strict_1.default.ok(extIdx < provIdx, 'AIDEV_ENV_EXTEND should appear before PROVIDER');
131
+ });
132
+ (0, node_test_1.it)('includes a descriptive comment before AIDEV_ENV_EXTEND when set', () => {
133
+ const out = (0, init_1.renderEnv)({ ...baseAnswers, aidevEnvExtend: '/home/user/.aidev.global' });
134
+ strict_1.default.ok(out.includes('# Global env base'));
135
+ });
119
136
  });
120
137
  // ─── ensureGitignore ─────────────────────────────────────────────────────────
121
138
  function withTmpDir(fn) {