@viewportai/daemon 0.1.0

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 (350) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +157 -0
  3. package/bin/vpd.js +3 -0
  4. package/dist/adapters/claude.d.ts +119 -0
  5. package/dist/adapters/claude.d.ts.map +1 -0
  6. package/dist/adapters/claude.js +621 -0
  7. package/dist/adapters/claude.js.map +1 -0
  8. package/dist/adapters/codex-event-normalizers.d.ts +10 -0
  9. package/dist/adapters/codex-event-normalizers.d.ts.map +1 -0
  10. package/dist/adapters/codex-event-normalizers.js +208 -0
  11. package/dist/adapters/codex-event-normalizers.js.map +1 -0
  12. package/dist/adapters/codex-sdk-loader.d.ts +47 -0
  13. package/dist/adapters/codex-sdk-loader.d.ts.map +1 -0
  14. package/dist/adapters/codex-sdk-loader.js +19 -0
  15. package/dist/adapters/codex-sdk-loader.js.map +1 -0
  16. package/dist/adapters/codex.d.ts +56 -0
  17. package/dist/adapters/codex.d.ts.map +1 -0
  18. package/dist/adapters/codex.js +267 -0
  19. package/dist/adapters/codex.js.map +1 -0
  20. package/dist/adapters/gemini-cli.d.ts +49 -0
  21. package/dist/adapters/gemini-cli.d.ts.map +1 -0
  22. package/dist/adapters/gemini-cli.js +181 -0
  23. package/dist/adapters/gemini-cli.js.map +1 -0
  24. package/dist/adapters/pty.d.ts +56 -0
  25. package/dist/adapters/pty.d.ts.map +1 -0
  26. package/dist/adapters/pty.js +223 -0
  27. package/dist/adapters/pty.js.map +1 -0
  28. package/dist/agents/aider.d.ts +9 -0
  29. package/dist/agents/aider.d.ts.map +1 -0
  30. package/dist/agents/aider.js +37 -0
  31. package/dist/agents/aider.js.map +1 -0
  32. package/dist/agents/built-in.d.ts +4 -0
  33. package/dist/agents/built-in.d.ts.map +1 -0
  34. package/dist/agents/built-in.js +6 -0
  35. package/dist/agents/built-in.js.map +1 -0
  36. package/dist/agents/claude.d.ts +12 -0
  37. package/dist/agents/claude.d.ts.map +1 -0
  38. package/dist/agents/claude.js +93 -0
  39. package/dist/agents/claude.js.map +1 -0
  40. package/dist/agents/codex.d.ts +6 -0
  41. package/dist/agents/codex.d.ts.map +1 -0
  42. package/dist/agents/codex.js +64 -0
  43. package/dist/agents/codex.js.map +1 -0
  44. package/dist/agents/command-detection.d.ts +6 -0
  45. package/dist/agents/command-detection.d.ts.map +1 -0
  46. package/dist/agents/command-detection.js +12 -0
  47. package/dist/agents/command-detection.js.map +1 -0
  48. package/dist/agents/gemini.d.ts +6 -0
  49. package/dist/agents/gemini.d.ts.map +1 -0
  50. package/dist/agents/gemini.js +36 -0
  51. package/dist/agents/gemini.js.map +1 -0
  52. package/dist/cli/agent-commands.d.ts +2 -0
  53. package/dist/cli/agent-commands.d.ts.map +1 -0
  54. package/dist/cli/agent-commands.js +87 -0
  55. package/dist/cli/agent-commands.js.map +1 -0
  56. package/dist/cli/args.d.ts +9 -0
  57. package/dist/cli/args.d.ts.map +1 -0
  58. package/dist/cli/args.js +34 -0
  59. package/dist/cli/args.js.map +1 -0
  60. package/dist/cli/command-shared.d.ts +53 -0
  61. package/dist/cli/command-shared.d.ts.map +1 -0
  62. package/dist/cli/command-shared.js +239 -0
  63. package/dist/cli/command-shared.js.map +1 -0
  64. package/dist/cli/commands.d.ts +20 -0
  65. package/dist/cli/commands.d.ts.map +1 -0
  66. package/dist/cli/commands.js +20 -0
  67. package/dist/cli/commands.js.map +1 -0
  68. package/dist/cli/daemon-client.d.ts +30 -0
  69. package/dist/cli/daemon-client.d.ts.map +1 -0
  70. package/dist/cli/daemon-client.js +161 -0
  71. package/dist/cli/daemon-client.js.map +1 -0
  72. package/dist/cli/daemon-lifecycle.d.ts +47 -0
  73. package/dist/cli/daemon-lifecycle.d.ts.map +1 -0
  74. package/dist/cli/daemon-lifecycle.js +262 -0
  75. package/dist/cli/daemon-lifecycle.js.map +1 -0
  76. package/dist/cli/daemon-settings.d.ts +9 -0
  77. package/dist/cli/daemon-settings.d.ts.map +1 -0
  78. package/dist/cli/daemon-settings.js +168 -0
  79. package/dist/cli/daemon-settings.js.map +1 -0
  80. package/dist/cli/directory-commands.d.ts +4 -0
  81. package/dist/cli/directory-commands.d.ts.map +1 -0
  82. package/dist/cli/directory-commands.js +190 -0
  83. package/dist/cli/directory-commands.js.map +1 -0
  84. package/dist/cli/hook-command.d.ts +14 -0
  85. package/dist/cli/hook-command.d.ts.map +1 -0
  86. package/dist/cli/hook-command.js +96 -0
  87. package/dist/cli/hook-command.js.map +1 -0
  88. package/dist/cli/install-command.d.ts +2 -0
  89. package/dist/cli/install-command.d.ts.map +1 -0
  90. package/dist/cli/install-command.js +91 -0
  91. package/dist/cli/install-command.js.map +1 -0
  92. package/dist/cli/lifecycle-commands.d.ts +10 -0
  93. package/dist/cli/lifecycle-commands.d.ts.map +1 -0
  94. package/dist/cli/lifecycle-commands.js +524 -0
  95. package/dist/cli/lifecycle-commands.js.map +1 -0
  96. package/dist/cli/listen-target.d.ts +13 -0
  97. package/dist/cli/listen-target.d.ts.map +1 -0
  98. package/dist/cli/listen-target.js +102 -0
  99. package/dist/cli/listen-target.js.map +1 -0
  100. package/dist/cli/orchestration-commands.d.ts +8 -0
  101. package/dist/cli/orchestration-commands.d.ts.map +1 -0
  102. package/dist/cli/orchestration-commands.js +340 -0
  103. package/dist/cli/orchestration-commands.js.map +1 -0
  104. package/dist/cli/permission-commands.d.ts +2 -0
  105. package/dist/cli/permission-commands.d.ts.map +1 -0
  106. package/dist/cli/permission-commands.js +138 -0
  107. package/dist/cli/permission-commands.js.map +1 -0
  108. package/dist/cli/runtime-toolchain.d.ts +35 -0
  109. package/dist/cli/runtime-toolchain.d.ts.map +1 -0
  110. package/dist/cli/runtime-toolchain.js +184 -0
  111. package/dist/cli/runtime-toolchain.js.map +1 -0
  112. package/dist/cli/service-commands.d.ts +19 -0
  113. package/dist/cli/service-commands.d.ts.map +1 -0
  114. package/dist/cli/service-commands.js +273 -0
  115. package/dist/cli/service-commands.js.map +1 -0
  116. package/dist/cli/session-commands.d.ts +3 -0
  117. package/dist/cli/session-commands.d.ts.map +1 -0
  118. package/dist/cli/session-commands.js +146 -0
  119. package/dist/cli/session-commands.js.map +1 -0
  120. package/dist/cli/setup-command.d.ts +12 -0
  121. package/dist/cli/setup-command.d.ts.map +1 -0
  122. package/dist/cli/setup-command.js +223 -0
  123. package/dist/cli/setup-command.js.map +1 -0
  124. package/dist/cli/supervisor-protocol.d.ts +20 -0
  125. package/dist/cli/supervisor-protocol.d.ts.map +1 -0
  126. package/dist/cli/supervisor-protocol.js +5 -0
  127. package/dist/cli/supervisor-protocol.js.map +1 -0
  128. package/dist/cli/supervisor.d.ts +10 -0
  129. package/dist/cli/supervisor.d.ts.map +1 -0
  130. package/dist/cli/supervisor.js +218 -0
  131. package/dist/cli/supervisor.js.map +1 -0
  132. package/dist/cli/worktree-commands.d.ts +2 -0
  133. package/dist/cli/worktree-commands.d.ts.map +1 -0
  134. package/dist/cli/worktree-commands.js +250 -0
  135. package/dist/cli/worktree-commands.js.map +1 -0
  136. package/dist/cli/ws-client.d.ts +20 -0
  137. package/dist/cli/ws-client.d.ts.map +1 -0
  138. package/dist/cli/ws-client.js +103 -0
  139. package/dist/cli/ws-client.js.map +1 -0
  140. package/dist/core/agent-registry.d.ts +128 -0
  141. package/dist/core/agent-registry.d.ts.map +1 -0
  142. package/dist/core/agent-registry.js +131 -0
  143. package/dist/core/agent-registry.js.map +1 -0
  144. package/dist/core/config-schema.d.ts +77 -0
  145. package/dist/core/config-schema.d.ts.map +1 -0
  146. package/dist/core/config-schema.js +66 -0
  147. package/dist/core/config-schema.js.map +1 -0
  148. package/dist/core/config.d.ts +111 -0
  149. package/dist/core/config.d.ts.map +1 -0
  150. package/dist/core/config.js +244 -0
  151. package/dist/core/config.js.map +1 -0
  152. package/dist/core/daemon.d.ts +113 -0
  153. package/dist/core/daemon.d.ts.map +1 -0
  154. package/dist/core/daemon.js +197 -0
  155. package/dist/core/daemon.js.map +1 -0
  156. package/dist/core/discovered-sessions.d.ts +7 -0
  157. package/dist/core/discovered-sessions.d.ts.map +1 -0
  158. package/dist/core/discovered-sessions.js +39 -0
  159. package/dist/core/discovered-sessions.js.map +1 -0
  160. package/dist/core/error-codes.d.ts +31 -0
  161. package/dist/core/error-codes.d.ts.map +1 -0
  162. package/dist/core/error-codes.js +30 -0
  163. package/dist/core/error-codes.js.map +1 -0
  164. package/dist/core/errors.d.ts +16 -0
  165. package/dist/core/errors.d.ts.map +1 -0
  166. package/dist/core/errors.js +43 -0
  167. package/dist/core/errors.js.map +1 -0
  168. package/dist/core/events.d.ts +183 -0
  169. package/dist/core/events.d.ts.map +1 -0
  170. package/dist/core/events.js +61 -0
  171. package/dist/core/events.js.map +1 -0
  172. package/dist/core/interfaces.d.ts +115 -0
  173. package/dist/core/interfaces.d.ts.map +1 -0
  174. package/dist/core/interfaces.js +9 -0
  175. package/dist/core/interfaces.js.map +1 -0
  176. package/dist/core/logger.d.ts +11 -0
  177. package/dist/core/logger.d.ts.map +1 -0
  178. package/dist/core/logger.js +17 -0
  179. package/dist/core/logger.js.map +1 -0
  180. package/dist/core/metrics.d.ts +24 -0
  181. package/dist/core/metrics.d.ts.map +1 -0
  182. package/dist/core/metrics.js +32 -0
  183. package/dist/core/metrics.js.map +1 -0
  184. package/dist/core/output.d.ts +13 -0
  185. package/dist/core/output.d.ts.map +1 -0
  186. package/dist/core/output.js +22 -0
  187. package/dist/core/output.js.map +1 -0
  188. package/dist/core/permission-coordinator.d.ts +67 -0
  189. package/dist/core/permission-coordinator.d.ts.map +1 -0
  190. package/dist/core/permission-coordinator.js +209 -0
  191. package/dist/core/permission-coordinator.js.map +1 -0
  192. package/dist/core/session-manager.d.ts +121 -0
  193. package/dist/core/session-manager.d.ts.map +1 -0
  194. package/dist/core/session-manager.js +354 -0
  195. package/dist/core/session-manager.js.map +1 -0
  196. package/dist/core/session-state-file.d.ts +20 -0
  197. package/dist/core/session-state-file.d.ts.map +1 -0
  198. package/dist/core/session-state-file.js +49 -0
  199. package/dist/core/session-state-file.js.map +1 -0
  200. package/dist/core/types.d.ts +250 -0
  201. package/dist/core/types.d.ts.map +1 -0
  202. package/dist/core/types.js +88 -0
  203. package/dist/core/types.js.map +1 -0
  204. package/dist/directories/manager.d.ts +32 -0
  205. package/dist/directories/manager.d.ts.map +1 -0
  206. package/dist/directories/manager.js +86 -0
  207. package/dist/directories/manager.js.map +1 -0
  208. package/dist/discovery/claude.d.ts +29 -0
  209. package/dist/discovery/claude.d.ts.map +1 -0
  210. package/dist/discovery/claude.js +55 -0
  211. package/dist/discovery/claude.js.map +1 -0
  212. package/dist/discovery/codex.d.ts +11 -0
  213. package/dist/discovery/codex.d.ts.map +1 -0
  214. package/dist/discovery/codex.js +365 -0
  215. package/dist/discovery/codex.js.map +1 -0
  216. package/dist/discovery/gemini.d.ts +15 -0
  217. package/dist/discovery/gemini.d.ts.map +1 -0
  218. package/dist/discovery/gemini.js +151 -0
  219. package/dist/discovery/gemini.js.map +1 -0
  220. package/dist/discovery/jsonl-reader.d.ts +122 -0
  221. package/dist/discovery/jsonl-reader.d.ts.map +1 -0
  222. package/dist/discovery/jsonl-reader.js +622 -0
  223. package/dist/discovery/jsonl-reader.js.map +1 -0
  224. package/dist/discovery/watcher.d.ts +29 -0
  225. package/dist/discovery/watcher.d.ts.map +1 -0
  226. package/dist/discovery/watcher.js +383 -0
  227. package/dist/discovery/watcher.js.map +1 -0
  228. package/dist/hooks/index.d.ts +10 -0
  229. package/dist/hooks/index.d.ts.map +1 -0
  230. package/dist/hooks/index.js +8 -0
  231. package/dist/hooks/index.js.map +1 -0
  232. package/dist/hooks/installers/base.d.ts +27 -0
  233. package/dist/hooks/installers/base.d.ts.map +1 -0
  234. package/dist/hooks/installers/base.js +9 -0
  235. package/dist/hooks/installers/base.js.map +1 -0
  236. package/dist/hooks/installers/claude.d.ts +18 -0
  237. package/dist/hooks/installers/claude.d.ts.map +1 -0
  238. package/dist/hooks/installers/claude.js +120 -0
  239. package/dist/hooks/installers/claude.js.map +1 -0
  240. package/dist/hooks/router.d.ts +63 -0
  241. package/dist/hooks/router.d.ts.map +1 -0
  242. package/dist/hooks/router.js +259 -0
  243. package/dist/hooks/router.js.map +1 -0
  244. package/dist/hooks/supervision.d.ts +27 -0
  245. package/dist/hooks/supervision.d.ts.map +1 -0
  246. package/dist/hooks/supervision.js +67 -0
  247. package/dist/hooks/supervision.js.map +1 -0
  248. package/dist/hooks/types.d.ts +171 -0
  249. package/dist/hooks/types.d.ts.map +1 -0
  250. package/dist/hooks/types.js +148 -0
  251. package/dist/hooks/types.js.map +1 -0
  252. package/dist/index.d.ts +17 -0
  253. package/dist/index.d.ts.map +1 -0
  254. package/dist/index.js +117 -0
  255. package/dist/index.js.map +1 -0
  256. package/dist/permissions/engine.d.ts +23 -0
  257. package/dist/permissions/engine.d.ts.map +1 -0
  258. package/dist/permissions/engine.js +43 -0
  259. package/dist/permissions/engine.js.map +1 -0
  260. package/dist/plugins/loader.d.ts +44 -0
  261. package/dist/plugins/loader.d.ts.map +1 -0
  262. package/dist/plugins/loader.js +177 -0
  263. package/dist/plugins/loader.js.map +1 -0
  264. package/dist/server/auth.d.ts +32 -0
  265. package/dist/server/auth.d.ts.map +1 -0
  266. package/dist/server/auth.js +78 -0
  267. package/dist/server/auth.js.map +1 -0
  268. package/dist/server/discovered-watch-key.d.ts +5 -0
  269. package/dist/server/discovered-watch-key.d.ts.map +1 -0
  270. package/dist/server/discovered-watch-key.js +31 -0
  271. package/dist/server/discovered-watch-key.js.map +1 -0
  272. package/dist/server/hello-builder.d.ts +17 -0
  273. package/dist/server/hello-builder.d.ts.map +1 -0
  274. package/dist/server/hello-builder.js +71 -0
  275. package/dist/server/hello-builder.js.map +1 -0
  276. package/dist/server/http-server.d.ts +30 -0
  277. package/dist/server/http-server.d.ts.map +1 -0
  278. package/dist/server/http-server.js +561 -0
  279. package/dist/server/http-server.js.map +1 -0
  280. package/dist/server/message-normalizers.d.ts +11 -0
  281. package/dist/server/message-normalizers.d.ts.map +1 -0
  282. package/dist/server/message-normalizers.js +104 -0
  283. package/dist/server/message-normalizers.js.map +1 -0
  284. package/dist/server/pairing-offers.d.ts +78 -0
  285. package/dist/server/pairing-offers.d.ts.map +1 -0
  286. package/dist/server/pairing-offers.js +502 -0
  287. package/dist/server/pairing-offers.js.map +1 -0
  288. package/dist/server/rate-limiter.d.ts +21 -0
  289. package/dist/server/rate-limiter.d.ts.map +1 -0
  290. package/dist/server/rate-limiter.js +61 -0
  291. package/dist/server/rate-limiter.js.map +1 -0
  292. package/dist/server/ring-buffer.d.ts +34 -0
  293. package/dist/server/ring-buffer.d.ts.map +1 -0
  294. package/dist/server/ring-buffer.js +73 -0
  295. package/dist/server/ring-buffer.js.map +1 -0
  296. package/dist/server/security.d.ts +22 -0
  297. package/dist/server/security.d.ts.map +1 -0
  298. package/dist/server/security.js +123 -0
  299. package/dist/server/security.js.map +1 -0
  300. package/dist/server/ws-command-handlers.d.ts +25 -0
  301. package/dist/server/ws-command-handlers.d.ts.map +1 -0
  302. package/dist/server/ws-command-handlers.js +218 -0
  303. package/dist/server/ws-command-handlers.js.map +1 -0
  304. package/dist/server/ws-daemon-event-bridge.d.ts +22 -0
  305. package/dist/server/ws-daemon-event-bridge.d.ts.map +1 -0
  306. package/dist/server/ws-daemon-event-bridge.js +321 -0
  307. package/dist/server/ws-daemon-event-bridge.js.map +1 -0
  308. package/dist/server/ws-limits.d.ts +2 -0
  309. package/dist/server/ws-limits.d.ts.map +1 -0
  310. package/dist/server/ws-limits.js +12 -0
  311. package/dist/server/ws-limits.js.map +1 -0
  312. package/dist/server/ws-protocol.d.ts +248 -0
  313. package/dist/server/ws-protocol.d.ts.map +1 -0
  314. package/dist/server/ws-protocol.js +157 -0
  315. package/dist/server/ws-protocol.js.map +1 -0
  316. package/dist/server/ws-server.d.ts +26 -0
  317. package/dist/server/ws-server.d.ts.map +1 -0
  318. package/dist/server/ws-server.js +290 -0
  319. package/dist/server/ws-server.js.map +1 -0
  320. package/dist/startup-agents.d.ts +6 -0
  321. package/dist/startup-agents.d.ts.map +1 -0
  322. package/dist/startup-agents.js +97 -0
  323. package/dist/startup-agents.js.map +1 -0
  324. package/dist/startup-prereqs.d.ts +29 -0
  325. package/dist/startup-prereqs.d.ts.map +1 -0
  326. package/dist/startup-prereqs.js +209 -0
  327. package/dist/startup-prereqs.js.map +1 -0
  328. package/dist/startup-watchers.d.ts +7 -0
  329. package/dist/startup-watchers.d.ts.map +1 -0
  330. package/dist/startup-watchers.js +196 -0
  331. package/dist/startup-watchers.js.map +1 -0
  332. package/dist/startup.d.ts +20 -0
  333. package/dist/startup.d.ts.map +1 -0
  334. package/dist/startup.js +335 -0
  335. package/dist/startup.js.map +1 -0
  336. package/dist/tracking/git-tracker.d.ts +52 -0
  337. package/dist/tracking/git-tracker.d.ts.map +1 -0
  338. package/dist/tracking/git-tracker.js +277 -0
  339. package/dist/tracking/git-tracker.js.map +1 -0
  340. package/dist/tracking/noop-tracker.d.ts +27 -0
  341. package/dist/tracking/noop-tracker.d.ts.map +1 -0
  342. package/dist/tracking/noop-tracker.js +42 -0
  343. package/dist/tracking/noop-tracker.js.map +1 -0
  344. package/docs/configuration.md +75 -0
  345. package/docs/developer-workflows.md +107 -0
  346. package/docs/protocol-matrix.json +155 -0
  347. package/docs/releasing.md +65 -0
  348. package/docs/security.md +48 -0
  349. package/docs/testing.md +112 -0
  350. package/package.json +84 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * GitTracker — git-backed run tracking with worktree isolation.
3
+ *
4
+ * Creates a git worktree per session, micro-commits on configurable tool calls,
5
+ * and supports rollback, branch-retry, and squash-merge operations.
6
+ *
7
+ * This is the most complex module in the daemon. It directly manages git state
8
+ * via child_process — no git library dependency.
9
+ */
10
+ import type { RunTracker } from '../core/interfaces.js';
11
+ import type { SessionMessage, Step, GitTrackerConfig } from '../core/types.js';
12
+ export declare class GitTracker implements RunTracker {
13
+ private config;
14
+ private worktreePath;
15
+ private projectPath;
16
+ private branch;
17
+ private stepCounter;
18
+ private commitCount;
19
+ private _steps;
20
+ private commitQueue;
21
+ private tornDown;
22
+ /** Callback fired after each successful commit. */
23
+ onStepCommitted?: (step: Step) => void;
24
+ private readonly _sessionId;
25
+ constructor(config: GitTrackerConfig, sessionId: string);
26
+ get steps(): ReadonlyArray<Step>;
27
+ /** Await all pending commits. Useful for testing. */
28
+ flush(): Promise<void>;
29
+ /** Flush any pending commits. Called before teardown on crash/end. */
30
+ flushPendingCommits(): Promise<void>;
31
+ setup(_sessionId: string, projectPath: string): Promise<string>;
32
+ onMessage(msg: SessionMessage): void;
33
+ rollback(toSha: string): Promise<void>;
34
+ branchRetry(fromSha: string): Promise<string>;
35
+ squashMerge(targetBranch: string, commitMessage: string): Promise<void>;
36
+ teardown(): Promise<void>;
37
+ getDiff(sha: string): Promise<string>;
38
+ getStepDiffs(): Promise<Array<{
39
+ step: number;
40
+ sha: string;
41
+ diff: string;
42
+ }>>;
43
+ getSummaryDiff(): Promise<string>;
44
+ private shouldCommit;
45
+ private enqueueCommit;
46
+ private doCommit;
47
+ private describeStep;
48
+ private writeStepLog;
49
+ private ensureWorktree;
50
+ private git;
51
+ }
52
+ //# sourceMappingURL=git-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-tracker.d.ts","sourceRoot":"","sources":["../../src/tracking/git-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAU/E,qBAAa,UAAW,YAAW,UAAU;IAgBzC,OAAO,CAAC,MAAM;IAfhB,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,QAAQ,CAAS;IAEzB,mDAAmD;IACnD,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAEvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAG1B,MAAM,EAAE,gBAAgB,EAChC,SAAS,EAAE,MAAM;IAMnB,IAAI,KAAK,IAAI,aAAa,CAAC,IAAI,CAAC,CAE/B;IAED,qDAAqD;IAC/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,sEAAsE;IAChE,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBrE,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;IAsB9B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW7C,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCvE,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBzB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAYrC,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAW3E,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAyBvC,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,aAAa;YAUP,QAAQ;IA8CtB,OAAO,CAAC,YAAY;YAiBN,YAAY;IA0B1B,OAAO,CAAC,cAAc;YAMR,GAAG;CAQlB"}
@@ -0,0 +1,277 @@
1
+ /**
2
+ * GitTracker — git-backed run tracking with worktree isolation.
3
+ *
4
+ * Creates a git worktree per session, micro-commits on configurable tool calls,
5
+ * and supports rollback, branch-retry, and squash-merge operations.
6
+ *
7
+ * This is the most complex module in the daemon. It directly manages git state
8
+ * via child_process — no git library dependency.
9
+ */
10
+ import { execFile } from 'node:child_process';
11
+ import { promisify } from 'node:util';
12
+ import fs from 'node:fs/promises';
13
+ import path from 'node:path';
14
+ import { metrics } from '../core/metrics.js';
15
+ import { logger } from '../core/logger.js';
16
+ const log = logger.child({ module: 'git-tracker' });
17
+ const execGit = promisify(execFile);
18
+ const GIT_TIMEOUT_MS = 30_000;
19
+ export class GitTracker {
20
+ config;
21
+ worktreePath = null;
22
+ projectPath = null;
23
+ branch;
24
+ stepCounter = 0;
25
+ commitCount = 0;
26
+ _steps = [];
27
+ commitQueue = Promise.resolve();
28
+ tornDown = false;
29
+ /** Callback fired after each successful commit. */
30
+ onStepCommitted;
31
+ _sessionId;
32
+ constructor(config, sessionId) {
33
+ this.config = config;
34
+ this._sessionId = sessionId;
35
+ this.branch = `${config.branchPrefix}${sessionId}`;
36
+ }
37
+ get steps() {
38
+ return this._steps;
39
+ }
40
+ /** Await all pending commits. Useful for testing. */
41
+ async flush() {
42
+ await this.commitQueue;
43
+ }
44
+ /** Flush any pending commits. Called before teardown on crash/end. */
45
+ async flushPendingCommits() {
46
+ await this.commitQueue;
47
+ }
48
+ async setup(_sessionId, projectPath) {
49
+ this.projectPath = projectPath;
50
+ // Verify this is a git repo
51
+ await this.git(['rev-parse', '--is-inside-work-tree'], projectPath);
52
+ // Compute worktree path
53
+ this.worktreePath = path.join(projectPath, this.config.worktreeRoot, this._sessionId);
54
+ // Ensure parent directory exists
55
+ await fs.mkdir(path.dirname(this.worktreePath), { recursive: true });
56
+ // Create worktree + branch
57
+ await this.git(['worktree', 'add', this.worktreePath, '-b', this.branch], projectPath);
58
+ return this.worktreePath;
59
+ }
60
+ onMessage(msg) {
61
+ if (this.tornDown)
62
+ return;
63
+ this.stepCounter++;
64
+ const step = {
65
+ step: this.stepCounter,
66
+ sha: null,
67
+ type: msg.type,
68
+ toolName: 'toolName' in msg ? msg.toolName : undefined,
69
+ description: this.describeStep(msg),
70
+ timestamp: msg.timestamp,
71
+ };
72
+ this._steps.push(step);
73
+ // Only commit on completed tool calls for configured tools
74
+ if (msg.type === 'tool_call_update' && msg.status === 'completed' && msg.toolName) {
75
+ if (this.shouldCommit(msg.toolName)) {
76
+ this.enqueueCommit(step);
77
+ }
78
+ }
79
+ }
80
+ async rollback(toSha) {
81
+ this.ensureWorktree();
82
+ await this.git(['reset', '--hard', toSha], this.worktreePath);
83
+ metrics.increment('git.rollbacks');
84
+ }
85
+ async branchRetry(fromSha) {
86
+ this.ensureWorktree();
87
+ const retryBranch = `${this.branch}-retry-${Date.now()}`;
88
+ const retryPath = `${this.worktreePath}-retry-${Date.now()}`;
89
+ await fs.mkdir(path.dirname(retryPath), { recursive: true });
90
+ await this.git(['worktree', 'add', retryPath, '-b', retryBranch, fromSha], this.projectPath);
91
+ return retryPath;
92
+ }
93
+ async squashMerge(targetBranch, commitMessage) {
94
+ this.ensureWorktree();
95
+ // Flush any pending commits first
96
+ await this.commitQueue;
97
+ if (targetBranch === this.branch) {
98
+ throw new Error('Target branch must differ from session branch');
99
+ }
100
+ // Keep all merge operations inside the session worktree so we never mutate
101
+ // the user's main working tree branch.
102
+ const targetRef = `refs/heads/${targetBranch}`;
103
+ const { stdout: targetShaRaw } = await this.git(['rev-parse', '--verify', targetRef], this.projectPath);
104
+ const targetSha = targetShaRaw.trim();
105
+ try {
106
+ await this.git(['checkout', '--detach', targetSha], this.worktreePath);
107
+ await this.git(['merge', '--squash', this.branch], this.worktreePath);
108
+ await this.git(['commit', '-m', commitMessage, '--author', this.config.commitAuthor], this.worktreePath);
109
+ const { stdout: mergedShaRaw } = await this.git(['rev-parse', 'HEAD'], this.worktreePath);
110
+ const mergedSha = mergedShaRaw.trim();
111
+ await this.git(['update-ref', targetRef, mergedSha], this.projectPath);
112
+ }
113
+ finally {
114
+ // Restore worktree to the session branch even if merge failed.
115
+ await this.git(['checkout', this.branch], this.worktreePath).catch(() => { });
116
+ }
117
+ }
118
+ async teardown() {
119
+ if (this.tornDown)
120
+ return;
121
+ // Flush pending commits before marking as torn down
122
+ await this.commitQueue;
123
+ this.tornDown = true;
124
+ if (this.worktreePath && this.projectPath) {
125
+ // Write step log to branch
126
+ await this.writeStepLog();
127
+ // Remove the worktree
128
+ try {
129
+ await this.git(['worktree', 'remove', this.worktreePath, '--force'], this.projectPath);
130
+ }
131
+ catch {
132
+ // If worktree removal fails (e.g., already removed), just clean up
133
+ await fs.rm(this.worktreePath, { recursive: true, force: true });
134
+ await this.git(['worktree', 'prune'], this.projectPath).catch(() => { });
135
+ }
136
+ }
137
+ }
138
+ async getDiff(sha) {
139
+ this.ensureWorktree();
140
+ try {
141
+ const { stdout } = await this.git(['diff', `${sha}~1..${sha}`], this.worktreePath);
142
+ return stdout;
143
+ }
144
+ catch {
145
+ // First commit in worktree has no parent — show all changes
146
+ const { stdout } = await this.git(['show', '--format=', sha], this.worktreePath);
147
+ return stdout;
148
+ }
149
+ }
150
+ async getStepDiffs() {
151
+ const committed = this._steps.filter((step) => !!step.sha);
152
+ return Promise.all(committed.map(async (step) => ({
153
+ step: step.step,
154
+ sha: step.sha,
155
+ diff: await this.getDiff(step.sha),
156
+ })));
157
+ }
158
+ async getSummaryDiff() {
159
+ this.ensureWorktree();
160
+ const stepsWithSha = this._steps.filter((s) => s.sha);
161
+ if (stepsWithSha.length === 0)
162
+ return '';
163
+ const firstSha = stepsWithSha[0].sha;
164
+ const lastSha = stepsWithSha[stepsWithSha.length - 1].sha;
165
+ if (firstSha === lastSha) {
166
+ return this.getDiff(firstSha);
167
+ }
168
+ try {
169
+ const { stdout } = await this.git(['diff', `${firstSha}~1..${lastSha}`], this.worktreePath);
170
+ return stdout;
171
+ }
172
+ catch {
173
+ const { stdout } = await this.git(['diff', `${firstSha}..${lastSha}`], this.worktreePath);
174
+ return stdout;
175
+ }
176
+ }
177
+ // ---------------------------------------------------------------------------
178
+ // Private
179
+ // ---------------------------------------------------------------------------
180
+ shouldCommit(toolName) {
181
+ return this.config.commitOn.includes(toolName);
182
+ }
183
+ enqueueCommit(step) {
184
+ if (this.commitCount >= this.config.maxCommitsPerSession)
185
+ return;
186
+ this.commitQueue = this.commitQueue
187
+ .then(() => this.doCommit(step))
188
+ .catch((err) => {
189
+ log.warn({ err, step: step.step, sessionId: this._sessionId }, 'Git commit failed');
190
+ });
191
+ }
192
+ async doCommit(step) {
193
+ if (this.tornDown || !this.worktreePath)
194
+ return;
195
+ // Check if there are any changes
196
+ const { stdout: status } = await this.git(['status', '--porcelain'], this.worktreePath);
197
+ if (!status.trim())
198
+ return; // Nothing to commit
199
+ // Check we're still on our branch
200
+ const { stdout: currentBranch } = await this.git(['branch', '--show-current'], this.worktreePath);
201
+ if (currentBranch.trim() !== this.branch)
202
+ return; // Agent switched branches
203
+ // Stage all changes, respecting ignore patterns
204
+ const addArgs = ['add', '-A'];
205
+ for (const pattern of this.config.ignore) {
206
+ addArgs.push(`:(exclude)${pattern}`);
207
+ }
208
+ await this.git(addArgs, this.worktreePath);
209
+ // Check if staging resulted in any changes
210
+ const { stdout: staged } = await this.git(['diff', '--cached', '--name-only'], this.worktreePath);
211
+ if (!staged.trim())
212
+ return; // All changes were ignored
213
+ // Commit
214
+ const message = `[viewport] Step ${step.step}: ${step.description}`;
215
+ // We skip local git hooks because daemon-generated commits must be non-interactive and deterministic.
216
+ // Operators should enforce secret scanning via centralized CI/push protection.
217
+ await this.git(['commit', '-m', message, '--author', this.config.commitAuthor, '--no-verify'], this.worktreePath);
218
+ // Get the commit SHA
219
+ const { stdout: sha } = await this.git(['rev-parse', 'HEAD'], this.worktreePath);
220
+ step.sha = sha.trim();
221
+ this.commitCount++;
222
+ metrics.increment('git.commits');
223
+ this.onStepCommitted?.(step);
224
+ }
225
+ describeStep(msg) {
226
+ switch (msg.type) {
227
+ case 'tool_call':
228
+ return `${msg.toolName}: ${msg.title}`;
229
+ case 'tool_call_update':
230
+ return `${msg.toolName ?? 'tool'} ${msg.status}${msg.title ? ': ' + msg.title : ''}`;
231
+ case 'user_message':
232
+ return `User: ${msg.text.slice(0, 80)}`;
233
+ case 'agent_message':
234
+ return `Agent: ${msg.text.slice(0, 80)}`;
235
+ case 'token_usage':
236
+ return `Token usage: ${msg.inputTokens + msg.outputTokens} tokens`;
237
+ default:
238
+ return msg.type;
239
+ }
240
+ }
241
+ async writeStepLog() {
242
+ if (!this.worktreePath)
243
+ return;
244
+ const logPath = path.join(this.worktreePath, '.viewport-session.jsonl');
245
+ const lines = this._steps.map((s) => JSON.stringify(s)).join('\n') + '\n';
246
+ try {
247
+ await fs.writeFile(logPath, lines, 'utf-8');
248
+ await this.git(['add', '.viewport-session.jsonl'], this.worktreePath);
249
+ await this.git([
250
+ 'commit',
251
+ '-m',
252
+ `[viewport] Session log: ${this._steps.length} steps`,
253
+ '--author',
254
+ this.config.commitAuthor,
255
+ // Keep session-log commits non-interactive for the same reason as step commits.
256
+ '--no-verify',
257
+ ], this.worktreePath);
258
+ }
259
+ catch {
260
+ // Non-fatal — session log is nice-to-have
261
+ }
262
+ }
263
+ ensureWorktree() {
264
+ if (!this.worktreePath) {
265
+ throw new Error('GitTracker not set up. Call setup() first.');
266
+ }
267
+ }
268
+ async git(args, cwd) {
269
+ const { stdout, stderr } = await execGit('git', args, {
270
+ cwd,
271
+ maxBuffer: 10 * 1024 * 1024,
272
+ timeout: GIT_TIMEOUT_MS,
273
+ });
274
+ return { stdout, stderr };
275
+ }
276
+ }
277
+ //# sourceMappingURL=git-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-tracker.js","sourceRoot":"","sources":["../../src/tracking/git-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * NoopTracker — a RunTracker that does nothing.
3
+ *
4
+ * Used when git tracking is disabled (config.gitTracker.enabled = false).
5
+ * The agent runs in-place in the project directory with no worktree,
6
+ * no commits, no rollback capability.
7
+ */
8
+ import type { RunTracker } from '../core/interfaces.js';
9
+ import type { SessionMessage, Step } from '../core/types.js';
10
+ export declare class NoopTracker implements RunTracker {
11
+ readonly steps: ReadonlyArray<Step>;
12
+ setup(_sessionId: string, projectPath: string): Promise<string>;
13
+ onMessage(_msg: SessionMessage): void;
14
+ flushPendingCommits(): Promise<void>;
15
+ rollback(_toSha: string): Promise<void>;
16
+ branchRetry(_fromSha: string): Promise<string>;
17
+ squashMerge(_targetBranch: string, _commitMessage: string): Promise<void>;
18
+ teardown(): Promise<void>;
19
+ getDiff(_sha: string): Promise<string>;
20
+ getStepDiffs(): Promise<Array<{
21
+ step: number;
22
+ sha: string;
23
+ diff: string;
24
+ }>>;
25
+ getSummaryDiff(): Promise<string>;
26
+ }
27
+ //# sourceMappingURL=noop-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noop-tracker.d.ts","sourceRoot":"","sources":["../../src/tracking/noop-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7D,qBAAa,WAAY,YAAW,UAAU;IAC5C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,CAAM;IAEnC,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKrE,SAAS,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAI/B,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI9C,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzE,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAItC,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAI3E,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;CAGxC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * NoopTracker — a RunTracker that does nothing.
3
+ *
4
+ * Used when git tracking is disabled (config.gitTracker.enabled = false).
5
+ * The agent runs in-place in the project directory with no worktree,
6
+ * no commits, no rollback capability.
7
+ */
8
+ export class NoopTracker {
9
+ steps = [];
10
+ async setup(_sessionId, projectPath) {
11
+ // No worktree — run directly in the project directory
12
+ return projectPath;
13
+ }
14
+ onMessage(_msg) {
15
+ // No tracking
16
+ }
17
+ async flushPendingCommits() {
18
+ // Nothing to flush
19
+ }
20
+ async rollback(_toSha) {
21
+ throw new Error('Rollback is not available without git tracking enabled.');
22
+ }
23
+ async branchRetry(_fromSha) {
24
+ throw new Error('Branch-retry is not available without git tracking enabled.');
25
+ }
26
+ async squashMerge(_targetBranch, _commitMessage) {
27
+ throw new Error('Squash-merge is not available without git tracking enabled.');
28
+ }
29
+ async teardown() {
30
+ // Nothing to clean up
31
+ }
32
+ async getDiff(_sha) {
33
+ return '';
34
+ }
35
+ async getStepDiffs() {
36
+ return [];
37
+ }
38
+ async getSummaryDiff() {
39
+ return '';
40
+ }
41
+ }
42
+ //# sourceMappingURL=noop-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noop-tracker.js","sourceRoot":"","sources":["../../src/tracking/noop-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,OAAO,WAAW;IACb,KAAK,GAAwB,EAAE,CAAC;IAEzC,KAAK,CAAC,KAAK,CAAC,UAAkB,EAAE,WAAmB;QACjD,sDAAsD;QACtD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,SAAS,CAAC,IAAoB;QAC5B,cAAc;IAChB,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,mBAAmB;IACrB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc;QAC3B,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,QAAgB;QAChC,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,aAAqB,EAAE,cAAsB;QAC7D,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,sBAAsB;IACxB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAY;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,OAAO,EAAE,CAAC;IACZ,CAAC;CACF"}
@@ -0,0 +1,75 @@
1
+ # Viewport Daemon Configuration
2
+
3
+ ## Precedence
4
+
5
+ Daemon runtime settings resolve in this order (later wins):
6
+
7
+ 1. Built-in defaults
8
+ 2. `~/.viewport/config.json` (`daemon.*`)
9
+ 3. Environment variables (`VPD_*` / `VIEWPORT_*`)
10
+ 4. CLI flags
11
+
12
+ Session config resolution is separate:
13
+
14
+ 1. Framework built-ins
15
+ 2. Agent defaults
16
+ 3. Global defaults (`defaults`)
17
+ 4. Directory overrides (`directories.<id>.config`)
18
+ 5. Session launch overrides
19
+
20
+ ## Runtime keys
21
+
22
+ `config.json`:
23
+
24
+ ```json
25
+ {
26
+ "daemon": {
27
+ "listen": "127.0.0.1:7070",
28
+ "profile": "local",
29
+ "allowedHosts": ["localhost"],
30
+ "allowedOrigins": ["localhost"],
31
+ "authEnabled": false,
32
+ "logFile": "~/.viewport/daemon.log",
33
+ "relay": {
34
+ "enabled": false,
35
+ "endpoint": "wss://relay.example.test",
36
+ "publicEndpoint": "wss://relay.example.test"
37
+ }
38
+ }
39
+ }
40
+ ```
41
+
42
+ ## Environment variables
43
+
44
+ - `VPD_LISTEN` / `VIEWPORT_LISTEN`
45
+ - `VPD_PROFILE` / `VIEWPORT_PROFILE`
46
+ - `VPD_ALLOWED_HOSTS` / `VIEWPORT_ALLOWED_HOSTS`
47
+ - `VPD_ALLOWED_ORIGINS` / `VIEWPORT_ALLOWED_ORIGINS`
48
+ - `VPD_AUTH` / `VIEWPORT_AUTH`
49
+ - `VPD_LOG_FILE` / `VIEWPORT_LOG_FILE`
50
+ - `VPD_RELAY_ENABLED` / `VIEWPORT_RELAY_ENABLED`
51
+ - `VPD_RELAY_ENDPOINT` / `VIEWPORT_RELAY_ENDPOINT`
52
+ - `VIEWPORT_HTTP_LOG_LEVEL`
53
+ - `VIEWPORT_MAX_WS_CLIENTS`
54
+
55
+ ## CLI flags
56
+
57
+ - `--listen`
58
+ - `--profile`
59
+ - `--allowed-hosts`
60
+ - `--allowed-origins`
61
+ - `--auth`
62
+ - `--log-file`
63
+ - `--relay-endpoint`
64
+ - `--no-relay`
65
+
66
+ ## Notes for relay phase
67
+
68
+ Current daemon config already carries relay keys and security profile semantics.
69
+ Relay transport, cryptographic peer identity, and remote identity binding are intentionally deferred to the relay phase.
70
+
71
+ ## Validation guarantees
72
+
73
+ - `~/.viewport/config.json` is schema-validated with Zod.
74
+ - Malformed JSON or schema-invalid values fail fast with actionable errors.
75
+ - Unknown keys are rejected to prevent silent misconfiguration drift.
@@ -0,0 +1,107 @@
1
+ # Developer Workflows
2
+
3
+ ## Install and run locally
4
+
5
+ 1. Tarball-based local install (recommended):
6
+
7
+ ```bash
8
+ ./scripts/install-dev.sh --yes --no-service --no-prereqs --no-hooks
9
+ ```
10
+
11
+ 2. `npm link` local install (use only when you specifically need symlink behavior):
12
+
13
+ ```bash
14
+ ./scripts/install-dev.sh --link --yes --no-service --no-prereqs --no-hooks
15
+ ```
16
+
17
+ ## Uninstall / reinstall locally
18
+
19
+ 1. Remove global package and user service:
20
+
21
+ ```bash
22
+ npm run dev:uninstall
23
+ ```
24
+
25
+ 2. Remove package + service + daemon home/state:
26
+
27
+ ```bash
28
+ npm run dev:uninstall:all
29
+ ```
30
+
31
+ 3. Reinstall from current local source:
32
+
33
+ ```bash
34
+ npm run dev:reinstall
35
+ ```
36
+
37
+ Note on macOS background item naming:
38
+ The Login Items UI may show `Node.js Foundation` for the daemon service because launchd runs the Node runtime binary. That name comes from the executable signature, not the launchd label (`ai.viewport.daemon`).
39
+ If you ever see `sh` there, your service was installed from an older shell-wrapper plist; run `vpd service uninstall && vpd service install` to refresh it.
40
+
41
+ ## Why tarball install exists
42
+
43
+ `npm pack` builds the exact package artifact that npm would publish (`@viewportai/daemon-<version>.tgz`).
44
+ Installing from that tarball verifies all of these in one path:
45
+
46
+ 1. `files`/packaging manifest is correct.
47
+ 2. `bin` (`vpd`) resolves correctly after install.
48
+ 3. Runtime dependencies are present in the packaged artifact.
49
+ 4. Real install behavior matches production npm installs.
50
+
51
+ That makes tarball install a stronger release-confidence check than `npm link`, which can hide packaging mistakes by running directly from the source tree.
52
+
53
+ ## Verification scripts
54
+
55
+ 1. Repository quality gate:
56
+
57
+ ```bash
58
+ npm run verify:repo
59
+ ```
60
+
61
+ 2. Environment verification (isolated runtime):
62
+
63
+ ```bash
64
+ npm run verify:env
65
+ ```
66
+
67
+ 3. Environment verification + OS service checks:
68
+
69
+ ```bash
70
+ npm run verify:env:service
71
+ ```
72
+
73
+ 4. Package/install verification from isolated npm prefix:
74
+
75
+ ```bash
76
+ npm run verify:install
77
+ ```
78
+
79
+ Note: this command requires internet access to resolve package runtime dependencies.
80
+
81
+ 5. Combined verification with optional flags:
82
+
83
+ ```bash
84
+ ./scripts/verify.sh --fullstack --env --service
85
+ ```
86
+
87
+ ## Unified test command modes
88
+
89
+ ```bash
90
+ npm run test
91
+ npm run test --verify
92
+ npm run test --e2e
93
+ npm run test --fullstack
94
+ npm run test --env
95
+ npm run test --service
96
+ ```
97
+
98
+ ## Script surface (canonical)
99
+
100
+ Use only these shell entrypoints:
101
+
102
+ 1. `scripts/install.sh`
103
+ 2. `scripts/install-dev.sh`
104
+ 3. `scripts/test.sh`
105
+ 4. `scripts/test-env.sh`
106
+ 5. `scripts/install-verify.sh`
107
+ 6. `scripts/verify.sh`