@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,175 @@
1
+ # Google Search Console (`pa gsc`)
2
+
3
+ `pa gsc` automates Google Search Console onboarding and analytics across any
4
+ domain whose DNS lives on Cloudflare in an account the operator controls.
5
+
6
+ ## Status
7
+
8
+ Implemented: `add-property`, `verify-via-cf-dns`, `submit-sitemap`,
9
+ `pull-analytics`, `list-properties`. Auth via Google service-account JSON
10
+ loaded from the SOPS vault. Cloudflare planting via the CF v4 REST API.
11
+
12
+ ## Dependencies
13
+
14
+ Two npm packages (declared in `@stravica-ai/digital-operator-pa`):
15
+
16
+ - `googleapis` — the canonical Node SDK for Google Cloud APIs.
17
+ - `google-auth-library` — JWT auth helper used by `googleapis`.
18
+
19
+ ## Operator setup (one-time per platform install)
20
+
21
+ 1. **Create a Google Cloud project** dedicated to GSC automation. Pick a
22
+ short name like `gsc-automation-prod`.
23
+
24
+ 2. **Enable the APIs** in that project:
25
+ - Search Console API:
26
+ https://console.cloud.google.com/apis/library/searchconsole.googleapis.com
27
+ - Site Verification API:
28
+ https://console.cloud.google.com/apis/library/siteverification.googleapis.com
29
+
30
+ 3. **Create a service account** under IAM & Admin → Service accounts:
31
+ - Name: `gsc-automation`
32
+ - No project-level roles needed (GSC permissions are granted per-property
33
+ in the GSC dashboard, not at GCP IAM level).
34
+
35
+ 4. **Generate a JSON key** for the service account (Keys tab → Add Key →
36
+ JSON). Download the file — this is the SA key.
37
+
38
+ 5. **Store the SA key in the SOPS vault**:
39
+ ```bash
40
+ pnpm exec secrets set GSC_SERVICE_ACCOUNT_KEY -
41
+ # paste the entire JSON contents, then Ctrl-D
42
+ ```
43
+
44
+ 6. **Store Cloudflare credentials** (also one-time). Two key shapes are
45
+ supported; pick whichever fits your setup:
46
+
47
+ **Single-account setup** — one CF account, no `--account` flag needed:
48
+ ```bash
49
+ pnpm exec secrets set CLOUDFLARE_PAGES_API_KEY <token>
50
+ pnpm exec secrets set CLOUDFLARE_PAGES_ACCOUNT_ID <account-id>
51
+ ```
52
+
53
+ **Multi-account setup** — multiple CF accounts, each addressed by name:
54
+ ```bash
55
+ # Stravica account → addressed as --account stravica
56
+ pnpm exec secrets set CLOUDFLARE_PAGES_API_KEY_STRAVICA <token>
57
+ pnpm exec secrets set CLOUDFLARE_PAGES_ACCOUNT_ID_STRAVICA <account-id>
58
+
59
+ # Clive account → addressed as --account clive
60
+ pnpm exec secrets set CLOUDFLARE_PAGES_API_KEY_CLIVE <token>
61
+ pnpm exec secrets set CLOUDFLARE_PAGES_ACCOUNT_ID_CLIVE <account-id>
62
+ ```
63
+
64
+ The CF API token needs `Zone:DNS:Edit` and `Zone:Zone:Read` for any
65
+ zones the tool will operate on. Account-level "Write to all resources"
66
+ tokens also work.
67
+
68
+ For back-compat, the legacy `CLOUDFLARE_API_TOKEN` /
69
+ `CLOUDFLARE_ACCOUNT_ID` pair is read as a last-resort fallback when
70
+ no `--account` flag is passed and the `CLOUDFLARE_PAGES_*` unsuffixed
71
+ pair is absent. Don't rely on it — set the `CLOUDFLARE_PAGES_*` keys.
72
+
73
+ ## Per-domain setup (each time you onboard a new property)
74
+
75
+ 7. **Grant the service-account access to the GSC property.** Until the
76
+ property exists, you can't grant access. So the workflow is:
77
+
78
+ 1. Run `pa gsc verify-via-cf-dns <domain>` — this performs verification
79
+ end-to-end and registers the property under the SA's identity, so
80
+ the SA implicitly has Owner permission.
81
+
82
+ *Or, if a property already exists under a human Google account:*
83
+
84
+ 2. Open Search Console → Settings → Users and permissions →
85
+ Add user, paste the SA email (`<name>@<project>.iam.gserviceaccount.com`),
86
+ grant Owner (or Full).
87
+
88
+ The `pa gsc list-properties` command will then show the property.
89
+
90
+ ## Usage
91
+
92
+ ```bash
93
+ # Get the verification TXT token for a domain (no DNS change yet)
94
+ pnpm exec pa gsc add-property stravica.ai
95
+
96
+ # Plant the TXT in Cloudflare, wait, verify, register
97
+ pnpm exec pa gsc verify-via-cf-dns stravica.ai
98
+ # Optional --wait SECONDS to override the default 60s propagation pause:
99
+ pnpm exec pa gsc verify-via-cf-dns stravica.ai --wait 120
100
+ # Multi-account: select which CF account's vault keys to use:
101
+ pnpm exec pa gsc verify-via-cf-dns stravica.ai --account stravica
102
+ pnpm exec pa gsc verify-via-cf-dns besafetraining.co.uk --account clive
103
+
104
+ # Submit a sitemap
105
+ pnpm exec pa gsc submit-sitemap stravica.ai https://stravica.ai/sitemap.xml
106
+
107
+ # Pull search analytics (default 28d, top queries, 100 rows)
108
+ pnpm exec pa gsc pull-analytics stravica.ai
109
+ pnpm exec pa gsc pull-analytics stravica.ai --days 90 --dimensions query,page --rows 500
110
+
111
+ # List every property the SA can see (sanity-check setup)
112
+ pnpm exec pa gsc list-properties
113
+ ```
114
+
115
+ ## Multi-account selection
116
+
117
+ When `--account <name>` is passed to `verify-via-cf-dns`, the tool resolves
118
+ the Cloudflare credentials by upper-casing the name and looking up the
119
+ corresponding suffixed vault pair. For example:
120
+
121
+ ```
122
+ --account stravica -> CLOUDFLARE_PAGES_API_KEY_STRAVICA
123
+ CLOUDFLARE_PAGES_ACCOUNT_ID_STRAVICA
124
+ --account clive -> CLOUDFLARE_PAGES_API_KEY_CLIVE
125
+ CLOUDFLARE_PAGES_ACCOUNT_ID_CLIVE
126
+ ```
127
+
128
+ If `--account` is passed but the suffixed pair isn't set, the command
129
+ fails fast with a message telling you which key is missing. It does
130
+ **not** silently fall back to the unsuffixed pair — that would defeat
131
+ the safety the flag exists to provide.
132
+
133
+ Without `--account`, resolution order is:
134
+ 1. `CLOUDFLARE_PAGES_API_KEY` + `CLOUDFLARE_PAGES_ACCOUNT_ID`
135
+ 2. Legacy `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` (back-compat
136
+ only; do not rely on this).
137
+
138
+ The account name accepts letters and digits only — anything else is a
139
+ usage error.
140
+
141
+ ## Notes
142
+
143
+ - Properties are always registered as **domain-properties** (`sc-domain:<host>`),
144
+ which cover https + http + every subdomain under a single property. The
145
+ legacy URL-prefix shape is not supported by this tool.
146
+ - The verification TXT record is planted at the **apex** of the domain
147
+ (no `_google-site-verification` subdomain prefix — that is required for
148
+ URL-prefix properties only).
149
+ - The Cloudflare DNS write is **idempotent**: a re-run with the same
150
+ token leaves DNS untouched; a re-run after a token rotation updates
151
+ the existing record in place.
152
+ - Verification can fail if DNS hasn't propagated yet. Re-run with
153
+ `--wait 180` if the default 60s is too short.
154
+
155
+ ## Exit codes
156
+
157
+ ```
158
+ 0 OK
159
+ 1 Usage error / vault uninitialised / domain ambiguous
160
+ 2 Operational failure (Google API, Cloudflare API, verification failed)
161
+ 3 Transport / network / missing SDK
162
+ ```
163
+
164
+ ## Live-test gap
165
+
166
+ The mock test suite covers the auth-construction path, domain
167
+ normalisation, CF API request shape, and the GSC verb plumbing. Live
168
+ testing requires:
169
+
170
+ 1. The operator setup above completed (GCP project + APIs + SA key in vault).
171
+ 2. CF credentials in vault.
172
+ 3. One real domain to verify.
173
+
174
+ After GCP setup, run `pa gsc list-properties` first — it requires no
175
+ DNS or verification and proves the SA key + scopes work end-to-end.
@@ -0,0 +1,139 @@
1
+ # pa lint linkedin
2
+
3
+ Deterministic voice-rule linter for operator-authored LinkedIn text. Loads a
4
+ JSON rule corpus and reports voice-rule violations in **alter-format** — each
5
+ finding tells the writer what to do (`swap → X`, `cut`, `rename`) rather than
6
+ just flagging a banned token.
7
+
8
+ ## Why this exists
9
+
10
+ Voice rules that are machine-checkable should be machine-checked, not left to a
11
+ prompt instruction the writer mentally verifies against. Three voice failures
12
+ shipped in one week despite a pre-delivery checklist (a forced "isn't X, it's Y"
13
+ contrast, a `the right cut` reaction phrase reused across sibling replies, an
14
+ `Indeed..` opener repeated across replies). This linter moves those rules into a
15
+ validator. The framing is deliberately **alter, not block**: the writer is more
16
+ reliable picking from a known target than avoiding a blacklist, so every rule
17
+ carries its swap / cut / rename guidance inline.
18
+
19
+ ## Usage
20
+
21
+ ```sh
22
+ pa lint linkedin <input-file> [options]
23
+ ```
24
+
25
+ | Option | Default | Meaning |
26
+ |---|---|---|
27
+ | `--rules <path>` | `operator/knowledge/writing/linkedin-rules.json` under the repo root | Rule corpus JSON. Required if the default file is absent. |
28
+ | `--format <text\|json>` | `text` | Output format. |
29
+ | `--severity <error\|warning\|info>` | `error` | Severity floor — only violations at or above this level are reported. |
30
+ | `--surface <name>` | `linkedin` | Surface context: `all`, `linkedin`, `article`, `newsletter`, `reply`. A rule applies if its `surface` is `all` or includes this value. |
31
+ | `-h, --help` | | Show help. |
32
+
33
+ The default rules path resolves relative to the operator repo root (located via
34
+ `$DAVE_REPO_ROOT` / `$PA_REPO_ROOT`, else by walking up to the nearest `.git`).
35
+ If it is absent and `--rules` is not given, the command exits 3 with guidance.
36
+
37
+ ### Text output
38
+
39
+ One line per violation:
40
+
41
+ ```
42
+ <file>:<line>:<col> <severity> <ruleId> <matched-text> → <alter-guidance>
43
+ ```
44
+
45
+ Example:
46
+
47
+ ```
48
+ post.md:1:14 error punct-em-dash "—" → swap → "," | " - " — Comma or hyphen carries the load.
49
+ post.md:2:7 error vocab-utilize "utilize" → swap → "use" — Plain word.
50
+ ```
51
+
52
+ ### JSON output
53
+
54
+ `--format json` prints an array (`[]` when clean — always valid JSON). Each
55
+ entry:
56
+
57
+ ```json
58
+ {
59
+ "file": "post.md",
60
+ "line": 1,
61
+ "col": 14,
62
+ "ruleId": "punct-em-dash",
63
+ "severity": "error",
64
+ "matched": "—",
65
+ "alter": "swap → \",\" | \" - \" — Comma or hyphen carries the load.",
66
+ "rationale": "Hard AI tell. Operator-mandated permanent rule.",
67
+ "source": "operator/knowledge/writing/voice-guide.md"
68
+ }
69
+ ```
70
+
71
+ ## Exit codes
72
+
73
+ This command uses **lint-semantic exit codes** (ESLint/ruff-style), where the
74
+ code reports the worst severity among the *reported* (post-floor) findings:
75
+
76
+ | Code | Meaning |
77
+ |---|---|
78
+ | `0` | Clean — no findings at/above the floor (info-only also exits 0) |
79
+ | `1` | At least one `error` finding |
80
+ | `2` | `warning` findings only (no errors) |
81
+ | `3` | Usage / IO / config error (bad flag, missing file, malformed corpus) |
82
+
83
+ > **Note — deviation from tooling standard §6.** The platform standard reserves
84
+ > exit `1` for usage errors and `2`/`3` for operational/transport failure. A
85
+ > linter's exit code is load-bearing differently: automation needs to branch on
86
+ > *what was found*, not just *did the tool run*. So this command follows the
87
+ > universal linter convention (`1` = findings, higher = clean-vs-broken) and
88
+ > maps every non-finding failure to `3`. This is the only `pa` verb that
89
+ > deviates, and it does so intentionally.
90
+
91
+ ## Rule corpus schema
92
+
93
+ The corpus is a JSON array of independent rule objects (order does not matter).
94
+ The loader validates strictly — a malformed corpus is a config error (exit 3),
95
+ never a silent skip.
96
+
97
+ ```jsonc
98
+ {
99
+ "ruleId": "punct-em-dash", // kebab-case, unique across the corpus
100
+ "category": "punctuation", // punctuation | vocabulary | phrase |
101
+ // reaction-phrase | filler | structural |
102
+ // format | count
103
+ "surface": ["all"], // any of: all linkedin article newsletter reply
104
+ "severity": "error", // error | warning | info
105
+ "detect": { /* see below */ },
106
+ "alter": { /* see below */ },
107
+ "rationale": "Hard AI tell.", // why the rule exists
108
+ "source": "operator/knowledge/writing/voice-guide.md" // human-readable home
109
+ }
110
+ ```
111
+
112
+ ### `detect`
113
+
114
+ | `type` | Fields | Behaviour |
115
+ |---|---|---|
116
+ | `literal-phrase` | `phrase`, `caseSensitive` (default `false`), `wordBoundary` (default `true`) | Matches the phrase as text. Word boundaries are applied at word-character edges only. |
117
+ | `regex` | `pattern`, `caseSensitive` (default `false`) | Matches the pattern. Scanned line-by-line, so positions are exact and negated classes can't swallow newlines. |
118
+ | `count` | `pattern`, `max` | Counts matches document-wide; flags every occurrence **beyond** `max`. Use `(?:^\|\n)…` anchoring to count line openers. |
119
+
120
+ ### `alter`
121
+
122
+ | `kind` | Fields | Rendered as |
123
+ |---|---|---|
124
+ | `swap` | `with` (array of replacement strings), `guidance` | `swap → "a" \| "b" — guidance` |
125
+ | `cut` | `guidance` | `cut → guidance` |
126
+ | `rename` | `guidance` (open-ended rephrase instruction) | `rename → guidance` |
127
+
128
+ ## Examples
129
+
130
+ ```sh
131
+ # Lint a draft against the default operator corpus.
132
+ pa lint linkedin drafts/post.md
133
+
134
+ # Lint a reply, surfacing warnings too, as JSON.
135
+ pa lint linkedin drafts/reply.md --surface reply --severity warning --format json
136
+
137
+ # Lint against an explicit corpus (e.g. in CI or a fixture).
138
+ pa lint linkedin post.md --rules path/to/linkedin-rules.json
139
+ ```
@@ -0,0 +1,221 @@
1
+ # Secrets Management
2
+
3
+ Identity: `ai.stravica.ops.secrets` — CLI alias `secrets`.
4
+
5
+ Dave uses SOPS with age encryption for secrets management. Secrets are encrypted at rest and stored in `.vault/` within the repository. The encrypted file is safe to commit to git — only the holder of the private key can decrypt it.
6
+
7
+ ## Status
8
+
9
+ Implemented: `init`, `get`, `set`, `list`, `delete`, `rotate`, `status`, `backup`, `vaults`, `find` (alias `which`), `verify`. No npm dependencies — shells out to `sops` and `age` via `node:child_process.spawn`.
10
+
11
+ `set` additionally supports `--canonical-clone PATH` (write a canonical clone's vault file first, then the resolved workspace copy — aborts before touching the workspace copy if the canonical write fails). `verify --values --against PATH` does a byte-level comparison of DECRYPTED values between the resolved vault and a reference vault at PATH — never a decrypt-only pass. See "Value-compare verification" and "Canonical-first writes" below.
12
+
13
+ `get`/`set` run without `--scope`/`--file` now resolve a **default scope** — `$SECRETS_DEFAULT_SCOPE` env var, then `"defaultScope"` in `~/.config/stravica-pa/defaults.json`, then the calling PA's own `agents/<name>/identity.json`, then the legacy single-file vault as a last resort. Every such invocation prints a one-line stderr notice naming the target vault BEFORE the operation runs, including the legacy-fallback case ("no scope specified and no default configured") — see `secrets --help` → "Default scope" for the full precedence and example notices.
14
+
15
+ ## Prerequisites
16
+
17
+ Two tools are required:
18
+
19
+ - **age** — modern encryption tool
20
+ - macOS: `brew install age`
21
+ - Debian/Ubuntu: `sudo apt install age`
22
+ - Manual: https://github.com/FiloSottile/age/releases/latest
23
+
24
+ - **SOPS** — encrypted file editor
25
+ - macOS: `brew install sops`
26
+ - Debian/Ubuntu: download from https://github.com/getsops/sops/releases
27
+ - Manual: https://github.com/getsops/sops/releases/latest
28
+
29
+ ## Invoke
30
+
31
+ The CLI shim is `core/tools/secrets/bin/secrets`. You can run it directly with `node`:
32
+
33
+ ```bash
34
+ node core/tools/secrets/bin/secrets <verb> [ARGS]
35
+ ```
36
+
37
+ Or via the per-tool symlink convention (see tooling standard §14):
38
+
39
+ ```bash
40
+ secrets <verb> [ARGS]
41
+ ```
42
+
43
+ ## Commands
44
+
45
+ ```bash
46
+ # Initialise the vault (generate keys, create config, empty encrypted store)
47
+ node core/tools/secrets/bin/secrets init
48
+
49
+ # Store a secret
50
+ node core/tools/secrets/bin/secrets set API_KEY "sk-abc123"
51
+
52
+ # Retrieve a secret
53
+ node core/tools/secrets/bin/secrets get API_KEY
54
+
55
+ # List all secret names (values are not shown)
56
+ node core/tools/secrets/bin/secrets list
57
+
58
+ # Remove a secret
59
+ node core/tools/secrets/bin/secrets delete API_KEY
60
+
61
+ # Re-encrypt all secrets with the current recipients
62
+ node core/tools/secrets/bin/secrets rotate
63
+
64
+ # Check vault health (exit 0 when initialised, 1 otherwise)
65
+ node core/tools/secrets/bin/secrets status
66
+
67
+ # Open a browser with a QR code of the master key for backup
68
+ node core/tools/secrets/bin/secrets backup
69
+
70
+ # Write a canonical clone's vault FIRST, then the workspace copy second.
71
+ # Aborts (exit 2) before touching the workspace copy if the canonical
72
+ # write fails (e.g. the existing canonical store can't be decrypted).
73
+ node core/tools/secrets/bin/secrets set API_KEY "sk-abc123" --canonical-clone /path/to/canonical/vault/scope.enc.json
74
+
75
+ # Byte-level comparison of DECRYPTED values against a reference vault.
76
+ # --values is required — there is no decrypt-only verification mode
77
+ # (decrypt-only false-passes a vault that decrypts cleanly but holds the
78
+ # wrong content, e.g. a clobbered/stale copy with placeholder values).
79
+ node core/tools/secrets/bin/secrets verify --values --against /path/to/other/vault/scope.enc.json
80
+ ```
81
+
82
+ ### Canonical-first writes (`set --canonical-clone`)
83
+
84
+ Without the flag, `set` behaves exactly as before — it writes only the
85
+ resolved workspace copy. With `--canonical-clone PATH`, `set`:
86
+
87
+ 1. Resolves `PATH` the same way `--file` resolves any other vault (its
88
+ own `.sops.yaml` expected alongside it), reusing this host's own key
89
+ material (`keyDir`/`keyFile`) — the canonical clone and the workspace
90
+ copy are expected to share recipients in practice (same operator,
91
+ same device).
92
+ 2. Decrypts the existing canonical store (if any) and writes the new key
93
+ into it. **If this fails for any reason — the existing canonical
94
+ store can't be decrypted, or the encrypt itself fails — `set` aborts
95
+ with exit 2 and the workspace copy is never touched.**
96
+ 3. Only on canonical success does it proceed to the existing
97
+ decrypt-mutate-encrypt cycle against the resolved workspace copy.
98
+
99
+ This closes the "device-side vault mutation only round-trips halfway"
100
+ class: a device-side `secrets set` that updates the workspace copy but
101
+ never reaches canonical leaves the two vaults silently diverged until the
102
+ next down-path materialisation clobbers the device's fresher value.
103
+ `--canonical-clone` makes the canonical write the FIRST, gating step —
104
+ the workspace never ends up ahead of canonical.
105
+
106
+ ### Value-compare verification (`verify --values --against`)
107
+
108
+ Any vault verification that stops at "the store decrypts" is a false-pass
109
+ waiting to happen: an always-take-canonical materialisation can silently
110
+ overwrite a device's real secret values with stale or placeholder
111
+ content, and the decrypt still succeeds (same recipients) — only a
112
+ byte-level VALUE comparison against a known-good reference catches it.
113
+ `secrets verify` therefore has no decrypt-only mode at all; `--values` is
114
+ required, and omitting it is a usage error (exit 1), not a lesser check.
115
+
116
+ `--against PATH` names the reference vault (any vault file, resolved the
117
+ same way `--file` resolves elsewhere). Both vaults are decrypted and
118
+ compared key-by-key; the report never prints a decrypted value, only the
119
+ per-key result:
120
+
121
+ - `same` — both sides hold byte-identical values
122
+ - `differs` — both sides have the key, values differ
123
+ - `missing-in-reference` — key exists in the working vault only
124
+ - `missing-in-working` — key exists in the reference vault only
125
+
126
+ Exit 0 only when every key is `same`; exit 2 otherwise (or if either side
127
+ fails to decrypt at all).
128
+
129
+ ## Exit codes
130
+
131
+ | Code | Meaning |
132
+ |---|---|
133
+ | `0` | OK |
134
+ | `1` | Usage / not-initialised / not-found |
135
+ | `2` | Operational failure (sops decrypt or encrypt failed, bad JSON) |
136
+ | `3` | Transport failure (spawn failed) |
137
+
138
+ ## Operational discipline
139
+
140
+ - The private key must never be committed. It lives only at `~/.config/dave/age-key.txt`, with mode `600` on a `700` key directory.
141
+ - All sops/age invocations are spawned with arguments as an array — no shell interpolation surface.
142
+ - Tests must never touch the real `~/.config/dave/` or repo `.vault/`. The test helpers mint a disposable temp directory for every case.
143
+
144
+ ## Project layout
145
+
146
+ ```
147
+ core/tools/secrets/
148
+ bin/secrets # node shebang shim — one line
149
+ package.json # name: ai.stravica.ops.secrets, type: module, no deps
150
+ README.md # this file
151
+ src/
152
+ cli.mjs # verb routing + exit-code translation
153
+ vault.mjs # domain + sops/age spawn chokepoint
154
+ commands/
155
+ init.mjs # generate keypair, write recipients/config, empty store
156
+ get.mjs # print a single secret value
157
+ set.mjs # upsert and re-encrypt
158
+ list.mjs # sorted key names
159
+ delete.mjs # remove and re-encrypt
160
+ rotate.mjs # decrypt + re-encrypt with current recipients
161
+ status.mjs # vault health report
162
+ backup.mjs # render QR-code HTML and open it in the default browser
163
+ backup-template.mjs # HTML + embedded alphanumeric QR generator
164
+ vaults.mjs # enumerate every visible vault (names only, no decryption)
165
+ find.mjs # report which vault(s) contain a key by name (alias: which)
166
+ verify.mjs # byte-level DECRYPTED-value comparison against a reference vault
167
+ test/
168
+ helpers.mjs # temp-vault isolation
169
+ *.test.mjs # node:test coverage per subcommand + CLI routing
170
+ ```
171
+
172
+ ## Security model
173
+
174
+ - The **private key** (`~/.config/dave/age-key.txt`) never enters the repository. It is gitignored and lives only on the machine where secrets need to be decrypted.
175
+ - The **public key** (`.vault/recipients.txt`) is committed. It allows anyone with repo access to encrypt new secrets, but only the private key holder can decrypt them.
176
+ - The **encrypted secrets file** (`.vault/secrets.enc.json`) is committed. It is safe to store in git because its contents are encrypted with the age public key.
177
+ - SOPS handles encryption/decryption transparently. The `.vault/.sops.yaml` config tells SOPS which key to use.
178
+
179
+ ## Key rotation
180
+
181
+ If you need to rotate keys (e.g. a machine was compromised):
182
+
183
+ 1. Generate a new keypair: `age-keygen -o ~/.config/dave/age-key.txt`
184
+ 2. Update `.vault/recipients.txt` with the new public key
185
+ 3. Update `.vault/.sops.yaml` with the new public key
186
+ 4. Run `node core/tools/secrets/bin/secrets rotate` to re-encrypt all secrets with the new key
187
+
188
+ Note: you need the old private key present to decrypt before re-encrypting. If the old key is lost, the secrets cannot be recovered.
189
+
190
+ ## Multi-machine setup
191
+
192
+ To use secrets on a second machine:
193
+
194
+ 1. Clone the repository (public key and encrypted secrets are included)
195
+ 2. Copy your private key to `~/.config/dave/age-key.txt` on the new machine
196
+ 3. Secrets are immediately accessible via `node core/tools/secrets/bin/secrets get`
197
+
198
+ The private key must be transferred securely (e.g. via a password manager, secure file transfer, or physical media). Never send it over unencrypted channels.
199
+
200
+ ## Backup
201
+
202
+ Back up `~/.config/dave/age-key.txt` securely. If you lose it, your encrypted secrets are unrecoverable. The encrypted file in git is useless without the private key.
203
+
204
+ The `backup` command renders the master key as a QR code in a temporary HTML file and opens it in the default browser. The file self-destructs after 30 seconds. No browser-automation dependency — the QR generator is a small pure-JS module embedded in the generated HTML.
205
+
206
+ ## Tests
207
+
208
+ ```bash
209
+ node --test core/tools/secrets/test/*.test.mjs
210
+ ```
211
+
212
+ The integration tests require `sops` and `age` on PATH and skip gracefully when either is missing. The CLI-routing tests always run.
213
+
214
+ ## The tooling standard
215
+
216
+ This tool conforms to the standard in [`core/knowledge/standards/tooling.md`](../../knowledge/standards/tooling.md). Notable points:
217
+
218
+ - Zero npm dependencies. Node stdlib only.
219
+ - All external effects (sops, age, fs writes in the vault path) route through `src/vault.mjs`.
220
+ - Commands return numeric exit codes or throw `VaultError` with an `exitCode` property. The CLI wrapper translates to `process.exit`.
221
+ - JSON property names are camelCase.
@@ -0,0 +1,113 @@
1
+ # smoke
2
+
3
+ ## Identity
4
+
5
+ - **Name**: `ai.stravica.platform.smoke`
6
+ - **Alias**: `smoke`
7
+ - **Purpose**: Fresh-clone smoke suite for the Dave platform. Simulates a clean clone and validates structure, server, APIs, and CLI tools before shipping.
8
+
9
+ ## Status
10
+
11
+ Implemented: all 52 assertions from the legacy `test/smoke.sh` (path existence, workspace server boot, HTML page HTTP 200s, JSON API validity, CLI `--help` invocations, `secrets` execution, `dave.sh --help`).
12
+
13
+ Deferred: none. This is a direct Node.js port with no scope change.
14
+
15
+ ## Install / invoke
16
+
17
+ From the repo root:
18
+
19
+ ```sh
20
+ npm run test:smoke
21
+ ```
22
+
23
+ Or invoke the binary directly:
24
+
25
+ ```sh
26
+ node core/tools/smoke/bin/smoke
27
+ ```
28
+
29
+ ## Commands
30
+
31
+ The tool has a single default command; `npm run test:smoke` is the canonical invocation.
32
+
33
+ | Flag | Purpose |
34
+ |-----------------|-----------------------------------------------------------------|
35
+ | `--help, -h` | Print usage and exit 0 |
36
+ | `--root <path>` | Repo root to smoke-test (default: auto-detected from the binary location) |
37
+ | `--port <n>` | HTTP port for the workspace server during the run (default: 4201) |
38
+
39
+ No verbs, no subcommands — this is a single-purpose runner.
40
+
41
+ ## Exit codes
42
+
43
+ | Code | Meaning |
44
+ |------|----------------------------------------------------------------------|
45
+ | `0` | All checks passed |
46
+ | `1` | One or more checks failed, or a usage error (bad argument) |
47
+ | `2` | Internal error (uncaught exception in the tool itself) |
48
+ | `3` | IO / transport failure during setup (tempdir, copy, or server launch)|
49
+
50
+ ## Operational discipline rules
51
+
52
+ - **No side effects on the source tree.** The suite copies the repo into a temp directory (`rm -rf`'d on exit) and performs every assertion against the copy. The source tree is only read.
53
+ - **Single chokepoint for external effects.** `src/runner.mjs` owns every process spawn, HTTP fetch, and filesystem mutation. Commands and checks delegate to it; no other module may spawn or fetch.
54
+ - **Server lifecycle is bracketed.** The workspace server is launched once per run, killed in `finally`, and never leaks across invocations. If a check throws, cleanup still runs.
55
+ - **HTTP / JSON checks are gated.** If the server fails to come up within the ready-probe budget, downstream HTTP and JSON assertions are skipped (not failed) — matching the legacy behaviour.
56
+ - **Zero npm dependencies.** The tool uses only `node:` built-ins (`util`, `child_process`, `fs/promises`, `path`, `os`, `test`, `assert/strict`) plus the global `fetch`.
57
+
58
+ ## Project layout
59
+
60
+ ```
61
+ core/tools/smoke/
62
+ bin/smoke # node shebang shim — one line
63
+ package.json # name, version, type: module, no dependencies
64
+ README.md # this file
65
+ src/
66
+ cli.mjs # parseArgs, --help, exit-code translation
67
+ checks.mjs # pure check plan: path, http, json, cli classes
68
+ runner.mjs # external-effects chokepoint (spawn, fetch, fs)
69
+ commands/
70
+ run.mjs # orchestrates copy → launch → check → cleanup
71
+ test/
72
+ checks.test.mjs # plan shape, parity with legacy smoke.sh
73
+ cli.test.mjs # arg parsing and exit-code cases
74
+ run.test.mjs # orchestration via fake runner
75
+ ```
76
+
77
+ Per-entry rationale:
78
+
79
+ - **`bin/smoke`** — one-line shim; logic lives in `src/cli.mjs`.
80
+ - **`src/cli.mjs`** — the only module that calls `process.exit`. Commands return numbers or throw; this wrapper translates.
81
+ - **`src/checks.mjs`** — pure data + helpers. Defines the ordered plan. No I/O.
82
+ - **`src/runner.mjs`** — chokepoint for every external effect. Tests inject fakes here.
83
+ - **`src/commands/run.mjs`** — the single command that orchestrates the suite.
84
+ - **`test/`** — `node:test` files. No separate config.
85
+
86
+ ## Check plan (parity with legacy `test/smoke.sh`)
87
+
88
+ | Section | Count | Class | What |
89
+ |---------|-------|--------------|---------------------------------------------------------------|
90
+ | Step 3 | 1 | `execFile` | `dave.sh` is an executable file |
91
+ | Step 4 | 1 | `file` | `dave.ps1` exists |
92
+ | Step 5 | 33 | `path` | Expected-path existence (roles, retrieval, desk, workspace app, .gitkeeps, top-level docs) |
93
+ | Step 6-7| 1 | `serverReady`| Workspace server becomes reachable on the test port |
94
+ | Step 8 | 7 | `httpStatus` | `/`, `home.html`, `onboarding.html`, `tasks.html`, `knowledge.html`, `secrets.html`, `viewer.html` all return 200 |
95
+ | Step 9 | 3 | `jsonValid` | `/__api/overview`, `/__api/projects`, `/__api/work` return parseable JSON |
96
+ | Step 10-13 | 4 | `cliExit` | `backlink-indexer.mjs --help`, `graph-builder.mjs --help`, `query.mjs --help`, `desk --help` exit 0 |
97
+ | Step 14 | 1 | `vaultExit` | `node core/tools/secrets/bin/secrets` exits 0 or 1 |
98
+ | Step 15 | 1 | `cliShell` | `bash dave.sh --help` exits 0 |
99
+ | **Total** | **52** | | |
100
+
101
+ Labels match the bash `PASS:` lines verbatim — CI log comparisons stay valid.
102
+
103
+ ## Tests
104
+
105
+ ```sh
106
+ node --test core/tools/smoke/test/*.test.mjs
107
+ ```
108
+
109
+ The test suite exercises the plan, the CLI wrapper, and the orchestration layer via a fake runner. The real `runner.mjs` is exercised end-to-end by `npm run test:smoke` against the live repo.
110
+
111
+ ## The tooling standard
112
+
113
+ Governed by [`core/knowledge/standards/tooling.md`](../../knowledge/standards/tooling.md). This tool follows sections §1–§16 as written: identity (§1), Node-only (§2), zero-dep (§3), project structure (§4), CLI conventions (§5), exit codes (§6), chokepoint (§7), testing (§8), README-as-contract (§9), operational discipline (§10), JSON camelCase (§11).