@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,320 @@
1
+ /**
2
+ * Global status banner.
3
+ *
4
+ * Renders into <div id="global-banner"></div>, which every workspace page
5
+ * places as the first child of <body>. Fetches /__api/status-mon on load,
6
+ * re-polls every 30 seconds while the tab is visible, and restarts the poll
7
+ * immediately when the tab regains focus.
8
+ *
9
+ * Severity order (most severe wins per source): critical > major > minor >
10
+ * maintenance > recovered > none. Active-disruption rows (minor/major/critical/
11
+ * maintenance) link out to the incident's status page. "Recovered" rows are
12
+ * dismissable; dismissal is stored in localStorage keyed by incident ID so
13
+ * the acknowledgement is per-browser and naturally GC'd when the ID ages out
14
+ * of the recentlyResolved list.
15
+ *
16
+ * No innerHTML with untrusted strings — all content is built with
17
+ * createElement + textContent. Statuspage.io is a trusted source but
18
+ * "safe-by-default" is cheaper than "safe-by-inspection".
19
+ */
20
+ (function () {
21
+ 'use strict';
22
+
23
+ const ENDPOINT = '/__api/status-mon';
24
+ const POLL_INTERVAL_MS = 30_000;
25
+ const DISMISSED_KEY = 'dave.statusmon.dismissed';
26
+
27
+ const SLOT_ID = 'global-banner';
28
+
29
+ const COLOURS = {
30
+ critical: { bg: '#b91c1c', text: '#ffffff', weight: 600 },
31
+ major: { bg: '#b91c1c', text: '#ffffff', weight: 600 },
32
+ minor: { bg: '#b58100', text: '#ffffff', weight: 600 },
33
+ maintenance: { bg: '#1e5aa8', text: '#ffffff', weight: 600 },
34
+ recovered: { bg: '#0a7f2e', text: '#ffffff', weight: 600 },
35
+ };
36
+
37
+ function readDismissed() {
38
+ try {
39
+ const raw = localStorage.getItem(DISMISSED_KEY);
40
+ if (!raw) return [];
41
+ const parsed = JSON.parse(raw);
42
+ if (!Array.isArray(parsed)) return [];
43
+ return parsed.filter((id) => typeof id === 'string');
44
+ } catch {
45
+ return [];
46
+ }
47
+ }
48
+
49
+ function writeDismissed(ids) {
50
+ try {
51
+ localStorage.setItem(DISMISSED_KEY, JSON.stringify(ids));
52
+ } catch { /* storage unavailable — silently no-op */ }
53
+ }
54
+
55
+ /**
56
+ * Prune dismissed IDs that are no longer present in recentlyResolved. Keeps
57
+ * the dismissal set bounded without needing an explicit expiry timer.
58
+ */
59
+ function gcDismissals(state) {
60
+ const activeResolvedIds = new Set();
61
+ for (const source of state.sources || []) {
62
+ for (const r of source.recentlyResolved || []) activeResolvedIds.add(r.id);
63
+ }
64
+ const current = readDismissed();
65
+ const filtered = current.filter((id) => activeResolvedIds.has(id));
66
+ if (filtered.length !== current.length) writeDismissed(filtered);
67
+ return new Set(filtered);
68
+ }
69
+
70
+ /**
71
+ * For a single source, pick the row to render. Returns null when the
72
+ * source contributes nothing (all-clear + no undismissed recentlyResolved,
73
+ * or an all-errors slice with no cached history).
74
+ */
75
+ // Severity rank for computing the effective indicator across overall +
76
+ // active incidents. Statuspage.io occasionally keeps status.indicator='none'
77
+ // while listing an active incident with impact='major' (observed live on
78
+ // githubstatus.com 2026-04-20). Gating the banner purely on overall hides
79
+ // real disruptions in that window, so we take the worst of overall and any
80
+ // per-incident impact.
81
+ const SEVERITY_RANK = { none: 0, maintenance: 1, minor: 2, major: 3, critical: 4 };
82
+
83
+ function effectiveIndicator(source) {
84
+ const overall = (source.overall && source.overall.indicator) || 'none';
85
+ let worst = overall;
86
+ let worstRank = SEVERITY_RANK[overall] != null ? SEVERITY_RANK[overall] : 0;
87
+ for (const incident of (source.incidents || [])) {
88
+ const impact = incident && incident.impact ? incident.impact : 'none';
89
+ const rank = SEVERITY_RANK[impact] != null ? SEVERITY_RANK[impact] : 0;
90
+ if (rank > worstRank) { worst = impact; worstRank = rank; }
91
+ }
92
+ return worst;
93
+ }
94
+
95
+ function pickRow(source, dismissed) {
96
+ const indicator = effectiveIndicator(source);
97
+
98
+ // Active disruption takes precedence over recently-resolved.
99
+ if (indicator === 'critical' || indicator === 'major' || indicator === 'minor' || indicator === 'maintenance') {
100
+ const top = (source.incidents || [])[0];
101
+ const extras = Math.max(0, (source.incidents || []).length - 1);
102
+ const indicatorLabel = indicator === 'minor' ? 'minor disruption'
103
+ : indicator === 'major' ? 'service disruption'
104
+ : indicator === 'critical' ? 'major outage'
105
+ : 'scheduled maintenance';
106
+ const text = top
107
+ ? source.name + ' — ' + indicatorLabel + ': ' + top.name + (extras > 0 ? ' (+' + extras + ' others)' : '')
108
+ : source.name + ' — ' + indicatorLabel;
109
+ const url = top && top.url ? top.url : source.sourceUrl;
110
+ return {
111
+ kind: indicator,
112
+ sourceId: source.id,
113
+ text,
114
+ href: url,
115
+ dismissable: false,
116
+ };
117
+ }
118
+
119
+ // All-clear: surface undismissed recentlyResolved entries.
120
+ const resolved = (source.recentlyResolved || []).filter((r) => !dismissed.has(r.id));
121
+ if (resolved.length > 0) {
122
+ const latest = resolved[0];
123
+ const extras = resolved.length - 1;
124
+ const time = formatRelative(latest.resolvedAt);
125
+ const text = 'All clear — ' + source.name + ' recovered' + (time ? ' ' + time : '') + (extras > 0 ? ' (+' + extras + ' others)' : '');
126
+ return {
127
+ kind: 'recovered',
128
+ sourceId: source.id,
129
+ incidentId: latest.id,
130
+ text,
131
+ href: latest.url || source.sourceUrl,
132
+ dismissable: true,
133
+ };
134
+ }
135
+
136
+ return null;
137
+ }
138
+
139
+ function formatRelative(iso) {
140
+ if (!iso) return '';
141
+ const then = Date.parse(iso);
142
+ if (Number.isNaN(then)) return '';
143
+ const diffSec = Math.max(0, Math.floor((Date.now() - then) / 1000));
144
+ if (diffSec < 60) return '(just now)';
145
+ if (diffSec < 3600) return '(' + Math.floor(diffSec / 60) + 'm ago)';
146
+ if (diffSec < 86_400) return '(' + Math.floor(diffSec / 3600) + 'h ago)';
147
+ return '(' + Math.floor(diffSec / 86_400) + 'd ago)';
148
+ }
149
+
150
+ function renderRow(row) {
151
+ const palette = COLOURS[row.kind] || COLOURS.minor;
152
+ const rowEl = document.createElement('div');
153
+ rowEl.setAttribute('data-banner-row', row.kind);
154
+ rowEl.setAttribute('data-source-id', row.sourceId);
155
+ rowEl.style.cssText = [
156
+ 'display:flex',
157
+ 'align-items:center',
158
+ 'justify-content:space-between',
159
+ 'width:100%',
160
+ 'min-height:34px',
161
+ 'padding:6px 14px',
162
+ 'box-sizing:border-box',
163
+ 'background:' + palette.bg,
164
+ 'color:' + palette.text,
165
+ 'font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif',
166
+ 'font-size:13px',
167
+ 'font-weight:' + palette.weight,
168
+ 'line-height:1.3',
169
+ 'letter-spacing:0.01em',
170
+ ].join(';');
171
+
172
+ const link = document.createElement('a');
173
+ link.href = row.href || '#';
174
+ link.target = '_blank';
175
+ link.rel = 'noopener noreferrer';
176
+ link.textContent = row.text;
177
+ link.style.cssText = [
178
+ 'color:inherit',
179
+ 'text-decoration:none',
180
+ 'flex:1 1 auto',
181
+ 'min-width:0',
182
+ 'overflow:hidden',
183
+ 'text-overflow:ellipsis',
184
+ 'white-space:nowrap',
185
+ 'cursor:pointer',
186
+ ].join(';');
187
+ rowEl.appendChild(link);
188
+
189
+ if (row.dismissable) {
190
+ const btn = document.createElement('button');
191
+ btn.type = 'button';
192
+ btn.setAttribute('aria-label', 'Dismiss');
193
+ btn.textContent = '×';
194
+ btn.style.cssText = [
195
+ 'flex:0 0 auto',
196
+ 'margin-left:10px',
197
+ 'background:transparent',
198
+ 'border:0',
199
+ 'color:inherit',
200
+ 'font-size:18px',
201
+ 'line-height:1',
202
+ 'cursor:pointer',
203
+ 'padding:2px 6px',
204
+ 'opacity:0.85',
205
+ ].join(';');
206
+ btn.addEventListener('click', function (e) {
207
+ e.preventDefault();
208
+ e.stopPropagation();
209
+ const dismissed = readDismissed();
210
+ if (row.incidentId && dismissed.indexOf(row.incidentId) === -1) {
211
+ dismissed.push(row.incidentId);
212
+ writeDismissed(dismissed);
213
+ }
214
+ rowEl.remove();
215
+ });
216
+ rowEl.appendChild(btn);
217
+ }
218
+
219
+ return rowEl;
220
+ }
221
+
222
+ function render(state) {
223
+ const slot = document.getElementById(SLOT_ID);
224
+ if (!slot) return;
225
+ // Clear only banner-owned rows. The slot may also contain the persistent
226
+ // theme-toggle chrome (`[data-theme-chrome]`) added by theme.js — that
227
+ // element must survive every refresh; clearing it would make the toggle
228
+ // vanish on the next 30s poll.
229
+ const owned = slot.querySelectorAll('[data-banner-row]');
230
+ for (let i = 0; i < owned.length; i++) owned[i].remove();
231
+ if (!state || !Array.isArray(state.sources)) return;
232
+
233
+ const dismissed = gcDismissals(state);
234
+ const chrome = slot.querySelector('[data-theme-chrome]');
235
+ for (const source of state.sources) {
236
+ const row = pickRow(source, dismissed);
237
+ if (!row) continue;
238
+ // Insert incident rows BEFORE the theme chrome so the loudest signal
239
+ // stays at the top and the chrome remains pinned to the bottom of the
240
+ // banner.
241
+ const el = renderRow(row);
242
+ if (chrome) slot.insertBefore(el, chrome);
243
+ else slot.appendChild(el);
244
+ }
245
+ }
246
+
247
+ let pollTimer = null;
248
+
249
+ async function fetchAndRender() {
250
+ try {
251
+ const res = await fetch(ENDPOINT, { cache: 'no-store' });
252
+ if (res.status === 404) {
253
+ // Poller hasn't run yet — nothing to show, try again next tick.
254
+ render({ sources: [] });
255
+ return;
256
+ }
257
+ if (!res.ok) return;
258
+ const state = await res.json();
259
+ render(state);
260
+ } catch { /* network blip — leave current row in place */ }
261
+ }
262
+
263
+ function schedule() {
264
+ clearSchedule();
265
+ pollTimer = setTimeout(async function tick() {
266
+ await fetchAndRender();
267
+ if (document.visibilityState === 'visible') schedule();
268
+ }, POLL_INTERVAL_MS);
269
+ }
270
+
271
+ function clearSchedule() {
272
+ if (pollTimer) { clearTimeout(pollTimer); pollTimer = null; }
273
+ }
274
+
275
+ function onVisibility() {
276
+ if (document.visibilityState === 'visible') {
277
+ fetchAndRender();
278
+ schedule();
279
+ } else {
280
+ clearSchedule();
281
+ }
282
+ }
283
+
284
+ function isTopLevel() {
285
+ try { return window.top === window.self; } catch { return false; }
286
+ }
287
+
288
+ function boot() {
289
+ // The shell (index.html) iframes every page. Rendering the banner in
290
+ // each iframed page would produce a second copy below the shell's row.
291
+ // Render only in the top-level context. When a page is opened directly
292
+ // (not via the shell) it IS the top-level, and the banner renders.
293
+ if (!isTopLevel()) return;
294
+
295
+ if (!document.getElementById(SLOT_ID)) {
296
+ // Belt + braces: create the slot if the page forgot to include it, so
297
+ // the banner still renders. Insert as the first child of <body>.
298
+ const slot = document.createElement('div');
299
+ slot.id = SLOT_ID;
300
+ if (document.body.firstChild) document.body.insertBefore(slot, document.body.firstChild);
301
+ else document.body.appendChild(slot);
302
+ }
303
+ fetchAndRender();
304
+ schedule();
305
+ document.addEventListener('visibilitychange', onVisibility);
306
+ }
307
+
308
+ // Fire after load rather than DOMContentLoaded. On busy pages (e.g.
309
+ // home.html fires ~9 API fetches) the HTTP/1.1 6-connection pool means
310
+ // DOMContentLoaded-initiated fetches queue behind the inline script's
311
+ // fetches. Waiting for load is cheap (sub-100ms on quiet pages, a
312
+ // second on busy ones) and gives the banner a clear slot. The banner
313
+ // is a background-info surface, not a critical-path element, so modest
314
+ // delay is the right trade.
315
+ if (document.readyState === 'complete') {
316
+ boot();
317
+ } else {
318
+ window.addEventListener('load', boot);
319
+ }
320
+ })();
@@ -0,0 +1,345 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Delegations — Workspace</title>
7
+ <script>(function(){try{var t=localStorage.getItem('dave.theme');document.documentElement.dataset.theme=(t==='light'||t==='dark')?t:'dark';}catch(_){document.documentElement.dataset.theme='dark';}})();</script>
8
+ <link rel="stylesheet" href="/core/tools/workspace/app/assets/theme.css">
9
+ <script src="/core/tools/workspace/app/assets/theme.js" defer></script>
10
+ <style>
11
+ * { margin: 0; padding: 0; box-sizing: border-box; }
12
+ body { font-family: 'SF Mono','JetBrains Mono','Fira Code',monospace; background: var(--bg); color: var(--text); padding: 1.5rem; line-height: 1.6; }
13
+ h1 { color: var(--text-bright); font-size: 1.25rem; margin-bottom: 0.25rem; }
14
+ .subtitle { color: var(--text-dim); font-size: 0.78rem; margin-bottom: 1.25rem; display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; }
15
+ .refresh-btn { background: var(--bg-surface); border: 1px solid var(--border); color: var(--text); padding: 0.2rem 0.6rem; border-radius: 4px; font-size: 0.72rem; font-family: inherit; cursor: pointer; }
16
+ .refresh-btn:hover { border-color: var(--accent); color: var(--text-bright); }
17
+
18
+ /* Shared loading state */
19
+ .loading { display: flex; align-items: center; justify-content: center; gap: 0.4rem; padding: 2rem; color: var(--text-dim); font-size: 0.82rem; letter-spacing: 0.04em; }
20
+ .loading .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); animation: loading-pulse 1.2s infinite ease-in-out; }
21
+ @keyframes loading-pulse { 0%,80%,100% { opacity: 0.25; } 40% { opacity: 1; } }
22
+
23
+ .metrics-bar { display: flex; flex-wrap: wrap; gap: 0.6rem; background: var(--bg-surface); border: 1px solid var(--border); border-radius: 8px; padding: 0.75rem 1rem; margin-bottom: 1.25rem; }
24
+ .metric { padding: 0 0.9rem; border-right: 1px solid var(--border); display: flex; flex-direction: column; align-items: center; min-width: 90px; }
25
+ .metric:last-child { border-right: none; }
26
+ .metric-value { font-size: 1.45rem; font-weight: 700; color: var(--text-bright); line-height: 1.1; }
27
+ .metric-value.cyan { color: var(--cyan); }
28
+ .metric-value.green { color: var(--green); }
29
+ .metric-value.orange { color: var(--orange); }
30
+ .metric-value.red { color: var(--red); }
31
+ .metric-label { font-size: 0.6rem; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 0.2rem; }
32
+
33
+ .grid { display: grid; grid-template-columns: 2fr 1fr; gap: 1rem; margin-bottom: 1rem; }
34
+ /* Let grid children shrink below their intrinsic content width — otherwise
35
+ long titles and wide content push the tracks past the iframe viewport. */
36
+ .grid > * { min-width: 0; }
37
+ @media (max-width: 900px) { .grid { grid-template-columns: 1fr; } }
38
+ .card { background: var(--bg-surface); border: 1px solid var(--border); border-radius: 8px; padding: 1rem 1.1rem; margin-bottom: 1rem; min-width: 0; }
39
+ .card h2 { color: var(--purple); font-size: 0.92rem; margin-bottom: 0.6rem; display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }
40
+ .card h2 .count { color: var(--text-dim); font-weight: 400; font-size: 0.72rem; }
41
+
42
+ /* Info tooltip */
43
+ .info-icon { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; border: 1px solid var(--border); border-radius: 50%; color: var(--text-dim); font-size: 0.62rem; font-weight: 600; cursor: help; position: relative; font-family: inherit; background: var(--bg-highlight); }
44
+ .info-icon:hover { color: var(--accent); border-color: var(--accent); }
45
+ .info-icon[aria-expanded="true"] { color: var(--accent); border-color: var(--accent); }
46
+ .tooltip { display: none; position: absolute; top: calc(100% + 6px); right: 0; background: var(--bg-surface); border: 1px solid var(--border); border-radius: 6px; padding: 0.75rem 0.9rem; width: 320px; max-width: 90vw; font-size: 0.7rem; color: var(--text); line-height: 1.5; z-index: 50; box-shadow: 0 4px 12px rgba(0,0,0,0.35); text-transform: none; letter-spacing: 0; font-weight: 400; white-space: normal; text-align: left; }
47
+ .tooltip.open { display: block; }
48
+ .tooltip strong { color: var(--text-bright); }
49
+ .tooltip .t-row { padding: 0.25rem 0; border-bottom: 1px dotted var(--bg-highlight); }
50
+ .tooltip .t-row:last-child { border-bottom: none; }
51
+ .tooltip .t-tier { color: var(--accent); font-weight: 600; }
52
+ .tooltip-anchor { position: relative; display: inline-flex; align-items: center; gap: 0.4rem; }
53
+
54
+ /* Filter bar */
55
+ .filter-bar { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.75rem; }
56
+ .chip { display: inline-block; padding: 0.2rem 0.55rem; border: 1px solid var(--border); border-radius: 4px; font-size: 0.7rem; cursor: pointer; background: var(--bg-surface); color: var(--text-dim); font-family: inherit; }
57
+ .chip:hover { border-color: var(--accent); color: var(--text); }
58
+ .chip.active { background: var(--accent); color: var(--bg); border-color: var(--accent); font-weight: 600; }
59
+
60
+ /* Spawn rows */
61
+ .spawn-list { max-height: 600px; overflow-y: auto; padding-right: 0.25rem; }
62
+ .spawn-row { display: flex; flex-direction: column; gap: 0.2rem; padding: 0.55rem 0.65rem; border: 1px solid var(--border); border-radius: 6px; margin-bottom: 0.5rem; background: var(--bg-highlight); cursor: pointer; transition: border-color 0.12s; }
63
+ .spawn-row:hover { border-color: var(--accent); }
64
+ .spawn-header { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; font-size: 0.72rem; }
65
+ .spawn-badge { padding: 0.08rem 0.4rem; border-radius: 3px; font-size: 0.62rem; font-weight: 600; }
66
+ .spawn-badge.role { background: rgba(122,162,247,0.15); color: var(--accent); border: 1px solid rgba(122,162,247,0.3); }
67
+ .spawn-badge.tier-0 { background: var(--bg-surface); color: var(--text-dim); border: 1px solid var(--border); }
68
+ .spawn-badge.tier-1 { background: rgba(122,162,247,0.15); color: var(--accent); }
69
+ .spawn-badge.tier-2 { background: rgba(187,154,247,0.15); color: var(--purple); }
70
+ .spawn-badge.tier-3 { background: rgba(255,158,100,0.15); color: var(--orange); }
71
+ .spawn-badge.outcome { font-weight: 600; }
72
+ .spawn-badge.outcome.success { background: rgba(158,206,106,0.15); color: var(--green); border: 1px solid rgba(158,206,106,0.3); }
73
+ .spawn-badge.outcome.in-flight { background: rgba(125,207,255,0.15); color: var(--cyan); border: 1px solid rgba(125,207,255,0.3); }
74
+ .spawn-badge.outcome.failed { background: rgba(247,118,142,0.15); color: var(--red); border: 1px solid rgba(247,118,142,0.3); }
75
+ .spawn-badge.outcome.other { background: var(--bg-surface); color: var(--text-dim); border: 1px solid var(--border); }
76
+ .spawn-agent { color: var(--purple); font-weight: 600; }
77
+ .spawn-time { color: var(--text-dim); margin-left: auto; }
78
+ .spawn-objective { color: var(--text-bright); font-size: 0.78rem; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
79
+ .spawn-notes { color: var(--text-dim); font-size: 0.7rem; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
80
+
81
+ /* Agent rollup */
82
+ .agent-row { display: flex; flex-direction: column; gap: 0.25rem; padding: 0.55rem 0.65rem; border-bottom: 1px solid var(--bg-highlight); }
83
+ .agent-row:last-child { border-bottom: none; }
84
+ .agent-header { display: flex; justify-content: space-between; font-size: 0.8rem; color: var(--text-bright); font-weight: 600; }
85
+ .agent-totals { display: flex; gap: 0.6rem; font-size: 0.66rem; color: var(--text-dim); }
86
+ .agent-totals .n-ok { color: var(--green); font-weight: 600; }
87
+ .agent-totals .n-if { color: var(--cyan); font-weight: 600; }
88
+ .agent-totals .n-bad { color: var(--red); font-weight: 600; }
89
+
90
+ /* By-role/tier bars */
91
+ .histogram { display: flex; flex-direction: column; gap: 0.3rem; }
92
+ .hist-row { display: flex; align-items: center; gap: 0.5rem; font-size: 0.72rem; }
93
+ .hist-label { min-width: 7rem; color: var(--text); white-space: nowrap; }
94
+ .hist-bar { flex: 1; height: 6px; background: var(--bg-highlight); border-radius: 3px; overflow: hidden; }
95
+ .hist-fill { height: 100%; background: var(--accent); border-radius: 3px; }
96
+ .hist-count { color: var(--text-dim); font-size: 0.68rem; min-width: 2rem; text-align: right; }
97
+
98
+ .empty { color: var(--text-dim); font-size: 0.82rem; padding: 1rem; text-align: center; font-style: italic; }
99
+ </style>
100
+ <script src="/banner.js" defer></script>
101
+ </head>
102
+ <body>
103
+ <div id="global-banner"></div>
104
+ <h1>Delegations</h1>
105
+ <div class="subtitle">
106
+ <span>Spawn-log audit: what's been dispatched, what's in flight, who is doing the work.</span>
107
+ <button class="refresh-btn" onclick="load()">Refresh</button>
108
+ </div>
109
+ <div id="content"><div class="loading"><span>Loading delegations</span><span class="dot"></span></div></div>
110
+ <script src="/core/tools/workspace/app/assets/modal.js"></script>
111
+ <script>
112
+ function esc(s) { var el = document.createElement('span'); el.textContent = s == null ? '' : String(s); return el.innerHTML; }
113
+
114
+ function relTime(iso) {
115
+ if (!iso) return '';
116
+ var t = new Date(iso).getTime();
117
+ if (isNaN(t)) return '';
118
+ var diff = Math.floor((Date.now() - t) / 1000);
119
+ if (diff < 60) return 'just now';
120
+ if (diff < 3600) return Math.floor(diff / 60) + 'm ago';
121
+ if (diff < 86400) return Math.floor(diff / 3600) + 'h ago';
122
+ if (diff < 604800) return Math.floor(diff / 86400) + 'd ago';
123
+ return Math.floor(diff / 604800) + 'w ago';
124
+ }
125
+
126
+ function absTime(iso) {
127
+ if (!iso) return '';
128
+ var d = new Date(iso);
129
+ if (isNaN(d.getTime())) return iso;
130
+ return d.toISOString().replace('T', ' ').replace(/\.\d+Z$/, 'Z');
131
+ }
132
+
133
+ function outcomeClass(o) {
134
+ var v = String(o || '').toLowerCase();
135
+ if (v === 'success' || v === 'done' || v === 'complete' || v === 'completed') return 'success';
136
+ if (v === 'in-flight' || v === 'in-progress' || v === 'dispatched' || v === 'running') return 'in-flight';
137
+ if (v === 'failed' || v === 'failure' || v === 'error') return 'failed';
138
+ return 'other';
139
+ }
140
+
141
+ var state = { filter: 'all', data: null };
142
+
143
+ function renderMetrics(stats) {
144
+ var html = '<div class="metrics-bar">';
145
+ html += '<div class="metric"><div class="metric-value">' + stats.total + '</div><div class="metric-label">Total</div></div>';
146
+ html += '<div class="metric"><div class="metric-value cyan">' + stats.inFlight + '</div><div class="metric-label">In flight</div></div>';
147
+ html += '<div class="metric"><div class="metric-value green">' + stats.success + '</div><div class="metric-label">Success</div></div>';
148
+ html += '<div class="metric"><div class="metric-value red">' + stats.failed + '</div><div class="metric-label">Failed</div></div>';
149
+ html += '<div class="metric"><div class="metric-value orange">' + (stats.total - stats.inFlight - stats.success - stats.failed) + '</div><div class="metric-label">Other</div></div>';
150
+ html += '</div>';
151
+ return html;
152
+ }
153
+
154
+ function renderHistogram(label, bucket) {
155
+ var keys = Object.keys(bucket).sort(function(a, b) { return bucket[b] - bucket[a]; });
156
+ if (!keys.length) return '<div class="empty">No data.</div>';
157
+ var max = Math.max.apply(null, keys.map(function(k) { return bucket[k]; }));
158
+ var html = '<div class="histogram">';
159
+ keys.forEach(function(k) {
160
+ var pct = max ? Math.round(bucket[k] * 100 / max) : 0;
161
+ html += '<div class="hist-row"><span class="hist-label">' + esc(k) + '</span><div class="hist-bar"><div class="hist-fill" style="width:' + pct + '%"></div></div><span class="hist-count">' + bucket[k] + '</span></div>';
162
+ });
163
+ html += '</div>';
164
+ return html;
165
+ }
166
+
167
+ function renderAgents(agents) {
168
+ if (!agents.length) return '<div class="empty">No agents with spawn logs.</div>';
169
+ var html = '';
170
+ agents.forEach(function(a) {
171
+ html += '<div class="agent-row">';
172
+ html += '<div class="agent-header"><span>' + esc(a.name) + '</span><span>' + a.total + '</span></div>';
173
+ html += '<div class="agent-totals">';
174
+ html += '<span><span class="n-if">' + a.inFlight + '</span> in-flight</span>';
175
+ html += '<span><span class="n-ok">' + a.success + '</span> success</span>';
176
+ html += '<span><span class="n-bad">' + a.failed + '</span> failed</span>';
177
+ html += '</div></div>';
178
+ });
179
+ return html;
180
+ }
181
+
182
+ // Track which spawns are in the current filtered view so the row click
183
+ // handler can resolve back to the full record by index without stashing
184
+ // data attributes on every element.
185
+ var _filteredSpawns = [];
186
+
187
+ function renderSpawns(spawns) {
188
+ if (!spawns.length) return '<div class="empty">No delegations recorded.</div>';
189
+ _filteredSpawns = spawns.filter(function(s) {
190
+ if (state.filter === 'all') return true;
191
+ return outcomeClass(s.outcome) === state.filter;
192
+ });
193
+ if (!_filteredSpawns.length) return '<div class="empty">No spawns match this filter.</div>';
194
+ var html = '<div class="spawn-list">';
195
+ _filteredSpawns.forEach(function(s, i) {
196
+ var oc = outcomeClass(s.outcome);
197
+ html += '<div class="spawn-row" data-spawn-idx="' + i + '" tabindex="0" role="button" aria-label="View delegation details">';
198
+ html += '<div class="spawn-header">';
199
+ html += '<span class="spawn-agent">' + esc(s.agent) + '</span>';
200
+ html += '<span class="spawn-badge role">' + esc(s.role) + '</span>';
201
+ html += '<span class="spawn-badge tier-' + (s.tier == null ? '0' : s.tier) + '">tier ' + (s.tier == null ? '?' : s.tier) + '</span>';
202
+ html += '<span class="spawn-badge outcome ' + oc + '">' + esc(s.outcome) + '</span>';
203
+ html += '<span class="spawn-time">' + esc(relTime(s.timestamp)) + '</span>';
204
+ html += '</div>';
205
+ html += '<div class="spawn-objective">' + esc(s.objective) + '</div>';
206
+ if (s.notes) html += '<div class="spawn-notes">' + esc(s.notes) + '</div>';
207
+ html += '</div>';
208
+ });
209
+ html += '</div>';
210
+ return html;
211
+ }
212
+
213
+ function renderFilterBar() {
214
+ var filters = ['all', 'in-flight', 'success', 'failed', 'other'];
215
+ var html = '<div class="filter-bar">';
216
+ filters.forEach(function(f) {
217
+ html += '<span class="chip ' + (state.filter === f ? 'active' : '') + '" data-filter="' + f + '">' + f + '</span>';
218
+ });
219
+ html += '</div>';
220
+ return html;
221
+ }
222
+
223
+ // ── Spawn detail modal ──
224
+ function openSpawnModal(spawn) {
225
+ var oc = outcomeClass(spawn.outcome);
226
+ var body = '';
227
+ body += '<div class="kv">';
228
+ if (spawn.id) body += '<div class="k">ID</div><div class="v mono">' + esc(spawn.id) + '</div>';
229
+ body += '<div class="k">Timestamp</div><div class="v">' + esc(absTime(spawn.timestamp)) + (spawn.timestamp ? ' · ' + esc(relTime(spawn.timestamp)) : '') + '</div>';
230
+ body += '<div class="k">Agent</div><div class="v">' + esc(spawn.agent || '—') + '</div>';
231
+ body += '<div class="k">Role</div><div class="v">' + esc(spawn.role || '—') + '</div>';
232
+ body += '<div class="k">Tier</div><div class="v">' + (spawn.tier == null ? '—' : esc(String(spawn.tier))) + '</div>';
233
+ body += '<div class="k">Outcome</div><div class="v"><span class="spawn-badge outcome ' + oc + '">' + esc(spawn.outcome || 'unknown') + '</span></div>';
234
+ if (spawn.durationMs != null) body += '<div class="k">Duration</div><div class="v">' + esc(String(spawn.durationMs)) + ' ms</div>';
235
+ if (spawn.tokens != null) body += '<div class="k">Tokens</div><div class="v">' + esc(JSON.stringify(spawn.tokens)) + '</div>';
236
+ if (spawn.toolUses != null) body += '<div class="k">Tool uses</div><div class="v">' + esc(String(spawn.toolUses)) + '</div>';
237
+ body += '</div>';
238
+ body += '<div class="section-label">Objective</div>';
239
+ body += '<pre>' + esc(spawn.objective || '(none)') + '</pre>';
240
+ if (spawn.notes) {
241
+ body += '<div class="section-label">Notes</div>';
242
+ body += '<pre>' + esc(spawn.notes) + '</pre>';
243
+ }
244
+ // Surface any additional fields present on the record so we never hide data.
245
+ var KNOWN = { id:1, timestamp:1, agent:1, role:1, tier:1, objective:1, outcome:1, notes:1, tokens:1, durationMs:1, toolUses:1 };
246
+ var extras = Object.keys(spawn).filter(function(k) { return !KNOWN[k] && spawn[k] != null; });
247
+ if (extras.length) {
248
+ body += '<div class="section-label">Other fields</div>';
249
+ var extra = {};
250
+ extras.forEach(function(k) { extra[k] = spawn[k]; });
251
+ body += '<pre>' + esc(JSON.stringify(extra, null, 2)) + '</pre>';
252
+ }
253
+ var title = (spawn.agent || 'Unknown agent') + ' · ' + (spawn.role || 'unknown role');
254
+ window.openModal({ title: title, html: body });
255
+ }
256
+
257
+ function render() {
258
+ var d = state.data;
259
+ var html = '';
260
+ html += renderMetrics(d.stats);
261
+ html += '<div class="grid">';
262
+ html += '<div>';
263
+ html += '<div class="card"><h2>Recent delegations <span class="count">' + d.spawns.length + '</span></h2>';
264
+ html += renderFilterBar();
265
+ html += '<div id="spawn-list">' + renderSpawns(d.spawns) + '</div>';
266
+ html += '</div>';
267
+ html += '</div>';
268
+ html += '<div>';
269
+ html += '<div class="card"><h2>By agent</h2>' + renderAgents(d.agents) + '</div>';
270
+ html += '<div class="card"><h2>By role</h2>' + renderHistogram('role', d.stats.byRole) + '</div>';
271
+ // By tier with (?) tooltip explaining tiers.
272
+ html += '<div class="card"><h2>';
273
+ html += '<span class="tooltip-anchor">By tier';
274
+ html += '<button type="button" class="info-icon" id="tier-info" aria-label="What are tiers?" aria-expanded="false">?</button>';
275
+ html += '<span class="tooltip" id="tier-tooltip" role="tooltip">' +
276
+ '<div class="t-row"><span class="t-tier">Tier 1</span> — <strong>single subagent dispatch</strong>. Well-bounded work that fits one worker.</div>' +
277
+ '<div class="t-row"><span class="t-tier">Tier 2</span> — <strong>task group</strong>. Orchestrator plus two or more workers; multi-role projects or read-heavy parallel work.</div>' +
278
+ '<div class="t-row"><span class="t-tier">Tier 3</span> — <strong>main thread</strong>. Trivial edits, lookups, or quick questions that cost more to dispatch than to answer.</div>' +
279
+ '</span>';
280
+ html += '</span>';
281
+ html += '</h2>' + renderHistogram('tier', d.stats.byTier) + '</div>';
282
+ html += '</div>';
283
+ html += '</div>';
284
+ document.getElementById('content').innerHTML = html;
285
+
286
+ // Wire filter chip clicks.
287
+ document.querySelectorAll('.chip[data-filter]').forEach(function(c) {
288
+ c.addEventListener('click', function() {
289
+ state.filter = c.getAttribute('data-filter');
290
+ render();
291
+ });
292
+ });
293
+
294
+ // Wire spawn row clicks + keyboard open.
295
+ document.querySelectorAll('.spawn-row[data-spawn-idx]').forEach(function(row) {
296
+ row.addEventListener('click', function() {
297
+ var idx = parseInt(row.getAttribute('data-spawn-idx'), 10);
298
+ var sp = _filteredSpawns[idx];
299
+ if (sp) openSpawnModal(sp);
300
+ });
301
+ row.addEventListener('keydown', function(e) {
302
+ if (e.key === 'Enter' || e.key === ' ') {
303
+ e.preventDefault();
304
+ var idx = parseInt(row.getAttribute('data-spawn-idx'), 10);
305
+ var sp = _filteredSpawns[idx];
306
+ if (sp) openSpawnModal(sp);
307
+ }
308
+ });
309
+ });
310
+
311
+ // Wire the tier-info tooltip. Toggle on click (touch-friendly) and show on hover.
312
+ var infoBtn = document.getElementById('tier-info');
313
+ var tip = document.getElementById('tier-tooltip');
314
+ if (infoBtn && tip) {
315
+ var open = false;
316
+ function setOpen(v) {
317
+ open = v;
318
+ tip.classList.toggle('open', open);
319
+ infoBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
320
+ }
321
+ infoBtn.addEventListener('mouseenter', function() { setOpen(true); });
322
+ infoBtn.addEventListener('mouseleave', function() { setOpen(false); });
323
+ infoBtn.addEventListener('focus', function() { setOpen(true); });
324
+ infoBtn.addEventListener('blur', function() { setOpen(false); });
325
+ infoBtn.addEventListener('click', function(e) { e.stopPropagation(); setOpen(!open); });
326
+ document.addEventListener('click', function(e) {
327
+ if (open && e.target !== tip && !tip.contains(e.target) && e.target !== infoBtn) setOpen(false);
328
+ });
329
+ }
330
+ }
331
+
332
+ function load() {
333
+ document.getElementById('content').innerHTML = '<div class="loading"><span>Loading delegations</span><span class="dot"></span></div>';
334
+ fetch('/__api/delegations', { cache: 'no-store' })
335
+ .then(function(r) { return r.json(); })
336
+ .then(function(d) { state.data = d; render(); })
337
+ .catch(function(e) {
338
+ document.getElementById('content').innerHTML = '<div class="empty">Unable to load delegations: ' + esc(e.message) + '</div>';
339
+ });
340
+ }
341
+
342
+ load();
343
+ </script>
344
+ </body>
345
+ </html>