@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,398 @@
1
+ // desk — command implementations
2
+ // Each command is a plain async function returning an exit code.
3
+ // Output is written to stdout directly; formatting lives in format.mjs.
4
+
5
+ import { listProjects, getProject, listWork, getWork, sortByStateThenPriority, STATE_ORDER, getRepoRoot } from './repo.mjs';
6
+ import { colour, bold, dim, statusBadge, categoryBadge, priorityLabel, truncate, padEnd, header, kv } from './format.mjs';
7
+ import { filterProjectsByTeam, readTeamScopeConfig, parseTeamScopeFlags } from './team-scope.mjs';
8
+
9
+ // Read PA name + team-scope config from operator config. Falls back to
10
+ // paName 'pa', scoping disabled (backward compat — see team-scope.mjs).
11
+ async function getDeskConfig() {
12
+ const repoRoot = await getRepoRoot();
13
+ return readTeamScopeConfig(repoRoot);
14
+ }
15
+
16
+ // Kept as a thin wrapper — callers elsewhere in this file only need the name.
17
+ async function getPaName() {
18
+ return (await getDeskConfig()).paName;
19
+ }
20
+
21
+ // Apply the team-scoping filter to a project list, then (for human output
22
+ // only) print a one-line notice when projects were hidden by the default
23
+ // scoped view — the fail-open design still means the operator should know
24
+ // scoping is active, not just silently see a shorter list.
25
+ function scopeProjects(projects, config, teamFlags, { json = false } = {}) {
26
+ const scoped = filterProjectsByTeam(projects, {
27
+ selfIdentities: config.teamIdentities,
28
+ scopeEnabled: config.scopeEnabled,
29
+ allTeams: teamFlags.allTeams,
30
+ team: teamFlags.team,
31
+ });
32
+ const hiddenCount = projects.length - scoped.length;
33
+ if (!json && hiddenCount > 0 && !teamFlags.team) {
34
+ console.log(dim(` (${hiddenCount} other-team project${hiddenCount === 1 ? '' : 's'} hidden — use --all-teams to show)`));
35
+ }
36
+ return scoped;
37
+ }
38
+
39
+ function matchesFilter(item, filters) {
40
+ if (filters.status && item.status !== filters.status) return false;
41
+ if (filters.project && item.projectId !== filters.project) return false;
42
+ if (filters.category && item.category !== filters.category) return false;
43
+ if (filters.owner && item.owner !== filters.owner) return false;
44
+ if (filters.assignee) {
45
+ if (filters.assignee === 'unassigned') {
46
+ if (item.assignee) return false;
47
+ } else if (item.assignee !== filters.assignee) {
48
+ return false;
49
+ }
50
+ }
51
+ if (filters.mine && item.assignee !== filters.paName) return false;
52
+ if (filters.theirs && item.assignee !== 'operator') return false;
53
+ return true;
54
+ }
55
+
56
+ function parseFilters(args) {
57
+ const f = {};
58
+ for (let i = 0; i < args.length; i++) {
59
+ const a = args[i];
60
+ if (a === '--status') f.status = args[++i];
61
+ else if (a === '--project') f.project = args[++i];
62
+ else if (a === '--category') f.category = args[++i];
63
+ else if (a === '--owner') f.owner = args[++i];
64
+ else if (a === '--assignee') f.assignee = args[++i];
65
+ else if (a === '--mine') f.mine = true;
66
+ else if (a === '--theirs') f.theirs = true;
67
+ else if (a === '--all') f.all = true;
68
+ else if (a === '--json') f.json = true;
69
+ else if (a === '--all-teams') f.allTeams = true;
70
+ else if (a === '--team') f.team = args[++i];
71
+ else if (!f._rest) f._rest = [a];
72
+ else f._rest.push(a);
73
+ }
74
+ return f;
75
+ }
76
+
77
+ // --- projects ---
78
+
79
+ export async function projectsList(args) {
80
+ const filters = parseFilters(args);
81
+ const config = await getDeskConfig();
82
+ const allProjects = await listProjects();
83
+ const scopedProjects = scopeProjects(allProjects, config, filters, { json: filters.json });
84
+ const filtered = filters.all
85
+ ? scopedProjects
86
+ : scopedProjects.filter((p) => !['done', 'archived'].includes(p.status));
87
+
88
+ if (filters.json) {
89
+ console.log(JSON.stringify(filtered, null, 2));
90
+ return 0;
91
+ }
92
+
93
+ if (!filtered.length) {
94
+ console.log(dim(filters.all ? 'No projects.' : 'No active projects. Use --all to include done/archived.'));
95
+ return 0;
96
+ }
97
+
98
+ // Group by status.
99
+ const groups = new Map();
100
+ for (const p of filtered) {
101
+ const s = p.status || 'draft';
102
+ if (!groups.has(s)) groups.set(s, []);
103
+ groups.get(s).push(p);
104
+ }
105
+
106
+ for (const s of STATE_ORDER) {
107
+ const items = groups.get(s);
108
+ if (!items || !items.length) continue;
109
+ items.sort((a, b) => {
110
+ const pa = a.priority == null ? 99 : a.priority;
111
+ const pb = b.priority == null ? 99 : b.priority;
112
+ if (pa !== pb) return pa - pb;
113
+ return (a.number || 999) - (b.number || 999);
114
+ });
115
+ console.log(header(`${s} (${items.length})`));
116
+ for (const p of items) {
117
+ const num = p.number != null ? dim(`#${p.number}`) : dim(' ');
118
+ const prio = priorityLabel(p.priority);
119
+ const id = colour('cyan', p.id);
120
+ const name = p.name || '';
121
+ const cat = p.category ? dim(`[${p.category}]`) : '';
122
+ console.log(` ${padEnd(num, 4)} ${prio} ${padEnd(id, 24)} ${name} ${cat}`);
123
+ }
124
+ }
125
+ console.log('');
126
+ return 0;
127
+ }
128
+
129
+ export async function projectShow(args) {
130
+ const id = args[0];
131
+ if (!id) {
132
+ console.error('usage: desk projects show <id>');
133
+ return 1;
134
+ }
135
+ const p = await getProject(id);
136
+ if (!p) {
137
+ console.error(`project not found: ${id}`);
138
+ return 1;
139
+ }
140
+ console.log(header(p.name || p.id));
141
+ console.log(kv('id', colour('cyan', p.id)));
142
+ if (p.number != null) console.log(kv('number', `#${p.number}`));
143
+ console.log(kv('status', statusBadge(p.status || 'draft')));
144
+ console.log(kv('priority', priorityLabel(p.priority)));
145
+ if (p.category) console.log(kv('category', p.category));
146
+ if (p.lead) console.log(kv('lead', p.lead));
147
+ if (p.owner) console.log(kv('owner', p.owner));
148
+ if (p.executor) console.log(kv('executor', p.executor));
149
+ if (p.created) console.log(kv('created', p.created));
150
+ if (p.shipped) console.log(kv('shipped', p.shipped));
151
+ if (p.path) console.log(kv('path', dim(p.path)));
152
+ if (p.summary) {
153
+ console.log('');
154
+ console.log(' ' + p.summary);
155
+ }
156
+ if (p.docs && p.docs.length) {
157
+ console.log('');
158
+ console.log(bold(' docs'));
159
+ for (const d of p.docs) {
160
+ console.log(` ${dim('·')} ${d.label} ${dim(d.path)}`);
161
+ }
162
+ }
163
+ // Related work items.
164
+ const work = (await listWork()).filter((w) => w.projectId === p.id);
165
+ if (work.length) {
166
+ console.log('');
167
+ console.log(bold(` work items (${work.length})`));
168
+ for (const w of sortByStateThenPriority(work)) {
169
+ console.log(` ${statusBadge(w.status)} ${priorityLabel(w.priority)} ${colour('cyan', w.id)} ${truncate(w.title, 70)}`);
170
+ }
171
+ }
172
+ console.log('');
173
+ return 0;
174
+ }
175
+
176
+ // --- work ---
177
+
178
+ export async function workList(args) {
179
+ const filters = parseFilters(args);
180
+ const paName = await getPaName();
181
+ filters.paName = paName;
182
+
183
+ const items = await listWork();
184
+ let filtered = items.filter((w) => matchesFilter(w, filters));
185
+ if (!filters.all && !filters.status) {
186
+ filtered = filtered.filter((w) => !['done', 'archived'].includes(w.status));
187
+ }
188
+
189
+ if (filters.json) {
190
+ console.log(JSON.stringify(filtered, null, 2));
191
+ return 0;
192
+ }
193
+
194
+ if (!filtered.length) {
195
+ console.log(dim('No work items match.'));
196
+ return 0;
197
+ }
198
+
199
+ const sorted = sortByStateThenPriority(filtered);
200
+ const groups = new Map();
201
+ for (const w of sorted) {
202
+ const s = w.status || 'draft';
203
+ if (!groups.has(s)) groups.set(s, []);
204
+ groups.get(s).push(w);
205
+ }
206
+
207
+ const DISPLAY_ORDER = ['draft', 'planned', 'in-progress', 'blocked', 'done', 'archived'];
208
+ for (const s of DISPLAY_ORDER) {
209
+ const group = groups.get(s);
210
+ if (!group || !group.length) continue;
211
+ console.log(header(`${s} (${group.length})`));
212
+ for (const w of group) {
213
+ const prio = priorityLabel(w.priority);
214
+ const id = colour('cyan', w.id);
215
+ const cat = w.category ? categoryBadge(w.category) : '';
216
+ const proj = w.projectId ? dim(`[${w.projectId}]`) : dim('[—]');
217
+ const assignee = assigneeBadge(w.assignee, paName);
218
+ const title = truncate(w.title || '', 50);
219
+ console.log(` ${prio} ${padEnd(id, 22)} ${padEnd(assignee, 12)} ${padEnd(proj, 22)} ${padEnd(cat, 10)} ${title}`);
220
+ }
221
+ }
222
+ console.log('');
223
+ return 0;
224
+ }
225
+
226
+ function assigneeBadge(assignee, paName = 'pa') {
227
+ if (!assignee) return dim('—');
228
+ if (assignee === 'operator') return colour('orange', 'on you');
229
+ if (assignee === paName) return colour('cyan', 'on me');
230
+ return dim(`@${assignee}`);
231
+ }
232
+
233
+ export async function workShow(args) {
234
+ const id = args[0];
235
+ if (!id) {
236
+ console.error('usage: desk work show <id>');
237
+ return 1;
238
+ }
239
+ const w = await getWork(id);
240
+ if (!w) {
241
+ console.error(`work item not found: ${id}`);
242
+ return 1;
243
+ }
244
+ const paName = await getPaName();
245
+ console.log(header(w.title || w.id));
246
+ console.log(kv('id', colour('cyan', w.id)));
247
+ console.log(kv('status', statusBadge(w.status || 'draft')));
248
+ console.log(kv('priority', priorityLabel(w.priority)));
249
+ if (w.category) console.log(kv('category', categoryBadge(w.category)));
250
+ if (w.projectId) console.log(kv('project', w.projectId));
251
+ if (w.owner) console.log(kv('owner', w.owner));
252
+ console.log(kv('assignee', assigneeBadge(w.assignee, paName)));
253
+ if (w.created) console.log(kv('created', w.created));
254
+ if (w.updated) console.log(kv('updated', w.updated));
255
+ if (w.blocked) console.log(kv('blocked', colour('red', w.blocked)));
256
+ if (w.summary) {
257
+ console.log('');
258
+ console.log(' ' + w.summary);
259
+ }
260
+ if (w.links && w.links.length) {
261
+ console.log('');
262
+ console.log(bold(' links'));
263
+ for (const l of w.links) {
264
+ console.log(` ${dim('·')} ${l.label} ${dim(l.path)}`);
265
+ }
266
+ }
267
+ console.log('');
268
+ return 0;
269
+ }
270
+
271
+ // --- overview ---
272
+
273
+ export async function overview(args = []) {
274
+ const teamFlags = parseTeamScopeFlags(args);
275
+ const config = await getDeskConfig();
276
+ const paName = config.paName;
277
+ const allProjects = await listProjects();
278
+ const projects = scopeProjects(allProjects, config, teamFlags);
279
+ const work = await listWork();
280
+
281
+ const activeProjects = projects.filter((p) => !['done', 'archived'].includes(p.status));
282
+ const activeWork = work.filter((w) => !['done', 'archived'].includes(w.status));
283
+
284
+ const onMeWork = activeWork.filter((w) => w.assignee === paName);
285
+ const onYouWork = activeWork.filter((w) => w.assignee === 'operator');
286
+ const onMeProjects = activeProjects.filter((p) => p.assignee === paName);
287
+ const onYouProjects = activeProjects.filter((p) => p.assignee === 'operator');
288
+
289
+ const countByStatus = (arr) => {
290
+ const m = new Map();
291
+ for (const x of arr) {
292
+ const s = x.status || 'draft';
293
+ m.set(s, (m.get(s) || 0) + 1);
294
+ }
295
+ return m;
296
+ };
297
+ const projBy = countByStatus(activeProjects);
298
+ const workBy = countByStatus(activeWork);
299
+
300
+ console.log(header('Overview'));
301
+ console.log(` ${bold('Projects')}: ${activeProjects.length} active, ${projects.length - activeProjects.length} done/archived`);
302
+ for (const s of STATE_ORDER) {
303
+ const n = projBy.get(s);
304
+ if (n) console.log(` ${statusBadge(s)} ${n}`);
305
+ }
306
+ console.log(` ${bold('Work items')}: ${activeWork.length} active, ${work.length - activeWork.length} done/archived`);
307
+ for (const s of STATE_ORDER) {
308
+ const n = workBy.get(s);
309
+ if (n) console.log(` ${statusBadge(s)} ${n}`);
310
+ }
311
+
312
+ const onMe = onMeWork.length + onMeProjects.length;
313
+ const onYou = onYouWork.length + onYouProjects.length;
314
+ if (onMe || onYou) {
315
+ console.log(` ${bold('Assignment')}: ${colour('cyan', 'on me')} ${onMe} · ${colour('orange', 'on you')} ${onYou}`);
316
+ }
317
+
318
+ if (onYou) {
319
+ console.log(header('On the Operator'));
320
+ for (const p of onYouProjects) {
321
+ console.log(` ${colour('orange', '⏵')} ${bold(p.name || p.id)} ${dim('[project]')}`);
322
+ if (p.summary) console.log(` ${dim(truncate(p.summary, 100))}`);
323
+ }
324
+ for (const w of onYouWork) {
325
+ console.log(` ${colour('orange', '⏵')} ${w.title} ${dim(`[${w.id}]`)}`);
326
+ }
327
+ }
328
+
329
+ const inProgressProjects = activeProjects.filter((p) => p.status === 'in-progress');
330
+ const inProgressWork = activeWork.filter((w) => w.status === 'in-progress');
331
+ if (inProgressProjects.length || inProgressWork.length) {
332
+ console.log(header('In Progress'));
333
+ for (const p of inProgressProjects) {
334
+ console.log(` ${colour('cyan', '◆')} ${bold(p.name || p.id)} ${dim('[project]')}`);
335
+ if (p.summary) console.log(` ${dim(truncate(p.summary, 100))}`);
336
+ }
337
+ for (const w of inProgressWork) {
338
+ console.log(` ${colour('cyan', '○')} ${w.title} ${dim(`[${w.id}]`)}`);
339
+ }
340
+ }
341
+
342
+ const blocked = [...activeProjects, ...activeWork].filter((x) => x.status === 'blocked');
343
+ if (blocked.length) {
344
+ console.log(header('Blocked'));
345
+ for (const x of blocked) {
346
+ console.log(` ${colour('red', '⚠')} ${x.title || x.name || x.id}`);
347
+ if (x.blocked) console.log(` ${dim('└─')} ${x.blocked}`);
348
+ }
349
+ }
350
+
351
+ const planned = sortByStateThenPriority(
352
+ [...activeProjects, ...activeWork].filter((x) => x.status === 'planned')
353
+ ).slice(0, 10);
354
+ if (planned.length) {
355
+ console.log(header('Next up (planned)'));
356
+ for (const x of planned) {
357
+ const type = 'number' in x ? 'project' : 'work';
358
+ console.log(` ${priorityLabel(x.priority)} ${x.title || x.name} ${dim(`[${type}]`)}`);
359
+ }
360
+ }
361
+
362
+ console.log('');
363
+ return 0;
364
+ }
365
+
366
+ // --- today ---
367
+
368
+ export async function today(args = []) {
369
+ const todayStr = new Date().toISOString().slice(0, 10);
370
+ const teamFlags = parseTeamScopeFlags(args);
371
+ const config = await getDeskConfig();
372
+ const allProjects = await listProjects();
373
+ const projects = scopeProjects(allProjects, config, teamFlags);
374
+ const work = await listWork();
375
+
376
+ const touched = [
377
+ ...projects.filter((p) => p.created === todayStr || p.shipped === todayStr),
378
+ ...work.filter((w) => w.created === todayStr || w.updated === todayStr),
379
+ ];
380
+
381
+ if (!touched.length) {
382
+ console.log(dim(`Nothing tracked for today (${todayStr}).`));
383
+ return 0;
384
+ }
385
+
386
+ console.log(header(`Today — ${todayStr}`));
387
+ for (const x of touched) {
388
+ const type = 'number' in x ? 'project' : 'work';
389
+ const name = x.title || x.name || x.id;
390
+ const markers = [];
391
+ if (x.created === todayStr) markers.push('created');
392
+ if (x.shipped === todayStr) markers.push('shipped');
393
+ if (x.updated === todayStr && x.updated !== x.created) markers.push('updated');
394
+ console.log(` ${statusBadge(x.status)} ${name} ${dim(`[${type}] ${markers.join(', ')}`)}`);
395
+ }
396
+ console.log('');
397
+ return 0;
398
+ }
@@ -0,0 +1,84 @@
1
+ // desk — terminal output formatting
2
+ // ANSI colour palette for developer CLI output.
3
+
4
+ const C = {
5
+ reset: '\x1b[0m',
6
+ dim: '\x1b[2m',
7
+ bold: '\x1b[1m',
8
+ red: '\x1b[38;5;210m',
9
+ green: '\x1b[38;5;150m',
10
+ yellow: '\x1b[38;5;222m',
11
+ blue: '\x1b[38;5;110m',
12
+ cyan: '\x1b[38;5;117m',
13
+ purple: '\x1b[38;5;183m',
14
+ orange: '\x1b[38;5;215m',
15
+ grey: '\x1b[38;5;245m',
16
+ };
17
+
18
+ const USE_COLOUR = process.stdout.isTTY && !process.env.NO_COLOR;
19
+
20
+ export function colour(c, s) {
21
+ if (!USE_COLOUR) return s;
22
+ return `${C[c] || ''}${s}${C.reset}`;
23
+ }
24
+
25
+ export function bold(s) { return colour('bold', s); }
26
+ export function dim(s) { return colour('dim', s); }
27
+
28
+ export const STATUS_COLOURS = {
29
+ 'in-progress': 'cyan',
30
+ blocked: 'red',
31
+ planned: 'yellow',
32
+ draft: 'grey',
33
+ done: 'green',
34
+ archived: 'dim',
35
+ };
36
+
37
+ export const CATEGORY_COLOURS = {
38
+ feature: 'cyan',
39
+ bug: 'red',
40
+ techDebt: 'orange',
41
+ discussion: 'purple',
42
+ chore: 'grey',
43
+ research: 'blue',
44
+ };
45
+
46
+ export function statusBadge(status) {
47
+ const col = STATUS_COLOURS[status] || 'grey';
48
+ return colour(col, `[${status}]`);
49
+ }
50
+
51
+ export function categoryBadge(category) {
52
+ if (!category) return '';
53
+ const col = CATEGORY_COLOURS[category] || 'grey';
54
+ return colour(col, category);
55
+ }
56
+
57
+ export function priorityLabel(p) {
58
+ if (p == null) return dim('—');
59
+ if (p === 0) return colour('red', 'P0');
60
+ if (p === 1) return colour('orange', 'P1');
61
+ if (p === 2) return colour('yellow', 'P2');
62
+ return dim(`P${p}`);
63
+ }
64
+
65
+ export function truncate(s, n) {
66
+ if (!s) return '';
67
+ if (s.length <= n) return s;
68
+ return s.slice(0, n - 1) + '…';
69
+ }
70
+
71
+ export function padEnd(s, n) {
72
+ // ANSI-aware padding. Strip ANSI for length computation.
73
+ const visible = s.replace(/\x1b\[[0-9;]*m/g, '');
74
+ const pad = Math.max(0, n - visible.length);
75
+ return s + ' '.repeat(pad);
76
+ }
77
+
78
+ export function header(title) {
79
+ return '\n' + bold(colour('purple', title)) + '\n' + dim('─'.repeat(Math.max(20, title.length))) + '\n';
80
+ }
81
+
82
+ export function kv(key, value) {
83
+ return ` ${dim(key.padEnd(12))} ${value}`;
84
+ }
@@ -0,0 +1,172 @@
1
+ // desk — repo walker
2
+ // Source of truth: projects/{id}/project.json + work/{id}.json.
3
+ // Walks the operator repo on every call. No caching. No stale state.
4
+ //
5
+ // Repo root discovery:
6
+ // 1. DAVE_REPO_ROOT or PA_REPO_ROOT env var (explicit override).
7
+ // 2. `.git`-walk upwards from process.cwd().
8
+ //
9
+ // The v1 pattern of `resolve(__dirname, '../../../..')` is intentionally not
10
+ // used. In v2 the package lives in `node_modules/@stravica-ai/engineering-pa-core/`
11
+ // inside the operator repo — `__dirname`-relative navigation would land outside
12
+ // the operator's tree, not at its root.
13
+
14
+ import { readdir, readFile, stat } from 'node:fs/promises';
15
+ import { join, resolve, dirname } from 'node:path';
16
+
17
+ async function pathKind(p) {
18
+ try {
19
+ const s = await stat(p);
20
+ if (s.isDirectory()) return 'dir';
21
+ if (s.isFile()) return 'file';
22
+ return 'other';
23
+ } catch {
24
+ return 'missing';
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Walk up from `start` looking for a `.git` entry. Returns the first
30
+ * directory that contains one, or null. A `.git` *file* (worktree) is
31
+ * accepted alongside a `.git` *directory* (primary checkout) — both mark
32
+ * the top of an operator repo.
33
+ */
34
+ export async function findRepoRoot(start) {
35
+ let d = start;
36
+ while (d && d !== dirname(d)) {
37
+ const kind = await pathKind(join(d, '.git'));
38
+ if (kind === 'dir' || kind === 'file') return d;
39
+ d = dirname(d);
40
+ }
41
+ return null;
42
+ }
43
+
44
+ let _repoRootPromise = null;
45
+ async function resolveRepoRoot() {
46
+ if (_repoRootPromise) return _repoRootPromise;
47
+ _repoRootPromise = (async () => {
48
+ const envRoot = process.env.DAVE_REPO_ROOT || process.env.PA_REPO_ROOT;
49
+ if (envRoot) return resolve(envRoot);
50
+ const found = await findRepoRoot(process.cwd());
51
+ if (!found) {
52
+ const err = new Error(
53
+ 'could not find operator repo root from ' + process.cwd() +
54
+ ' (no .git ancestor; set DAVE_REPO_ROOT or PA_REPO_ROOT to override)'
55
+ );
56
+ err.exitCode = 2;
57
+ throw err;
58
+ }
59
+ return found;
60
+ })();
61
+ return _repoRootPromise;
62
+ }
63
+
64
+ // Cached, lazy. Exposed as a getter so consumers can await it; tests can
65
+ // override via _resetRepoRoot() + DAVE_REPO_ROOT.
66
+ export async function getRepoRoot() {
67
+ return resolveRepoRoot();
68
+ }
69
+
70
+ // Test seam: allow tests to reset the cached repo root between cases.
71
+ export function _resetRepoRoot() {
72
+ _repoRootPromise = null;
73
+ }
74
+
75
+ export async function readJson(path) {
76
+ const raw = await readFile(path, 'utf8');
77
+ return JSON.parse(raw);
78
+ }
79
+
80
+ export async function listProjects() {
81
+ const repoRoot = await getRepoRoot();
82
+ const projectsDir = join(repoRoot, 'projects');
83
+ let entries;
84
+ try {
85
+ entries = await readdir(projectsDir, { withFileTypes: true });
86
+ } catch (err) {
87
+ if (err.code === 'ENOENT') return [];
88
+ throw err;
89
+ }
90
+ const projects = [];
91
+ for (const entry of entries) {
92
+ if (!entry.isDirectory()) continue;
93
+ const manifestPath = join(projectsDir, entry.name, 'project.json');
94
+ try {
95
+ const project = await readJson(manifestPath);
96
+ projects.push(project);
97
+ } catch (err) {
98
+ if (err.code !== 'ENOENT') {
99
+ throw new Error(`bad project manifest at ${manifestPath}: ${err.message}`);
100
+ }
101
+ }
102
+ }
103
+ return projects;
104
+ }
105
+
106
+ export async function getProject(id) {
107
+ const repoRoot = await getRepoRoot();
108
+ const manifestPath = join(repoRoot, 'projects', id, 'project.json');
109
+ try {
110
+ return await readJson(manifestPath);
111
+ } catch (err) {
112
+ if (err.code === 'ENOENT') return null;
113
+ throw err;
114
+ }
115
+ }
116
+
117
+ export async function listWork() {
118
+ const repoRoot = await getRepoRoot();
119
+ const workDir = join(repoRoot, 'work');
120
+ let entries;
121
+ try {
122
+ entries = await readdir(workDir, { withFileTypes: true });
123
+ } catch (err) {
124
+ if (err.code === 'ENOENT') return [];
125
+ throw err;
126
+ }
127
+ const items = [];
128
+ for (const entry of entries) {
129
+ if (!entry.isFile() || !entry.name.endsWith('.json')) continue;
130
+ const path = join(workDir, entry.name);
131
+ try {
132
+ const item = await readJson(path);
133
+ items.push(item);
134
+ } catch (err) {
135
+ throw new Error(`bad work manifest at ${path}: ${err.message}`);
136
+ }
137
+ }
138
+ return items;
139
+ }
140
+
141
+ export async function getWork(id) {
142
+ const repoRoot = await getRepoRoot();
143
+ const path = join(repoRoot, 'work', `${id}.json`);
144
+ try {
145
+ return await readJson(path);
146
+ } catch (err) {
147
+ if (err.code === 'ENOENT') return null;
148
+ throw err;
149
+ }
150
+ }
151
+
152
+ // Sort orders used by multiple commands.
153
+ export const STATE_ORDER = [
154
+ 'in-progress',
155
+ 'blocked',
156
+ 'planned',
157
+ 'draft',
158
+ 'done',
159
+ 'archived',
160
+ ];
161
+
162
+ export function sortByStateThenPriority(items) {
163
+ return items.slice().sort((a, b) => {
164
+ const sa = STATE_ORDER.indexOf(a.status || 'draft');
165
+ const sb = STATE_ORDER.indexOf(b.status || 'draft');
166
+ if (sa !== sb) return sa - sb;
167
+ const pa = a.priority == null ? 99 : a.priority;
168
+ const pb = b.priority == null ? 99 : b.priority;
169
+ if (pa !== pb) return pa - pb;
170
+ return (a.id || '').localeCompare(b.id || '');
171
+ });
172
+ }