@stravica-ai/digital-operator-pa 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 (372) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +170 -0
  3. package/bin/desk +9 -0
  4. package/bin/distill +2 -0
  5. package/bin/estate-sync +2 -0
  6. package/bin/launch +2 -0
  7. package/bin/memory-sync +2 -0
  8. package/bin/migrate-inspect +2 -0
  9. package/bin/pa +2 -0
  10. package/bin/pa-coordinator-hook +2 -0
  11. package/bin/pa-init +2 -0
  12. package/bin/research +2 -0
  13. package/bin/scheduler +2 -0
  14. package/bin/secrets +2 -0
  15. package/bin/slice +2 -0
  16. package/bin/smoke +9 -0
  17. package/bin/sync +2 -0
  18. package/dist/engineering-pa-cli/README.md +205 -0
  19. package/dist/engineering-pa-cli/bin/estate-sync +2 -0
  20. package/dist/engineering-pa-cli/bin/launch +2 -0
  21. package/dist/engineering-pa-cli/bin/pa +2 -0
  22. package/dist/engineering-pa-cli/bin/pa-coordinator-hook +12 -0
  23. package/dist/engineering-pa-cli/bin/research +2 -0
  24. package/dist/engineering-pa-cli/bin/scheduler +2 -0
  25. package/dist/engineering-pa-cli/bin/secrets +2 -0
  26. package/dist/engineering-pa-cli/bin/smoke +9 -0
  27. package/dist/engineering-pa-cli/bin/sync +2 -0
  28. package/dist/engineering-pa-cli/config/coordinator-allowlist.json +118 -0
  29. package/dist/engineering-pa-cli/docs/coordinator-hook.md +211 -0
  30. package/dist/engineering-pa-cli/docs/estate-sync.md +412 -0
  31. package/dist/engineering-pa-cli/docs/gsc.md +175 -0
  32. package/dist/engineering-pa-cli/docs/lint-linkedin.md +139 -0
  33. package/dist/engineering-pa-cli/docs/secrets.md +221 -0
  34. package/dist/engineering-pa-cli/docs/smoke.md +113 -0
  35. package/dist/engineering-pa-cli/docs/staging-alias.md +114 -0
  36. package/dist/engineering-pa-cli/index.mjs +17 -0
  37. package/dist/engineering-pa-cli/package.json +37 -0
  38. package/dist/engineering-pa-cli/src/autonomy/cli.mjs +329 -0
  39. package/dist/engineering-pa-cli/src/autonomy/envelope.mjs +301 -0
  40. package/dist/engineering-pa-cli/src/coordinator-hook/cli.mjs +140 -0
  41. package/dist/engineering-pa-cli/src/coordinator-hook/config.mjs +134 -0
  42. package/dist/engineering-pa-cli/src/coordinator-hook/message.mjs +47 -0
  43. package/dist/engineering-pa-cli/src/coordinator-hook/policy.mjs +211 -0
  44. package/dist/engineering-pa-cli/src/coordinator-hook/repo-root.mjs +44 -0
  45. package/dist/engineering-pa-cli/src/coordinator-hook/self.mjs +30 -0
  46. package/dist/engineering-pa-cli/src/environment/cli.mjs +287 -0
  47. package/dist/engineering-pa-cli/src/environment/probes.mjs +302 -0
  48. package/dist/engineering-pa-cli/src/gsc/auth.mjs +148 -0
  49. package/dist/engineering-pa-cli/src/gsc/cli.mjs +93 -0
  50. package/dist/engineering-pa-cli/src/gsc/cloudflare.mjs +318 -0
  51. package/dist/engineering-pa-cli/src/gsc/commands/add-property.mjs +70 -0
  52. package/dist/engineering-pa-cli/src/gsc/commands/list-properties.mjs +33 -0
  53. package/dist/engineering-pa-cli/src/gsc/commands/pull-analytics.mjs +130 -0
  54. package/dist/engineering-pa-cli/src/gsc/commands/submit-sitemap.mjs +41 -0
  55. package/dist/engineering-pa-cli/src/gsc/commands/verify-via-cf-dns.mjs +189 -0
  56. package/dist/engineering-pa-cli/src/knowledge/call-log.mjs +59 -0
  57. package/dist/engineering-pa-cli/src/knowledge/cli.mjs +242 -0
  58. package/dist/engineering-pa-cli/src/knowledge/eval.mjs +446 -0
  59. package/dist/engineering-pa-cli/src/knowledge/formatters.mjs +331 -0
  60. package/dist/engineering-pa-cli/src/knowledge/graph.mjs +710 -0
  61. package/dist/engineering-pa-cli/src/launch/README.md +214 -0
  62. package/dist/engineering-pa-cli/src/launch/cli.mjs +51 -0
  63. package/dist/engineering-pa-cli/src/launch/commands/launch.mjs +106 -0
  64. package/dist/engineering-pa-cli/src/launch/identity.mjs +43 -0
  65. package/dist/engineering-pa-cli/src/launch/planner.mjs +44 -0
  66. package/dist/engineering-pa-cli/src/launch/repo-root.mjs +53 -0
  67. package/dist/engineering-pa-cli/src/launch/runner.mjs +147 -0
  68. package/dist/engineering-pa-cli/src/launch/task-loader.mjs +85 -0
  69. package/dist/engineering-pa-cli/src/lint/cli.mjs +61 -0
  70. package/dist/engineering-pa-cli/src/lint/commands/linkedin.mjs +133 -0
  71. package/dist/engineering-pa-cli/src/lint/detectors.mjs +90 -0
  72. package/dist/engineering-pa-cli/src/lint/linter.mjs +69 -0
  73. package/dist/engineering-pa-cli/src/lint/reporter.mjs +32 -0
  74. package/dist/engineering-pa-cli/src/lint/rules.mjs +132 -0
  75. package/dist/engineering-pa-cli/src/pa/cli.mjs +369 -0
  76. package/dist/engineering-pa-cli/src/pa/doc-groups.mjs +164 -0
  77. package/dist/engineering-pa-cli/src/pa/io.mjs +80 -0
  78. package/dist/engineering-pa-cli/src/pa/project-cli.mjs +385 -0
  79. package/dist/engineering-pa-cli/src/pa/projects.mjs +352 -0
  80. package/dist/engineering-pa-cli/src/pa/repo-root.mjs +64 -0
  81. package/dist/engineering-pa-cli/src/pa/session.mjs +254 -0
  82. package/dist/engineering-pa-cli/src/pa/work-cli.mjs +164 -0
  83. package/dist/engineering-pa-cli/src/pa/work.mjs +196 -0
  84. package/dist/engineering-pa-cli/src/pa/workstreams.mjs +201 -0
  85. package/dist/engineering-pa-cli/src/research/README.md +360 -0
  86. package/dist/engineering-pa-cli/src/research/briefs/extractor.md +103 -0
  87. package/dist/engineering-pa-cli/src/research/briefs/searcher.md +113 -0
  88. package/dist/engineering-pa-cli/src/research/briefs/synthesizer.md +124 -0
  89. package/dist/engineering-pa-cli/src/research/briefs/verifier.md +86 -0
  90. package/dist/engineering-pa-cli/src/research/cli.mjs +141 -0
  91. package/dist/engineering-pa-cli/src/research/commands/gates.mjs +176 -0
  92. package/dist/engineering-pa-cli/src/research/commands/list.mjs +56 -0
  93. package/dist/engineering-pa-cli/src/research/commands/mark.mjs +97 -0
  94. package/dist/engineering-pa-cli/src/research/commands/paths.mjs +69 -0
  95. package/dist/engineering-pa-cli/src/research/commands/prune.mjs +86 -0
  96. package/dist/engineering-pa-cli/src/research/commands/run.mjs +94 -0
  97. package/dist/engineering-pa-cli/src/research/commands/show.mjs +43 -0
  98. package/dist/engineering-pa-cli/src/research/docs/operator-present-flow.md +120 -0
  99. package/dist/engineering-pa-cli/src/research/format.mjs +59 -0
  100. package/dist/engineering-pa-cli/src/research/promote.mjs +260 -0
  101. package/dist/engineering-pa-cli/src/research/schema/finding.schema.json +55 -0
  102. package/dist/engineering-pa-cli/src/research/schema/gates.schema.json +34 -0
  103. package/dist/engineering-pa-cli/src/research/schema/manifest.schema.json +59 -0
  104. package/dist/engineering-pa-cli/src/research/schema/plan.schema.json +41 -0
  105. package/dist/engineering-pa-cli/src/research/schema/sources.schema.json +31 -0
  106. package/dist/engineering-pa-cli/src/research/store/findings.mjs +61 -0
  107. package/dist/engineering-pa-cli/src/research/store/gates.mjs +73 -0
  108. package/dist/engineering-pa-cli/src/research/store/index.mjs +312 -0
  109. package/dist/engineering-pa-cli/src/research/store/manifest.mjs +56 -0
  110. package/dist/engineering-pa-cli/src/research/store/plan.mjs +59 -0
  111. package/dist/engineering-pa-cli/src/research/store/sources.mjs +44 -0
  112. package/dist/engineering-pa-cli/src/research/store/validate.mjs +92 -0
  113. package/dist/engineering-pa-cli/src/research/workflows/research-normal.js +573 -0
  114. package/dist/engineering-pa-cli/src/scheduler/cli.mjs +197 -0
  115. package/dist/engineering-pa-cli/src/secrets/cli.mjs +254 -0
  116. package/dist/engineering-pa-cli/src/secrets/commands/backup-template.mjs +67 -0
  117. package/dist/engineering-pa-cli/src/secrets/commands/backup.mjs +85 -0
  118. package/dist/engineering-pa-cli/src/secrets/commands/delete.mjs +58 -0
  119. package/dist/engineering-pa-cli/src/secrets/commands/find.mjs +36 -0
  120. package/dist/engineering-pa-cli/src/secrets/commands/get.mjs +49 -0
  121. package/dist/engineering-pa-cli/src/secrets/commands/init.mjs +69 -0
  122. package/dist/engineering-pa-cli/src/secrets/commands/list.mjs +37 -0
  123. package/dist/engineering-pa-cli/src/secrets/commands/rotate.mjs +46 -0
  124. package/dist/engineering-pa-cli/src/secrets/commands/set.mjs +123 -0
  125. package/dist/engineering-pa-cli/src/secrets/commands/status.mjs +146 -0
  126. package/dist/engineering-pa-cli/src/secrets/commands/vaults.mjs +57 -0
  127. package/dist/engineering-pa-cli/src/secrets/commands/verify.mjs +143 -0
  128. package/dist/engineering-pa-cli/src/secrets/vault.mjs +766 -0
  129. package/dist/engineering-pa-cli/src/smoke/checks.mjs +199 -0
  130. package/dist/engineering-pa-cli/src/smoke/cli.mjs +108 -0
  131. package/dist/engineering-pa-cli/src/smoke/commands/run.mjs +237 -0
  132. package/dist/engineering-pa-cli/src/smoke/runner.mjs +191 -0
  133. package/dist/engineering-pa-cli/src/staging-alias/cli.mjs +91 -0
  134. package/dist/engineering-pa-cli/src/staging-alias/cloudflare.mjs +380 -0
  135. package/dist/engineering-pa-cli/src/staging-alias/commands/list.mjs +36 -0
  136. package/dist/engineering-pa-cli/src/staging-alias/commands/set.mjs +188 -0
  137. package/dist/engineering-pa-cli/src/staging-alias/commands/status.mjs +113 -0
  138. package/dist/engineering-pa-cli/src/staging-alias/commands/unset.mjs +95 -0
  139. package/dist/engineering-pa-cli/src/staging-alias/sites.mjs +105 -0
  140. package/dist/engineering-pa-cli/src/sync/cli.mjs +151 -0
  141. package/dist/engineering-pa-cli/src/sync/git.mjs +149 -0
  142. package/dist/engineering-pa-cli/src/sync/lock.mjs +30 -0
  143. package/dist/engineering-pa-cli/src/sync/regenerated-artifacts.mjs +114 -0
  144. package/dist/engineering-pa-cli/src/sync/registry-scope.mjs +260 -0
  145. package/dist/engineering-pa-cli/src/sync/run.mjs +531 -0
  146. package/dist/engineering-pa-cli/src/sync/runner.mjs +62 -0
  147. package/dist/engineering-pa-cli/src/sync/runs-digest.mjs +138 -0
  148. package/dist/engineering-pa-core/README.md +60 -0
  149. package/dist/engineering-pa-core/bin/desk +9 -0
  150. package/dist/engineering-pa-core/bin/distill +2 -0
  151. package/dist/engineering-pa-core/bin/memory-sync +2 -0
  152. package/dist/engineering-pa-core/bin/slice +2 -0
  153. package/dist/engineering-pa-core/docs/autonomy-envelope-tracker.md +111 -0
  154. package/dist/engineering-pa-core/docs/blueprints/README.md +45 -0
  155. package/dist/engineering-pa-core/docs/blueprints/docker-services/blueprint.md +168 -0
  156. package/dist/engineering-pa-core/docs/blueprints/git-identity/blueprint.md +116 -0
  157. package/dist/engineering-pa-core/docs/blueprints/ideas/custom-workspace-views.md +9 -0
  158. package/dist/engineering-pa-core/docs/blueprints/ideas/knowledge-domain-patterns.md +15 -0
  159. package/dist/engineering-pa-core/docs/blueprints/ideas/office-integration.md +11 -0
  160. package/dist/engineering-pa-core/docs/blueprints/ideas/team-scaling.md +9 -0
  161. package/dist/engineering-pa-core/docs/blueprints/ideas/work-personal-separation.md +9 -0
  162. package/dist/engineering-pa-core/docs/blueprints/scheduled-distillation/blueprint.md +129 -0
  163. package/dist/engineering-pa-core/docs/blueprints/tool-integration/blueprint.md +110 -0
  164. package/dist/engineering-pa-core/docs/commands/init.md +159 -0
  165. package/dist/engineering-pa-core/docs/commands/schedule.md +98 -0
  166. package/dist/engineering-pa-core/docs/commands/upgrade.md +67 -0
  167. package/dist/engineering-pa-core/docs/entity-location-map.md +93 -0
  168. package/dist/engineering-pa-core/docs/knowledge-scaffold.md +121 -0
  169. package/dist/engineering-pa-core/docs/lock.md +155 -0
  170. package/dist/engineering-pa-core/docs/memory-sync.md +28 -0
  171. package/dist/engineering-pa-core/docs/pa-operating-model.md +457 -0
  172. package/dist/engineering-pa-core/docs/scheduling.md +35 -0
  173. package/dist/engineering-pa-core/docs/standards/README.md +24 -0
  174. package/dist/engineering-pa-core/docs/standards/briefing-contract.md +161 -0
  175. package/dist/engineering-pa-core/docs/standards/tooling.md +240 -0
  176. package/dist/engineering-pa-core/docs/tools/distill.md +230 -0
  177. package/dist/engineering-pa-core/docs/tools/memory-sync.md +98 -0
  178. package/dist/engineering-pa-core/docs/tools/scheduler.md +243 -0
  179. package/dist/engineering-pa-core/docs/tools/slice.md +150 -0
  180. package/dist/engineering-pa-core/docs/upstream-issue-filing.md +88 -0
  181. package/dist/engineering-pa-core/docs/working-directory.md +29 -0
  182. package/dist/engineering-pa-core/docs/workspace-operations.md +46 -0
  183. package/dist/engineering-pa-core/index.mjs +21 -0
  184. package/dist/engineering-pa-core/knowledge/README.md +53 -0
  185. package/dist/engineering-pa-core/knowledge/canonical/.gitkeep +0 -0
  186. package/dist/engineering-pa-core/knowledge/content-voice/README.md +64 -0
  187. package/dist/engineering-pa-core/knowledge/content-voice/banned-ai-tells-baseline.md +133 -0
  188. package/dist/engineering-pa-core/knowledge/content-voice/banned-ai-tells-shape.md +58 -0
  189. package/dist/engineering-pa-core/knowledge/content-voice/banned-ai-tells-taxonomy.md +33 -0
  190. package/dist/engineering-pa-core/knowledge/content-voice/content-pipeline-routing.md +58 -0
  191. package/dist/engineering-pa-core/knowledge/content-voice/new-tell-capture-procedure.md +40 -0
  192. package/dist/engineering-pa-core/knowledge/content-voice/voice-guide-shape.md +43 -0
  193. package/dist/engineering-pa-core/knowledge/delegation-dispatch/README.md +34 -0
  194. package/dist/engineering-pa-core/knowledge/delegation-dispatch/briefing-contract.md +77 -0
  195. package/dist/engineering-pa-core/knowledge/delegation-dispatch/delegation-modes.md +84 -0
  196. package/dist/engineering-pa-core/knowledge/delegation-dispatch/dispatch-envelope.md +238 -0
  197. package/dist/engineering-pa-core/knowledge/delegation-dispatch/task-groups-and-orchestrators.md +62 -0
  198. package/dist/engineering-pa-core/knowledge/delegation-dispatch/team-improvement-loop.md +48 -0
  199. package/dist/engineering-pa-core/knowledge/delegation-dispatch/tool-development-policy.md +48 -0
  200. package/dist/engineering-pa-core/knowledge/engineering-discipline/README.md +33 -0
  201. package/dist/engineering-pa-core/knowledge/engineering-discipline/blast-radius-and-safety.md +50 -0
  202. package/dist/engineering-pa-core/knowledge/engineering-discipline/investigate-root-causes.md +48 -0
  203. package/dist/engineering-pa-core/knowledge/engineering-discipline/role-ladder.md +57 -0
  204. package/dist/engineering-pa-core/knowledge/engineering-discipline/verify-runtime-behaviour.md +53 -0
  205. package/dist/engineering-pa-core/knowledge/engineering-discipline/worktree-isolation.md +50 -0
  206. package/dist/engineering-pa-core/knowledge/knowledge-memory/README.md +33 -0
  207. package/dist/engineering-pa-core/knowledge/knowledge-memory/claude-md-hygiene.md +47 -0
  208. package/dist/engineering-pa-core/knowledge/knowledge-memory/journal-and-self-improvement.md +53 -0
  209. package/dist/engineering-pa-core/knowledge/knowledge-memory/knowledge-retrieval-discipline.md +62 -0
  210. package/dist/engineering-pa-core/knowledge/knowledge-memory/librarian-synthesis-mandate.md +56 -0
  211. package/dist/engineering-pa-core/knowledge/knowledge-memory/staging-and-observations.md +58 -0
  212. package/dist/engineering-pa-core/knowledge/operator-interface/README.md +32 -0
  213. package/dist/engineering-pa-core/knowledge/operator-interface/communication-style.md +33 -0
  214. package/dist/engineering-pa-core/knowledge/operator-interface/escalation-and-correction.md +45 -0
  215. package/dist/engineering-pa-core/knowledge/operator-interface/push-back-discipline.md +42 -0
  216. package/dist/engineering-pa-core/knowledge/operator-interface/session-boot-and-end.md +56 -0
  217. package/dist/engineering-pa-core/knowledge/platform-tooling/README.md +37 -0
  218. package/dist/engineering-pa-core/knowledge/platform-tooling/desk-cli-reference.md +52 -0
  219. package/dist/engineering-pa-core/knowledge/platform-tooling/environment-awareness.md +91 -0
  220. package/dist/engineering-pa-core/knowledge/platform-tooling/mcp-servers-catalogue.md +52 -0
  221. package/dist/engineering-pa-core/knowledge/platform-tooling/pa-cli-reference.md +55 -0
  222. package/dist/engineering-pa-core/knowledge/platform-tooling/scheduling-and-launchd.md +56 -0
  223. package/dist/engineering-pa-core/knowledge/platform-tooling/tool-discovery-discipline.md +49 -0
  224. package/dist/engineering-pa-core/knowledge/platform-tooling/working-directory-vs-project-root.md +43 -0
  225. package/dist/engineering-pa-core/knowledge/platform-tooling/workspace-server.md +51 -0
  226. package/dist/engineering-pa-core/knowledge/raw/.gitkeep +0 -0
  227. package/dist/engineering-pa-core/knowledge/scaffold/domains.json +5 -0
  228. package/dist/engineering-pa-core/knowledge/schema/.gitkeep +0 -0
  229. package/dist/engineering-pa-core/knowledge/work-management/README.md +33 -0
  230. package/dist/engineering-pa-core/knowledge/work-management/desk-cli.md +84 -0
  231. package/dist/engineering-pa-core/knowledge/work-management/progress-md.md +48 -0
  232. package/dist/engineering-pa-core/knowledge/work-management/projects.md +64 -0
  233. package/dist/engineering-pa-core/knowledge/work-management/spawn-log.md +48 -0
  234. package/dist/engineering-pa-core/knowledge/work-management/work-items.md +67 -0
  235. package/dist/engineering-pa-core/package.json +26 -0
  236. package/dist/engineering-pa-core/roles/agent-ops/definition.md +79 -0
  237. package/dist/engineering-pa-core/roles/dispatch-briefer/definition.md +195 -0
  238. package/dist/engineering-pa-core/roles/librarian/definition.md +176 -0
  239. package/dist/engineering-pa-core/roles/pa/definition.md +93 -0
  240. package/dist/engineering-pa-core/roles/system-admin/definition.md +106 -0
  241. package/dist/engineering-pa-core/roles/tool-developer/definition.md +116 -0
  242. package/dist/engineering-pa-core/roles/writer/definition.md +130 -0
  243. package/dist/engineering-pa-core/schema/autonomy-envelope.schema.json +61 -0
  244. package/dist/engineering-pa-core/schema/project.json +114 -0
  245. package/dist/engineering-pa-core/schema/schedule.json +63 -0
  246. package/dist/engineering-pa-core/schema/work-item.json +92 -0
  247. package/dist/engineering-pa-core/src/config/pa-package-name.mjs +30 -0
  248. package/dist/engineering-pa-core/src/desk/cli.mjs +95 -0
  249. package/dist/engineering-pa-core/src/desk/commands.mjs +398 -0
  250. package/dist/engineering-pa-core/src/desk/format.mjs +84 -0
  251. package/dist/engineering-pa-core/src/desk/repo.mjs +172 -0
  252. package/dist/engineering-pa-core/src/desk/team-scope.mjs +142 -0
  253. package/dist/engineering-pa-core/src/distill/cli.mjs +112 -0
  254. package/dist/engineering-pa-core/src/distill/prereqs.mjs +171 -0
  255. package/dist/engineering-pa-core/src/distill/prompt.mjs +74 -0
  256. package/dist/engineering-pa-core/src/distill/run.mjs +230 -0
  257. package/dist/engineering-pa-core/src/distill/runner.mjs +86 -0
  258. package/dist/engineering-pa-core/src/distill/staging.mjs +59 -0
  259. package/dist/engineering-pa-core/src/knowledge/retrieval/backlink-indexer.mjs +154 -0
  260. package/dist/engineering-pa-core/src/knowledge/retrieval/graph-builder.mjs +186 -0
  261. package/dist/engineering-pa-core/src/knowledge/retrieval/index-builder.mjs +225 -0
  262. package/dist/engineering-pa-core/src/knowledge/retrieval/query.mjs +263 -0
  263. package/dist/engineering-pa-core/src/lock/lock.mjs +202 -0
  264. package/dist/engineering-pa-core/src/memory-sync/cli-support.mjs +12 -0
  265. package/dist/engineering-pa-core/src/memory-sync/cli.mjs +56 -0
  266. package/dist/engineering-pa-core/src/memory-sync/commands/pull.mjs +44 -0
  267. package/dist/engineering-pa-core/src/memory-sync/commands/push.mjs +46 -0
  268. package/dist/engineering-pa-core/src/memory-sync/mirror.mjs +114 -0
  269. package/dist/engineering-pa-core/src/memory-sync/repo.mjs +65 -0
  270. package/dist/engineering-pa-core/src/scheduler/detect.mjs +111 -0
  271. package/dist/engineering-pa-core/src/scheduler/host.mjs +38 -0
  272. package/dist/engineering-pa-core/src/scheduler/index.mjs +13 -0
  273. package/dist/engineering-pa-core/src/scheduler/install.mjs +854 -0
  274. package/dist/engineering-pa-core/src/scheduler/list.mjs +168 -0
  275. package/dist/engineering-pa-core/src/scheduler/remove.mjs +176 -0
  276. package/dist/engineering-pa-core/src/scheduler/verify.mjs +435 -0
  277. package/dist/engineering-pa-core/src/session-boot/autonomy-injection.mjs +84 -0
  278. package/dist/engineering-pa-core/src/slice/cli.mjs +139 -0
  279. package/dist/engineering-pa-core/src/slice/inputs.mjs +174 -0
  280. package/dist/engineering-pa-core/src/slice/prompt.mjs +94 -0
  281. package/dist/engineering-pa-core/src/slice/prompts/dave-boot.md +91 -0
  282. package/dist/engineering-pa-core/src/slice/run.mjs +334 -0
  283. package/dist/engineering-pa-core-extensions-atlassian/README.md +31 -0
  284. package/dist/engineering-pa-core-extensions-atlassian/index.mjs +9 -0
  285. package/dist/engineering-pa-core-extensions-atlassian/package.json +19 -0
  286. package/dist/engineering-pa-core-extensions-n8n/README.md +29 -0
  287. package/dist/engineering-pa-core-extensions-n8n/index.mjs +8 -0
  288. package/dist/engineering-pa-core-extensions-n8n/package.json +19 -0
  289. package/dist/engineering-pa-librarian/README.md +38 -0
  290. package/dist/engineering-pa-librarian/index.mjs +12 -0
  291. package/dist/engineering-pa-librarian/package.json +19 -0
  292. package/dist/engineering-pa-migrate-inspect/README.md +131 -0
  293. package/dist/engineering-pa-migrate-inspect/bin/migrate-inspect +2 -0
  294. package/dist/engineering-pa-migrate-inspect/package.json +21 -0
  295. package/dist/engineering-pa-migrate-inspect/src/age-key-migrate.mjs +83 -0
  296. package/dist/engineering-pa-migrate-inspect/src/cli.mjs +97 -0
  297. package/dist/engineering-pa-migrate-inspect/src/inspector.mjs +237 -0
  298. package/dist/engineering-pa-migrate-inspect/src/platforms/linux.mjs +87 -0
  299. package/dist/engineering-pa-migrate-inspect/src/platforms/macos.mjs +105 -0
  300. package/dist/engineering-pa-migrate-inspect/src/runner.mjs +87 -0
  301. package/dist/engineering-pa-runbook/README.md +103 -0
  302. package/dist/engineering-pa-runbook/package.json +18 -0
  303. package/dist/engineering-pa-runbook/reference/dex-template.runbook.json +66 -0
  304. package/dist/engineering-pa-runbook/reference/hq-dave.runbook.json +69 -0
  305. package/dist/engineering-pa-runbook/reference/smarthome01.runbook.json +92 -0
  306. package/dist/engineering-pa-runbook/schema/inspection.schema.json +113 -0
  307. package/dist/engineering-pa-runbook/schema/runbook.schema.json +67 -0
  308. package/dist/engineering-pa-runbook/src/validator.mjs +167 -0
  309. package/dist/engineering-pa-scaffold/README.md +164 -0
  310. package/dist/engineering-pa-scaffold/bin/pa-init +2 -0
  311. package/dist/engineering-pa-scaffold/index.mjs +42 -0
  312. package/dist/engineering-pa-scaffold/package.json +22 -0
  313. package/dist/engineering-pa-scaffold/src/cli.mjs +115 -0
  314. package/dist/engineering-pa-scaffold/src/commands/init.mjs +169 -0
  315. package/dist/engineering-pa-scaffold/src/generator.mjs +354 -0
  316. package/dist/engineering-pa-scaffold/src/prompts.mjs +125 -0
  317. package/dist/engineering-pa-scaffold/src/runner.mjs +142 -0
  318. package/dist/engineering-pa-scaffold/templates/CLAUDE.md.template +196 -0
  319. package/dist/engineering-pa-scaffold/templates/operator-README.md.template +44 -0
  320. package/dist/engineering-pa-types-engineering/README.md +35 -0
  321. package/dist/engineering-pa-types-engineering/docs/commands/product-build.md +120 -0
  322. package/dist/engineering-pa-types-engineering/index.mjs +9 -0
  323. package/dist/engineering-pa-types-engineering/package.json +19 -0
  324. package/dist/engineering-pa-types-engineering/roles/product-engineer/definition.md +650 -0
  325. package/dist/engineering-pa-types-engineering/roles/product-engineer/templates/build-spec.md +82 -0
  326. package/dist/engineering-pa-types-engineering/roles/product-engineer/templates/preflight-checklist.md +158 -0
  327. package/dist/engineering-pa-types-engineering/roles/product-engineer/templates/worker-brief.md +130 -0
  328. package/dist/engineering-pa-workspace/README.md +197 -0
  329. package/dist/engineering-pa-workspace/app/assets/md.js +187 -0
  330. package/dist/engineering-pa-workspace/app/assets/modal.js +120 -0
  331. package/dist/engineering-pa-workspace/app/assets/theme.css +132 -0
  332. package/dist/engineering-pa-workspace/app/assets/theme.js +159 -0
  333. package/dist/engineering-pa-workspace/app/banner.js +320 -0
  334. package/dist/engineering-pa-workspace/app/delegations.html +345 -0
  335. package/dist/engineering-pa-workspace/app/home.html +1060 -0
  336. package/dist/engineering-pa-workspace/app/index.html +361 -0
  337. package/dist/engineering-pa-workspace/app/knowledge-map.html +163 -0
  338. package/dist/engineering-pa-workspace/app/knowledge.html +304 -0
  339. package/dist/engineering-pa-workspace/app/nav.json +75 -0
  340. package/dist/engineering-pa-workspace/app/notes.html +199 -0
  341. package/dist/engineering-pa-workspace/app/onboarding.html +592 -0
  342. package/dist/engineering-pa-workspace/app/profile.html +243 -0
  343. package/dist/engineering-pa-workspace/app/project-detail.html +432 -0
  344. package/dist/engineering-pa-workspace/app/projects.html +297 -0
  345. package/dist/engineering-pa-workspace/app/repos.html +598 -0
  346. package/dist/engineering-pa-workspace/app/schedules.html +486 -0
  347. package/dist/engineering-pa-workspace/app/secrets.html +164 -0
  348. package/dist/engineering-pa-workspace/app/staging.html +319 -0
  349. package/dist/engineering-pa-workspace/app/tasks.html +465 -0
  350. package/dist/engineering-pa-workspace/app/vendor/chart.umd.min.js +21 -0
  351. package/dist/engineering-pa-workspace/app/viewer.html +116 -0
  352. package/dist/engineering-pa-workspace/docs/DAEMON.md +104 -0
  353. package/dist/engineering-pa-workspace/docs/page-blueprint.md +286 -0
  354. package/dist/engineering-pa-workspace/docs/status-mon.md +168 -0
  355. package/dist/engineering-pa-workspace/index.mjs +12 -0
  356. package/dist/engineering-pa-workspace/nav.json.example +8 -0
  357. package/dist/engineering-pa-workspace/package.json +27 -0
  358. package/dist/engineering-pa-workspace/src/api.mjs +2086 -0
  359. package/dist/engineering-pa-workspace/src/install-daemon.mjs +573 -0
  360. package/dist/engineering-pa-workspace/src/nav.mjs +190 -0
  361. package/dist/engineering-pa-workspace/src/secrets-api.mjs +175 -0
  362. package/dist/engineering-pa-workspace/src/server.mjs +516 -0
  363. package/dist/engineering-pa-workspace/src/status-mon/poll.mjs +220 -0
  364. package/dist/engineering-pa-workspace/src/status-mon/poller.mjs +113 -0
  365. package/dist/engineering-pa-workspace/src/status-mon/run.mjs +133 -0
  366. package/dist/engineering-pa-workspace/src/supervisor.mjs +264 -0
  367. package/dist/engineering-pa-workspace/src/ws.mjs +633 -0
  368. package/index.mjs +60 -0
  369. package/package.json +58 -0
  370. package/templates/banned-ai-tells.md +102 -0
  371. package/templates/purpose.md +105 -0
  372. package/templates/voice-guide.md +98 -0
@@ -0,0 +1,573 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * install-daemon.mjs — Install the workspace server as a supervised daemon
5
+ *
6
+ * Supervises the workspace server via the host's native service manager so it
7
+ * auto-starts at login and auto-restarts on crash. This is distinct from the
8
+ * scheduler tool (cron/launchd-calendar/systemd-timer/schtasks), which is
9
+ * time-triggered. A daemon is continuous-supervision and needs KeepAlive /
10
+ * Restart=always / RunAtLoad semantics that cron doesn't express.
11
+ *
12
+ * The daemon invokes `node server.mjs --no-timeout --port N --no-open`
13
+ * directly — it deliberately bypasses ws.mjs to avoid double-fork detach,
14
+ * which would make the supervisor think the service died on every start.
15
+ *
16
+ * Usage:
17
+ * node install-daemon.mjs install [--port N] [--dry-run]
18
+ * node install-daemon.mjs uninstall [--dry-run]
19
+ * node install-daemon.mjs status
20
+ * node install-daemon.mjs --help
21
+ *
22
+ * Exit codes:
23
+ * 0 — OK
24
+ * 1 — Usage error
25
+ * 2 — Platform unsupported or logical failure
26
+ * 3 — Transport / IO failure (launchctl/systemctl call failed)
27
+ */
28
+
29
+ import { execSync } from 'node:child_process';
30
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync, realpathSync } from 'node:fs';
31
+ import { homedir, platform } from 'node:os';
32
+ import { dirname, join, resolve } from 'node:path';
33
+ import { fileURLToPath, pathToFileURL } from 'node:url';
34
+
35
+ const __filename = fileURLToPath(import.meta.url);
36
+ const __dirname = dirname(__filename);
37
+
38
+ // Resolve the operator repo root. In v2 this package is installed at
39
+ // node_modules/@stravica-ai/engineering-pa-workspace/, so walking up three
40
+ // __dirname levels lands inside node_modules/, not at the operator repo
41
+ // root. Precedence:
42
+ // 1. DAVE_REPO_ROOT or PA_REPO_ROOT env (explicit override)
43
+ // 2. Walk up from process.cwd() looking for .git or pnpm-workspace.yaml
44
+ // 3. Fall back to process.cwd() (best-effort; lets dry-run work in odd
45
+ // checkouts)
46
+ function findRepoRoot(start) {
47
+ let d = start;
48
+ while (d && d !== resolve(d, '..')) {
49
+ if (existsSync(join(d, '.git')) || existsSync(join(d, 'pnpm-workspace.yaml'))) return d;
50
+ d = resolve(d, '..');
51
+ }
52
+ return null;
53
+ }
54
+
55
+ const envRoot = process.env.DAVE_REPO_ROOT || process.env.PA_REPO_ROOT;
56
+ const REPO_ROOT = envRoot ? resolve(envRoot) : (findRepoRoot(process.cwd()) || process.cwd());
57
+ const SERVER_SCRIPT = join(__dirname, 'server.mjs');
58
+ const PREFS_FILE = join(REPO_ROOT, 'operator', 'config', 'preferences.json');
59
+
60
+ const LABEL = 'com.dave.workspace';
61
+ const UNIT_NAME = 'dave-workspace.service';
62
+
63
+ // --- Log paths (platform-specific) --------------------------------------
64
+
65
+ function defaultLogPaths() {
66
+ const plat = platform();
67
+ if (plat === 'darwin') {
68
+ const dir = join(homedir(), 'Library', 'Logs');
69
+ return { dir, out: join(dir, 'dave-workspace.log'), err: join(dir, 'dave-workspace.err.log') };
70
+ }
71
+ if (plat === 'linux') {
72
+ const dir = join(homedir(), '.local', 'state', 'dave');
73
+ return { dir, out: join(dir, 'workspace.log'), err: join(dir, 'workspace.err.log') };
74
+ }
75
+ return { dir: null, out: null, err: null };
76
+ }
77
+
78
+ // --- Port resolution ----------------------------------------------------
79
+
80
+ /**
81
+ * Resolve the workspace port at install time. Precedence:
82
+ * 1. CLI --port flag
83
+ * 2. operator/config/preferences.json workspacePort
84
+ * 3. default 4200
85
+ * @param {string|undefined} flagPort
86
+ * @returns {number}
87
+ */
88
+ export function resolvePort(flagPort) {
89
+ if (flagPort !== undefined && flagPort !== null) {
90
+ const parsed = parseInt(String(flagPort), 10);
91
+ if (Number.isNaN(parsed) || parsed < 1 || parsed > 65535) {
92
+ throw Object.assign(new Error(`Invalid port "${flagPort}". Must be 1-65535.`), { exitCode: 1 });
93
+ }
94
+ return parsed;
95
+ }
96
+ try {
97
+ const prefs = JSON.parse(readFileSync(PREFS_FILE, 'utf-8'));
98
+ if (prefs.workspacePort) return prefs.workspacePort;
99
+ } catch { /* fall through to default */ }
100
+ return 4200;
101
+ }
102
+
103
+ // --- XML / plist builders -----------------------------------------------
104
+
105
+ /**
106
+ * XML-escape a string for safe embedding in plist values.
107
+ * @param {string} s
108
+ */
109
+ function xmlEscape(s) {
110
+ return String(s)
111
+ .replace(/&/g, '&amp;')
112
+ .replace(/</g, '&lt;')
113
+ .replace(/>/g, '&gt;')
114
+ .replace(/"/g, '&quot;');
115
+ }
116
+
117
+ /**
118
+ * Build the launchd plist XML for the workspace daemon. Pure function.
119
+ *
120
+ * ProgramArguments invokes server.mjs directly (NOT ws.mjs) because ws.mjs
121
+ * double-forks and detaches — launchd would see the immediate parent exit
122
+ * and interpret it as a crash, triggering a restart loop.
123
+ *
124
+ * KeepAlive is a bare boolean: restart unconditionally on exit. ThrottleInterval
125
+ * caps the restart rate so a persistent crash can't burn CPU in a tight loop.
126
+ *
127
+ * @param {object} opts
128
+ * @param {string} opts.nodePath - Absolute path to node executable
129
+ * @param {string} opts.serverScript - Absolute path to server.mjs
130
+ * @param {string} opts.repoRoot - Absolute repo root for WorkingDirectory
131
+ * @param {number} opts.port - Port to bind
132
+ * @param {string} opts.stdoutPath - Path to stdout log
133
+ * @param {string} opts.stderrPath - Path to stderr log
134
+ * @returns {string}
135
+ */
136
+ export function buildLaunchdPlist(opts) {
137
+ const { nodePath, serverScript, repoRoot, port, stdoutPath, stderrPath } = opts;
138
+ const programArgs = [
139
+ nodePath,
140
+ serverScript,
141
+ '--no-timeout',
142
+ '--port', String(port),
143
+ '--no-open',
144
+ ];
145
+ const argsXml = programArgs.map((p) => ` <string>${xmlEscape(p)}</string>`).join('\n');
146
+
147
+ return `<?xml version="1.0" encoding="UTF-8"?>
148
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
149
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
150
+ <plist version="1.0">
151
+ <dict>
152
+ <key>Label</key>
153
+ <string>${LABEL}</string>
154
+ <key>ProgramArguments</key>
155
+ <array>
156
+ ${argsXml}
157
+ </array>
158
+ <key>WorkingDirectory</key>
159
+ <string>${xmlEscape(repoRoot)}</string>
160
+ <key>EnvironmentVariables</key>
161
+ <dict>
162
+ <key>DAVE_ROOT</key>
163
+ <string>${xmlEscape(repoRoot)}</string>
164
+ <key>PATH</key>
165
+ <string>${xmlEscape(process.env.PATH || '/usr/local/bin:/usr/bin:/bin')}</string>
166
+ </dict>
167
+ <key>RunAtLoad</key>
168
+ <true/>
169
+ <key>KeepAlive</key>
170
+ <true/>
171
+ <key>ThrottleInterval</key>
172
+ <integer>10</integer>
173
+ <key>StandardOutPath</key>
174
+ <string>${xmlEscape(stdoutPath)}</string>
175
+ <key>StandardErrorPath</key>
176
+ <string>${xmlEscape(stderrPath)}</string>
177
+ <key>ProcessType</key>
178
+ <string>Background</string>
179
+ </dict>
180
+ </plist>
181
+ `;
182
+ }
183
+
184
+ /**
185
+ * Build the systemd user service unit for the workspace daemon. Pure function.
186
+ *
187
+ * Same rationale as launchd: ExecStart invokes server.mjs directly (not ws.mjs),
188
+ * because ws.mjs detaches and systemd would see Type=simple's main process exit
189
+ * and assume the service died. Restart=always + RestartSec=5 mirrors launchd's
190
+ * KeepAlive+ThrottleInterval.
191
+ *
192
+ * @param {object} opts
193
+ * @param {string} opts.nodePath
194
+ * @param {string} opts.serverScript
195
+ * @param {string} opts.repoRoot
196
+ * @param {number} opts.port
197
+ * @param {string} opts.stdoutPath
198
+ * @param {string} opts.stderrPath
199
+ * @returns {string}
200
+ */
201
+ export function buildSystemdUnit(opts) {
202
+ const { nodePath, serverScript, repoRoot, port, stdoutPath, stderrPath } = opts;
203
+ return `[Unit]
204
+ Description=Dave workspace server (supervised daemon)
205
+ After=network.target
206
+
207
+ [Service]
208
+ Type=simple
209
+ WorkingDirectory=${repoRoot}
210
+ Environment=DAVE_ROOT=${repoRoot}
211
+ ExecStart=${nodePath} ${serverScript} --no-timeout --port ${port} --no-open
212
+ Restart=always
213
+ RestartSec=5
214
+ StandardOutput=append:${stdoutPath}
215
+ StandardError=append:${stderrPath}
216
+
217
+ [Install]
218
+ WantedBy=default.target
219
+ `;
220
+ }
221
+
222
+ // --- Paths --------------------------------------------------------------
223
+
224
+ function launchdPlistPath() {
225
+ return join(homedir(), 'Library', 'LaunchAgents', `${LABEL}.plist`);
226
+ }
227
+
228
+ function systemdUnitPath() {
229
+ return join(homedir(), '.config', 'systemd', 'user', UNIT_NAME);
230
+ }
231
+
232
+ // --- Darwin (launchd) ---------------------------------------------------
233
+
234
+ function darwinInstall({ port, dryRun }) {
235
+ const logs = defaultLogPaths();
236
+ const opts = {
237
+ nodePath: process.execPath,
238
+ serverScript: SERVER_SCRIPT,
239
+ repoRoot: REPO_ROOT,
240
+ port,
241
+ stdoutPath: logs.out,
242
+ stderrPath: logs.err,
243
+ };
244
+ const plist = buildLaunchdPlist(opts);
245
+ const plistPath = launchdPlistPath();
246
+
247
+ if (dryRun) {
248
+ console.log(`# Would write plist to: ${plistPath}`);
249
+ console.log(`# Log dir: ${logs.dir}`);
250
+ console.log(`# Would run: launchctl unload -w ${plistPath} (ignoring errors)`);
251
+ console.log(`# Would run: launchctl load -w ${plistPath}`);
252
+ console.log('# --- plist contents ---');
253
+ console.log(plist);
254
+ return 0;
255
+ }
256
+
257
+ mkdirSync(dirname(plistPath), { recursive: true });
258
+ mkdirSync(logs.dir, { recursive: true });
259
+ writeFileSync(plistPath, plist, 'utf8');
260
+ console.log(`Wrote plist: ${plistPath}`);
261
+
262
+ // Unload if present (ignore failure — it may not be loaded)
263
+ try {
264
+ execSync(`launchctl unload -w ${shellQuote(plistPath)}`, { stdio: 'pipe' });
265
+ } catch { /* not previously loaded */ }
266
+
267
+ try {
268
+ execSync(`launchctl load -w ${shellQuote(plistPath)}`, { stdio: 'pipe' });
269
+ } catch (err) {
270
+ throw Object.assign(new Error(`launchctl load failed: ${err.message}`), { exitCode: 3 });
271
+ }
272
+
273
+ console.log(`Loaded service: ${LABEL}`);
274
+ console.log(`Logs: ${logs.out}`);
275
+ console.log(` ${logs.err}`);
276
+ console.log(`URL: http://127.0.0.1:${port}/`);
277
+ return 0;
278
+ }
279
+
280
+ function darwinUninstall({ dryRun }) {
281
+ const plistPath = launchdPlistPath();
282
+ if (dryRun) {
283
+ console.log(`# Would run: launchctl unload -w ${plistPath}`);
284
+ console.log(`# Would remove: ${plistPath}`);
285
+ return 0;
286
+ }
287
+
288
+ if (existsSync(plistPath)) {
289
+ try {
290
+ execSync(`launchctl unload -w ${shellQuote(plistPath)}`, { stdio: 'pipe' });
291
+ } catch { /* not loaded — fine */ }
292
+ try {
293
+ unlinkSync(plistPath);
294
+ console.log(`Removed plist: ${plistPath}`);
295
+ } catch (err) {
296
+ throw Object.assign(new Error(`Could not remove plist: ${err.message}`), { exitCode: 3 });
297
+ }
298
+ } else {
299
+ console.log(`No plist found at ${plistPath} — nothing to remove.`);
300
+ }
301
+ console.log(`Unloaded: ${LABEL}`);
302
+ return 0;
303
+ }
304
+
305
+ function darwinStatus() {
306
+ const plistPath = launchdPlistPath();
307
+ const plistExists = existsSync(plistPath);
308
+ console.log(`Plist: ${plistPath} (${plistExists ? 'present' : 'absent'})`);
309
+
310
+ let listing = '';
311
+ try {
312
+ listing = execSync(`launchctl list ${LABEL}`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
313
+ } catch {
314
+ console.log(`Service ${LABEL}: not loaded.`);
315
+ return plistExists ? 2 : 0;
316
+ }
317
+
318
+ // launchctl list <label> returns a plist-ish dict. Extract PID line if any.
319
+ const pidMatch = listing.match(/"PID"\s*=\s*(\d+)/);
320
+ if (pidMatch) {
321
+ console.log(`Service ${LABEL}: running (PID ${pidMatch[1]}).`);
322
+ return 0;
323
+ }
324
+ const exitMatch = listing.match(/"LastExitStatus"\s*=\s*(-?\d+)/);
325
+ console.log(`Service ${LABEL}: loaded but not running${exitMatch ? ` (last exit: ${exitMatch[1]})` : ''}.`);
326
+ return 2;
327
+ }
328
+
329
+ // --- Linux (systemd --user) --------------------------------------------
330
+
331
+ function linuxInstall({ port, dryRun }) {
332
+ const logs = defaultLogPaths();
333
+ const opts = {
334
+ nodePath: process.execPath,
335
+ serverScript: SERVER_SCRIPT,
336
+ repoRoot: REPO_ROOT,
337
+ port,
338
+ stdoutPath: logs.out,
339
+ stderrPath: logs.err,
340
+ };
341
+ const unit = buildSystemdUnit(opts);
342
+ const unitPath = systemdUnitPath();
343
+
344
+ if (dryRun) {
345
+ console.log(`# Would write unit to: ${unitPath}`);
346
+ console.log(`# Log dir: ${logs.dir}`);
347
+ console.log('# Would run: systemctl --user daemon-reload');
348
+ console.log(`# Would run: systemctl --user enable --now ${UNIT_NAME}`);
349
+ console.log('# --- unit contents ---');
350
+ console.log(unit);
351
+ return 0;
352
+ }
353
+
354
+ mkdirSync(dirname(unitPath), { recursive: true });
355
+ mkdirSync(logs.dir, { recursive: true });
356
+ writeFileSync(unitPath, unit, 'utf8');
357
+ console.log(`Wrote unit: ${unitPath}`);
358
+
359
+ try {
360
+ execSync('systemctl --user daemon-reload', { stdio: 'pipe' });
361
+ execSync(`systemctl --user enable --now ${UNIT_NAME}`, { stdio: 'pipe' });
362
+ } catch (err) {
363
+ throw Object.assign(new Error(`systemctl failed: ${err.message}`), { exitCode: 3 });
364
+ }
365
+
366
+ console.log(`Enabled + started: ${UNIT_NAME}`);
367
+ console.log(`Logs: ${logs.out}`);
368
+ console.log(` ${logs.err}`);
369
+ console.log(`URL: http://127.0.0.1:${port}/`);
370
+ return 0;
371
+ }
372
+
373
+ function linuxUninstall({ dryRun }) {
374
+ const unitPath = systemdUnitPath();
375
+ if (dryRun) {
376
+ console.log(`# Would run: systemctl --user disable --now ${UNIT_NAME}`);
377
+ console.log('# Would run: systemctl --user daemon-reload');
378
+ console.log(`# Would remove: ${unitPath}`);
379
+ return 0;
380
+ }
381
+
382
+ try {
383
+ execSync(`systemctl --user disable --now ${UNIT_NAME}`, { stdio: 'pipe' });
384
+ } catch { /* not installed — fine */ }
385
+
386
+ if (existsSync(unitPath)) {
387
+ try {
388
+ unlinkSync(unitPath);
389
+ console.log(`Removed unit: ${unitPath}`);
390
+ } catch (err) {
391
+ throw Object.assign(new Error(`Could not remove unit: ${err.message}`), { exitCode: 3 });
392
+ }
393
+ } else {
394
+ console.log(`No unit file at ${unitPath} — nothing to remove.`);
395
+ }
396
+
397
+ try {
398
+ execSync('systemctl --user daemon-reload', { stdio: 'pipe' });
399
+ } catch { /* non-fatal */ }
400
+
401
+ console.log(`Disabled: ${UNIT_NAME}`);
402
+ return 0;
403
+ }
404
+
405
+ function linuxStatus() {
406
+ const unitPath = systemdUnitPath();
407
+ const unitExists = existsSync(unitPath);
408
+ console.log(`Unit: ${unitPath} (${unitExists ? 'present' : 'absent'})`);
409
+
410
+ try {
411
+ const active = execSync(`systemctl --user is-active ${UNIT_NAME}`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
412
+ console.log(`Service ${UNIT_NAME}: ${active}`);
413
+ return active === 'active' ? 0 : 2;
414
+ } catch {
415
+ console.log(`Service ${UNIT_NAME}: not active or not installed.`);
416
+ return unitExists ? 2 : 0;
417
+ }
418
+ }
419
+
420
+ // --- Windows stub -------------------------------------------------------
421
+
422
+ function windowsNotSupported() {
423
+ console.error('Error: Windows service installation is not yet implemented.');
424
+ console.error('Open an issue on Stravica/dave if you need this, or run the');
425
+ console.error('workspace manually with: pa workspace start (or node node_modules/@stravica-ai/engineering-pa-workspace/src/ws.mjs start)');
426
+ return 2;
427
+ }
428
+
429
+ // --- Platform dispatcher -------------------------------------------------
430
+
431
+ /**
432
+ * Route to the correct backend for the host platform.
433
+ * Exported so tests can exercise the routing independently of real OS calls.
434
+ * @param {string} plat - platform() return value
435
+ * @returns {string} - 'darwin' | 'linux' | 'win32' | 'unsupported'
436
+ */
437
+ export function routePlatform(plat) {
438
+ if (plat === 'darwin') return 'darwin';
439
+ if (plat === 'linux') return 'linux';
440
+ if (plat === 'win32') return 'win32';
441
+ return 'unsupported';
442
+ }
443
+
444
+ // --- Shell quoting ------------------------------------------------------
445
+
446
+ /**
447
+ * Quote a path for inclusion in a shell command. launchctl/systemctl invocations
448
+ * go through the shell via execSync, so paths with spaces need quoting.
449
+ * @param {string} s
450
+ */
451
+ function shellQuote(s) {
452
+ if (!/[^A-Za-z0-9_\-./]/.test(s)) return s;
453
+ return `'${String(s).replace(/'/g, `'\\''`)}'`;
454
+ }
455
+
456
+ // --- CLI ----------------------------------------------------------------
457
+
458
+ const USAGE = `Usage: node install-daemon.mjs <command> [options]
459
+
460
+ Commands:
461
+ install [--port N] [--dry-run] Install + start the workspace daemon
462
+ uninstall [--dry-run] Stop + remove the daemon
463
+ status Show daemon status
464
+ --help, -h Show this help
465
+
466
+ Options:
467
+ --port N Override the port (default: reads operator/config/preferences.json, falls back to 4200)
468
+ --dry-run Print what would happen; do not write files or invoke the service manager
469
+
470
+ Exit codes:
471
+ 0 OK
472
+ 1 Usage error
473
+ 2 Unsupported platform / logical failure
474
+ 3 Transport failure (launchctl/systemctl call)
475
+ `;
476
+
477
+ function parseArgs(argv) {
478
+ const out = { command: null, port: undefined, dryRun: false };
479
+ const args = argv.slice();
480
+ while (args.length > 0) {
481
+ const a = args.shift();
482
+ if (a === '--help' || a === '-h') { out.command = 'help'; continue; }
483
+ if (a === '--dry-run') { out.dryRun = true; continue; }
484
+ if (a === '--port') { out.port = args.shift(); continue; }
485
+ if (out.command === null) { out.command = a; continue; }
486
+ throw Object.assign(new Error(`Unexpected argument: ${a}`), { exitCode: 1 });
487
+ }
488
+ return out;
489
+ }
490
+
491
+ export async function main(argv) {
492
+ let parsed;
493
+ try {
494
+ parsed = parseArgs(argv);
495
+ } catch (err) {
496
+ console.error(`Error: ${err.message}`);
497
+ console.error(USAGE);
498
+ return err.exitCode || 1;
499
+ }
500
+
501
+ if (parsed.command === 'help' || parsed.command === null) {
502
+ console.log(USAGE);
503
+ return parsed.command === null ? 1 : 0;
504
+ }
505
+
506
+ let port = null;
507
+ if (parsed.command === 'install') {
508
+ try {
509
+ port = resolvePort(parsed.port);
510
+ } catch (err) {
511
+ console.error(`Error: ${err.message}`);
512
+ return err.exitCode || 1;
513
+ }
514
+ }
515
+ const plat = routePlatform(platform());
516
+
517
+ if (plat === 'unsupported') {
518
+ console.error(`Error: Platform ${platform()} is not supported.`);
519
+ return 2;
520
+ }
521
+ if (plat === 'win32') {
522
+ if (parsed.command === 'install' || parsed.command === 'uninstall' || parsed.command === 'status') {
523
+ return windowsNotSupported();
524
+ }
525
+ }
526
+
527
+ switch (parsed.command) {
528
+ case 'install':
529
+ if (plat === 'darwin') return darwinInstall({ port, dryRun: parsed.dryRun });
530
+ if (plat === 'linux') return linuxInstall({ port, dryRun: parsed.dryRun });
531
+ break;
532
+ case 'uninstall':
533
+ if (plat === 'darwin') return darwinUninstall({ dryRun: parsed.dryRun });
534
+ if (plat === 'linux') return linuxUninstall({ dryRun: parsed.dryRun });
535
+ break;
536
+ case 'status':
537
+ if (plat === 'darwin') return darwinStatus();
538
+ if (plat === 'linux') return linuxStatus();
539
+ break;
540
+ default:
541
+ console.error(`Error: Unknown command '${parsed.command}'.`);
542
+ console.error(USAGE);
543
+ return 1;
544
+ }
545
+ return 1;
546
+ }
547
+
548
+ // --- Entry point --------------------------------------------------------
549
+ //
550
+ // Under pnpm's hoisted layout, `import.meta.url` realpath-resolves through
551
+ // `.pnpm/...` while `process.argv[1]` keeps the symlinked path. A naive
552
+ // equality check would always be false and the CLI would silently no-op.
553
+ // Realpath both sides so the comparison reflects file identity. If argv[1]
554
+ // is unset or unresolvable (e.g. imported by tests), treat as not-main.
555
+
556
+ const isMainModule = (() => {
557
+ if (!process.argv[1]) return false;
558
+ try {
559
+ return import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href;
560
+ } catch {
561
+ return false;
562
+ }
563
+ })();
564
+
565
+ if (isMainModule) {
566
+ try {
567
+ const code = await main(process.argv.slice(2));
568
+ process.exit(code);
569
+ } catch (err) {
570
+ console.error(`Error: ${err.message}`);
571
+ process.exit(err.exitCode || 3);
572
+ }
573
+ }