@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,302 @@
1
+ // probes.mjs — Node-only environment probes. Cross-platform (macOS + Linux
2
+ // + Windows) — uses only stdlib. No shell scripts, no `which`, no `test -e`,
3
+ // no `curl`, no `wget`. Timeouts on every network probe so a broken
4
+ // resolver / firewall can't stall boot.
5
+
6
+ import { execFile } from 'node:child_process';
7
+ import { existsSync, readdirSync, statSync, readFileSync } from 'node:fs';
8
+ import { promisify } from 'node:util';
9
+ import { arch, platform, release, homedir } from 'node:os';
10
+ import { basename, join, resolve, dirname } from 'node:path';
11
+ import { resolve4 } from 'node:dns/promises';
12
+ import { fileURLToPath } from 'node:url';
13
+
14
+ const execFileP = promisify(execFile);
15
+
16
+ const NETWORK_TIMEOUT_MS = 3000;
17
+ const VERSION_TIMEOUT_MS = 3000;
18
+
19
+ /**
20
+ * Probe platform facts (OS/kernel/shell). Fast — no child process, no
21
+ * network.
22
+ */
23
+ export function probePlatform() {
24
+ return {
25
+ os: platform(),
26
+ arch: arch(),
27
+ kernel: release(),
28
+ shell: process.env.SHELL || process.env.COMSPEC || null,
29
+ };
30
+ }
31
+
32
+ /**
33
+ * Probe runtime versions (node, pnpm, git). Parallel; each capped at
34
+ * VERSION_TIMEOUT_MS.
35
+ */
36
+ export async function probeRuntimes() {
37
+ const targets = ['node', 'pnpm', 'git'];
38
+ const results = await Promise.all(targets.map((name) => probeRuntime(name)));
39
+ const out = {};
40
+ for (let i = 0; i < targets.length; i++) {
41
+ out[targets[i]] = results[i];
42
+ }
43
+ return out;
44
+ }
45
+
46
+ async function probeRuntime(name) {
47
+ if (name === 'node') {
48
+ // Fast path — we're running under node, no need to shell out.
49
+ return { version: process.versions.node, path: process.execPath };
50
+ }
51
+ return runVersionProbe(name);
52
+ }
53
+
54
+ async function runVersionProbe(binName) {
55
+ try {
56
+ const { stdout } = await execFileP(binName, ['--version'], { timeout: VERSION_TIMEOUT_MS });
57
+ const version = stdout.trim().split('\n')[0];
58
+ const path = await resolveBinPath(binName);
59
+ return { version, path };
60
+ } catch (err) {
61
+ if (err.code === 'ENOENT') {
62
+ return { version: null, path: null, error: 'not installed' };
63
+ }
64
+ return { version: null, path: null, error: err.message };
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Resolve a bin path cross-platform without invoking `which`. Walks PATH
70
+ * looking for a matching executable.
71
+ */
72
+ async function resolveBinPath(binName) {
73
+ const isWin = process.platform === 'win32';
74
+ const pathEnv = process.env.PATH || '';
75
+ const sep = isWin ? ';' : ':';
76
+ const exts = isWin ? (process.env.PATHEXT || '.EXE;.CMD;.BAT').split(';') : [''];
77
+ const parts = pathEnv.split(sep).filter(Boolean);
78
+ for (const dir of parts) {
79
+ for (const ext of exts) {
80
+ const candidate = join(dir, binName + ext);
81
+ try {
82
+ if (existsSync(candidate)) return candidate;
83
+ } catch {
84
+ // ignore per-candidate errors — resolution is best-effort
85
+ }
86
+ }
87
+ }
88
+ return null;
89
+ }
90
+
91
+ /**
92
+ * Introspect the platform CLI surface. Reads `pa` and other bundled bins
93
+ * from node_modules if available; otherwise reports installed=false.
94
+ */
95
+ export function probePlatformCli(repoRoot) {
96
+ const bins = ['pa', 'desk', 'sync', 'secrets', 'scheduler', 'smoke', 'distill', 'memory-sync', 'pa-init', 'slice', 'launch', 'migrate-inspect'];
97
+ const pkgJsonPath = join(repoRoot, 'node_modules', '@stravica-ai', 'digital-operator-pa', 'package.json');
98
+ let version = null;
99
+ if (existsSync(pkgJsonPath)) {
100
+ try {
101
+ const meta = JSON.parse(readFileSync(pkgJsonPath, 'utf8'));
102
+ version = meta.version ?? null;
103
+ } catch {
104
+ version = null;
105
+ }
106
+ }
107
+ const out = {};
108
+ for (const bin of bins) {
109
+ const shimPath = join(repoRoot, 'node_modules', '.bin', bin);
110
+ if (existsSync(shimPath)) {
111
+ out[bin] = { version, path: shimPath };
112
+ } else {
113
+ out[bin] = { version: null, path: null, installed: false };
114
+ }
115
+ }
116
+ return out;
117
+ }
118
+
119
+ /**
120
+ * List operator extension tools. Each subdir under
121
+ * operator/extensions/tools/ counts. Missing dir returns an empty array.
122
+ */
123
+ export function probeCustomTools(repoRoot) {
124
+ const dir = join(repoRoot, 'operator', 'extensions', 'tools');
125
+ if (!existsSync(dir)) return [];
126
+ try {
127
+ return readdirSync(dir)
128
+ .filter((name) => !name.startsWith('.'))
129
+ .filter((name) => statSync(join(dir, name)).isDirectory())
130
+ .map((name) => ({ name, path: join(dir, name) }));
131
+ } catch {
132
+ return [];
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Network probes — DNS (github.com by default) and HTTP HEAD (cloudflare
138
+ * DNS by default). Both capped at NETWORK_TIMEOUT_MS. Failures record an
139
+ * `error` field but do NOT block the write.
140
+ */
141
+ export async function probeNetwork({ dnsTarget = 'github.com', httpTarget = 'https://1.1.1.1', skip = false } = {}) {
142
+ if (skip) {
143
+ return {
144
+ dns: { target: dnsTarget, skipped: true },
145
+ http: { target: httpTarget, skipped: true },
146
+ };
147
+ }
148
+ const [dns, http] = await Promise.all([
149
+ probeDns(dnsTarget),
150
+ probeHttp(httpTarget),
151
+ ]);
152
+ return { dns, http };
153
+ }
154
+
155
+ async function probeDns(target) {
156
+ const start = Date.now();
157
+ try {
158
+ const result = await withTimeout(resolve4(target), NETWORK_TIMEOUT_MS);
159
+ return { target, resolved: result, elapsedMs: Date.now() - start };
160
+ } catch (err) {
161
+ return { target, resolved: null, elapsedMs: Date.now() - start, error: err.message };
162
+ }
163
+ }
164
+
165
+ async function probeHttp(target) {
166
+ const start = Date.now();
167
+ try {
168
+ const url = new URL(target);
169
+ const mod = url.protocol === 'https:' ? await import('node:https') : await import('node:http');
170
+ const res = await withTimeout(new Promise((res, rej) => {
171
+ const req = mod.request({
172
+ hostname: url.hostname,
173
+ port: url.port || (url.protocol === 'https:' ? 443 : 80),
174
+ path: url.pathname + url.search,
175
+ method: 'HEAD',
176
+ timeout: NETWORK_TIMEOUT_MS,
177
+ }, (r) => {
178
+ r.resume(); // drain
179
+ res({ statusCode: r.statusCode });
180
+ });
181
+ req.on('error', rej);
182
+ req.on('timeout', () => {
183
+ req.destroy(new Error('timeout'));
184
+ });
185
+ req.end();
186
+ }), NETWORK_TIMEOUT_MS);
187
+ return { target, statusCode: res.statusCode, elapsedMs: Date.now() - start };
188
+ } catch (err) {
189
+ return { target, statusCode: null, elapsedMs: Date.now() - start, error: err.message };
190
+ }
191
+ }
192
+
193
+ async function withTimeout(promise, ms) {
194
+ let timer;
195
+ const timeoutPromise = new Promise((_, rej) => {
196
+ timer = setTimeout(() => rej(new Error(`timeout after ${ms}ms`)), ms);
197
+ });
198
+ try {
199
+ return await Promise.race([promise, timeoutPromise]);
200
+ } finally {
201
+ if (timer) clearTimeout(timer);
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Workspace port + reachability. Reads port from operator preferences if
207
+ * present; probes with a TCP connect (fast — no HTTP round-trip). Timeout
208
+ * capped at 1s.
209
+ */
210
+ export async function probeWorkspace(repoRoot) {
211
+ const port = readWorkspacePort(repoRoot);
212
+ const net = await import('node:net');
213
+ const running = await new Promise((res) => {
214
+ const socket = new net.Socket();
215
+ let done = false;
216
+ const finish = (value) => {
217
+ if (done) return;
218
+ done = true;
219
+ try { socket.destroy(); } catch { /* ignore */ }
220
+ res(value);
221
+ };
222
+ socket.setTimeout(1000);
223
+ socket.once('connect', () => finish(true));
224
+ socket.once('error', () => finish(false));
225
+ socket.once('timeout', () => finish(false));
226
+ socket.connect(port, '127.0.0.1');
227
+ });
228
+ return {
229
+ port,
230
+ running,
231
+ url: `http://localhost:${port}`,
232
+ };
233
+ }
234
+
235
+ function readWorkspacePort(repoRoot) {
236
+ try {
237
+ const prefsPath = join(repoRoot, 'operator', 'config', 'preferences.json');
238
+ if (existsSync(prefsPath)) {
239
+ const prefs = JSON.parse(readFileSync(prefsPath, 'utf8'));
240
+ if (typeof prefs.workspacePort === 'number') return prefs.workspacePort;
241
+ }
242
+ } catch {
243
+ // fall through
244
+ }
245
+ return 4200;
246
+ }
247
+
248
+ /**
249
+ * Working directory + project root resolution. Search-upward for an
250
+ * `agents/<name>/CLAUDE.md` marker or a `.git` ancestor. Env var override
251
+ * honoured — any `<...>_ROOT` env var whose value is a valid prefix of cwd.
252
+ */
253
+ export function probeWorkingDirectory(cwd = process.cwd()) {
254
+ const projectRoot = findProjectRoot(cwd);
255
+ return {
256
+ cwd,
257
+ projectRoot: projectRoot?.path ?? null,
258
+ resolvedVia: projectRoot?.via ?? 'unresolved',
259
+ };
260
+ }
261
+
262
+ function findProjectRoot(cwd) {
263
+ // 1. Any *_ROOT env var whose value contains cwd.
264
+ for (const [name, value] of Object.entries(process.env)) {
265
+ if (!name.endsWith('_ROOT')) continue;
266
+ if (typeof value !== 'string' || value.length === 0) continue;
267
+ const abs = resolve(value);
268
+ if (cwd.startsWith(abs)) {
269
+ return { path: abs, via: `env:${name}` };
270
+ }
271
+ }
272
+ // 2. Walk upward looking for an agents/<name>/CLAUDE.md marker.
273
+ let d = cwd;
274
+ while (d && d !== dirname(d)) {
275
+ const agentsDir = join(d, 'agents');
276
+ if (existsSync(agentsDir)) {
277
+ try {
278
+ const children = readdirSync(agentsDir);
279
+ for (const child of children) {
280
+ if (existsSync(join(agentsDir, child, 'CLAUDE.md'))) {
281
+ return { path: d, via: 'agents-marker' };
282
+ }
283
+ }
284
+ } catch {
285
+ // ignore; keep walking
286
+ }
287
+ }
288
+ d = dirname(d);
289
+ }
290
+ // 3. Walk upward looking for .git.
291
+ d = cwd;
292
+ while (d && d !== dirname(d)) {
293
+ if (existsSync(join(d, '.git'))) {
294
+ return { path: d, via: 'git-ancestor' };
295
+ }
296
+ d = dirname(d);
297
+ }
298
+ return null;
299
+ }
300
+
301
+ // Test seam — expose the module's own dir for callers that want it.
302
+ export const __moduleDir = dirname(fileURLToPath(import.meta.url));
@@ -0,0 +1,148 @@
1
+ // auth.mjs — Service-account credential loading for Google Search Console.
2
+ //
3
+ // Reads the SA JSON from the SOPS vault under the configured key (default
4
+ // GSC_SERVICE_ACCOUNT_KEY) and constructs a JWT-authenticated client
5
+ // scoped for Search Console.
6
+ //
7
+ // All Google SDK imports are lazy — tests inject a mock `googleClient`
8
+ // override and never touch the network. The SA-key read also accepts an
9
+ // override so tests can pass in a synthetic key without going through SOPS.
10
+
11
+ import { defaultPaths, checkVault, secretsFileExists, sopsDecrypt, VaultError } from '../secrets/vault.mjs';
12
+
13
+ // Read-only scope: searchanalytics.query + sites.list + sitemaps.list.
14
+ // Read-write scope: sites.add, sitemaps.submit, site verification.
15
+ // We always use the read-write scope — the same client services every verb
16
+ // and the operator has explicitly granted the SA per-property, so there is
17
+ // no privilege-escalation risk inside the SA's own GSC surface.
18
+ export const GSC_SCOPES = [
19
+ 'https://www.googleapis.com/auth/webmasters',
20
+ 'https://www.googleapis.com/auth/siteverification',
21
+ ];
22
+
23
+ const DEFAULT_VAULT_KEY = 'GSC_SERVICE_ACCOUNT_KEY';
24
+
25
+ /**
26
+ * Load the service-account JSON object from the SOPS vault.
27
+ *
28
+ * @param {object} overrides
29
+ * @param {object} [overrides.paths] Vault paths (from defaultPaths()).
30
+ * @param {string} [overrides.vaultKey] Vault key name (default GSC_SERVICE_ACCOUNT_KEY).
31
+ * @param {string} [overrides.serviceAccountKey]
32
+ * Raw SA JSON string. If provided, skips vault entirely (testing).
33
+ * @returns {Promise<object>} Parsed service-account JSON.
34
+ */
35
+ export async function loadServiceAccountKey(overrides = {}) {
36
+ if (overrides.serviceAccountKey) {
37
+ return typeof overrides.serviceAccountKey === 'string'
38
+ ? JSON.parse(overrides.serviceAccountKey)
39
+ : overrides.serviceAccountKey;
40
+ }
41
+
42
+ const paths = overrides.paths || defaultPaths();
43
+ const vaultKey = overrides.vaultKey || DEFAULT_VAULT_KEY;
44
+
45
+ const state = checkVault(paths);
46
+ if (!state.ok) {
47
+ throw new VaultError(state.message, state.exitCode ?? 1);
48
+ }
49
+ if (!secretsFileExists(paths)) {
50
+ throw new VaultError(
51
+ `No secrets file at ${paths.secretsFile}. Run 'secrets init' first.`,
52
+ 1,
53
+ );
54
+ }
55
+ const data = await sopsDecrypt(paths, paths.secretsFile);
56
+ if (!(vaultKey in data)) {
57
+ throw new VaultError(
58
+ `Vault key "${vaultKey}" not found. Store the service-account JSON with:\n secrets set ${vaultKey} -\n(then paste the JSON, then Ctrl-D)`,
59
+ 1,
60
+ );
61
+ }
62
+ const raw = data[vaultKey];
63
+ try {
64
+ return typeof raw === 'string' ? JSON.parse(raw) : raw;
65
+ } catch (e) {
66
+ throw new VaultError(
67
+ `Vault key "${vaultKey}" is not valid JSON: ${e.message}`,
68
+ 2,
69
+ );
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Build a Google Search Console client (webmasters v3 + siteverification v1).
75
+ *
76
+ * The Google SDK packages are imported lazily so the rest of the CLI
77
+ * (and tests for non-Google paths) work without them being installed.
78
+ *
79
+ * @param {object} overrides
80
+ * @param {object} [overrides.googleClient] Pre-built client (for tests).
81
+ * Shape: { webmasters, siteVerification }
82
+ * @returns {Promise<{webmasters: object, siteVerification: object}>}
83
+ */
84
+ export async function buildGscClient(overrides = {}) {
85
+ if (overrides.googleClient) return overrides.googleClient;
86
+
87
+ const key = await loadServiceAccountKey(overrides);
88
+
89
+ let googleapis;
90
+ let googleAuthLibrary;
91
+ try {
92
+ googleapis = await import('googleapis');
93
+ googleAuthLibrary = await import('google-auth-library');
94
+ } catch (e) {
95
+ throw Object.assign(
96
+ new Error(
97
+ 'Google SDK packages not installed. Run `pnpm install` in the ' +
98
+ 'package root so `googleapis` and `google-auth-library` are ' +
99
+ 'available. (' + e.message + ')',
100
+ ),
101
+ { exitCode: 3 },
102
+ );
103
+ }
104
+
105
+ const { JWT } = googleAuthLibrary;
106
+ const auth = new JWT({
107
+ email: key.client_email,
108
+ key: key.private_key,
109
+ scopes: GSC_SCOPES,
110
+ });
111
+
112
+ const { google } = googleapis;
113
+ return {
114
+ webmasters: google.webmasters({ version: 'v3', auth }),
115
+ siteVerification: google.siteVerification({ version: 'v1', auth }),
116
+ auth,
117
+ };
118
+ }
119
+
120
+ /**
121
+ * Normalise a domain into the GSC domain-property siteUrl form.
122
+ *
123
+ * foo.com -> sc-domain:foo.com
124
+ * www.foo.com -> sc-domain:www.foo.com
125
+ * sc-domain:foo.com -> sc-domain:foo.com (idempotent)
126
+ * https://foo.com -> sc-domain:foo.com (strip scheme + path)
127
+ *
128
+ * Domain-property is the modern GSC default (covers https + http + all
129
+ * subdomains under a single property). URL-prefix properties are legacy.
130
+ */
131
+ export function toDomainProperty(input) {
132
+ if (!input) throw new Error('domain is required');
133
+ let s = String(input).trim();
134
+ if (s.startsWith('sc-domain:')) return s;
135
+ // Strip scheme + any path.
136
+ s = s.replace(/^https?:\/\//i, '');
137
+ s = s.split('/')[0];
138
+ // Strip trailing dot if present.
139
+ s = s.replace(/\.$/, '');
140
+ return `sc-domain:${s.toLowerCase()}`;
141
+ }
142
+
143
+ /**
144
+ * Strip `sc-domain:` prefix from a property URL, returning the bare domain.
145
+ */
146
+ export function bareDomain(siteUrl) {
147
+ return String(siteUrl || '').replace(/^sc-domain:/, '');
148
+ }
@@ -0,0 +1,93 @@
1
+ // gsc — Google Search Console subcommand router.
2
+ //
3
+ // Wired as `pa gsc <verb>` (verb-second pattern, mirrors `pa workspace`).
4
+ // Each verb routes to a command module under ./commands/.
5
+ //
6
+ // Exit codes (@stravica-ai/engineering-pa-core/docs/standards/tooling.md §6):
7
+ // 0 ok | 1 usage error | 2 operational failure | 3 transport/IO failure
8
+
9
+ import { runAddProperty } from './commands/add-property.mjs';
10
+ import { runVerifyViaCfDns } from './commands/verify-via-cf-dns.mjs';
11
+ import { runSubmitSitemap } from './commands/submit-sitemap.mjs';
12
+ import { runPullAnalytics } from './commands/pull-analytics.mjs';
13
+ import { runListProperties } from './commands/list-properties.mjs';
14
+
15
+ const HELP = `pa gsc — Google Search Console automation
16
+
17
+ Usage:
18
+ pa gsc add-property <domain>
19
+ Register a domain-property in Search Console (sites.add).
20
+ Returns the verification TXT token.
21
+
22
+ pa gsc verify-via-cf-dns <domain> [--wait SECONDS] [--account NAME]
23
+ Plant the GSC verification TXT record at the domain's Cloudflare
24
+ zone, wait for propagation, then trigger GSC verification.
25
+ --account selects which Cloudflare account's vault keys to use
26
+ (e.g. --account stravica, --account clive). Omit for the default
27
+ (unsuffixed) vault pair.
28
+
29
+ pa gsc submit-sitemap <domain> <sitemap-url>
30
+ Submit a sitemap to GSC for the property.
31
+
32
+ pa gsc pull-analytics <domain> [--days N] [--dimensions D1,D2,...] [--rows N]
33
+ Pull search-analytics rows. Defaults: --days 28 --dimensions query
34
+ --rows 100. Outputs a JSON array on stdout.
35
+
36
+ pa gsc list-properties
37
+ List every GSC property the service account can see. Useful for
38
+ verifying SA setup ("did I add the SA email as a user on the right
39
+ property?").
40
+
41
+ pa gsc -h, --help
42
+ Show this help.
43
+
44
+ Auth (one-time setup; see docs/gsc.md):
45
+ - Google service-account JSON stored in the SOPS vault under
46
+ GSC_SERVICE_ACCOUNT_KEY (entire JSON contents as the value).
47
+ - SA email added as a user on each GSC property via the GSC dashboard.
48
+
49
+ Cloudflare DNS planting reads two vault keys. Resolution order:
50
+ 1. With --account <name>: CLOUDFLARE_PAGES_API_KEY_<NAME> +
51
+ CLOUDFLARE_PAGES_ACCOUNT_ID_<NAME>
52
+ (e.g. --account stravica -> *_STRAVICA pair)
53
+ 2. Without --account: CLOUDFLARE_PAGES_API_KEY +
54
+ CLOUDFLARE_PAGES_ACCOUNT_ID
55
+ 3. Legacy fallback: CLOUDFLARE_API_TOKEN +
56
+ CLOUDFLARE_ACCOUNT_ID
57
+ `;
58
+
59
+ export async function run(argv, overrides = {}) {
60
+ const verb = argv[0];
61
+ const rest = argv.slice(1);
62
+
63
+ if (!verb || verb === '--help' || verb === '-h' || verb === 'help') {
64
+ process.stdout.write(HELP);
65
+ return verb ? 0 : 1;
66
+ }
67
+
68
+ switch (verb) {
69
+ case 'add-property': return runAddProperty(rest, overrides);
70
+ case 'verify-via-cf-dns': return runVerifyViaCfDns(rest, overrides);
71
+ case 'submit-sitemap': return runSubmitSitemap(rest, overrides);
72
+ case 'pull-analytics': return runPullAnalytics(rest, overrides);
73
+ case 'list-properties': return runListProperties(rest, overrides);
74
+ default: {
75
+ process.stderr.write(`[pa gsc] unknown verb: ${verb}\n`);
76
+ process.stderr.write(HELP);
77
+ return 1;
78
+ }
79
+ }
80
+ }
81
+
82
+ export async function main(argv, overrides = {}) {
83
+ try {
84
+ const code = await run(argv, overrides);
85
+ return code ?? 0;
86
+ } catch (err) {
87
+ const code = err && typeof err.exitCode === 'number' ? err.exitCode : 2;
88
+ if (!err || err.exitCode == null) {
89
+ process.stderr.write(`pa gsc: ${err && err.message ? err.message : err}\n`);
90
+ }
91
+ return code;
92
+ }
93
+ }