@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,1060 @@
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>Home — Dave</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 {
13
+ font-family: 'SF Mono','JetBrains Mono','Fira Code',monospace;
14
+ background: var(--bg); color: var(--text);
15
+ line-height: 1.6;
16
+ padding: 2rem 1.5rem 4rem;
17
+ }
18
+ a { color: inherit; text-decoration: none; cursor: pointer; }
19
+
20
+ /* Layout: prose-first main column + slim sticky aside */
21
+ .container {
22
+ max-width: 1280px; margin: 0 auto;
23
+ display: grid;
24
+ grid-template-columns: minmax(0, 1fr) 280px;
25
+ gap: 2.25rem;
26
+ align-items: start;
27
+ }
28
+ .main { min-width: 0; max-width: 780px; }
29
+ .aside { display: flex; flex-direction: column; gap: 1.5rem; position: sticky; top: 2rem; }
30
+
31
+ @media (max-width: 1080px) {
32
+ .container { grid-template-columns: 1fr; }
33
+ .aside { position: static; flex-direction: row; flex-wrap: wrap; }
34
+ .aside > * { flex: 1 1 320px; }
35
+ }
36
+ @media (max-width: 720px) {
37
+ .aside { flex-direction: column; }
38
+ .aside > * { flex: 1 1 100%; }
39
+ }
40
+
41
+ /* Greeting + briefing */
42
+ .greet-block { margin-bottom: 2rem; }
43
+ .greet-time {
44
+ font-size: 0.7rem; color: var(--text-dim);
45
+ text-transform: uppercase; letter-spacing: 0.12em;
46
+ margin-bottom: 0.4rem;
47
+ }
48
+ .greet-time .live-dot {
49
+ display: inline-block; width: 6px; height: 6px;
50
+ border-radius: 50%; background: var(--green);
51
+ margin-right: 0.45rem; vertical-align: middle;
52
+ animation: pulse 2.4s infinite;
53
+ }
54
+ @keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.3} }
55
+ .greet-line {
56
+ font-size: 1.85rem; color: var(--text-bright); font-weight: 700;
57
+ letter-spacing: -0.015em; line-height: 1.1;
58
+ margin-bottom: 0.5rem;
59
+ }
60
+ .greet-line .name { color: var(--accent); }
61
+ .briefing {
62
+ font-size: 0.95rem; color: var(--text); line-height: 1.65;
63
+ max-width: 780px;
64
+ min-height: 1.65em;
65
+ }
66
+ .briefing .em { color: var(--text-bright); font-weight: 600; }
67
+ .briefing .alert { color: var(--red); font-weight: 600; }
68
+ .briefing .ok { color: var(--green); font-weight: 600; }
69
+ .briefing .warn { color: var(--orange); font-weight: 600; }
70
+ .briefing a { color: var(--accent); border-bottom: 1px dashed var(--border); }
71
+ .briefing a:hover { color: var(--text-bright); border-bottom-color: var(--accent); }
72
+
73
+ /* Pick-up card */
74
+ .pickup {
75
+ background: linear-gradient(135deg, var(--bg-surface), var(--bg-inset));
76
+ border: 1px solid var(--accent);
77
+ border-left: 4px solid var(--accent);
78
+ border-radius: 8px;
79
+ padding: 1.1rem 1.25rem;
80
+ margin-bottom: 1.75rem;
81
+ position: relative;
82
+ }
83
+ .pickup.hidden { display: none; }
84
+ .pickup .tag {
85
+ font-size: 0.6rem; color: var(--accent);
86
+ text-transform: uppercase; letter-spacing: 0.12em;
87
+ margin-bottom: 0.5rem;
88
+ }
89
+ .pickup .pickup-title {
90
+ font-size: 1.05rem; color: var(--text-bright); font-weight: 700;
91
+ margin-bottom: 0.45rem;
92
+ }
93
+ .pickup .pickup-body { color: var(--text); font-size: 0.85rem; line-height: 1.6; }
94
+ .pickup .pickup-body code { color: var(--cyan); font-size: 0.8rem; }
95
+ .pickup .pickup-body strong { color: var(--text-bright); font-weight: 600; }
96
+ .pickup .pickup-body em { color: var(--accent); font-style: normal; }
97
+ .pickup .pickup-actions { margin-top: 0.85rem; display: flex; gap: 0.6rem; flex-wrap: wrap; }
98
+ .pickup .btn {
99
+ font-size: 0.72rem; padding: 0.35rem 0.75rem;
100
+ border-radius: 4px; border: 1px solid var(--accent);
101
+ color: var(--accent); cursor: pointer;
102
+ transition: all 0.12s;
103
+ background: transparent;
104
+ font-family: inherit;
105
+ }
106
+ .pickup .btn:hover { background: var(--accent); color: var(--bg); }
107
+ .pickup .btn.primary { background: var(--accent); color: var(--bg); font-weight: 700; }
108
+ .pickup .btn.primary:hover { background: var(--text-bright); border-color: var(--text-bright); color: var(--bg); }
109
+
110
+ /* Section titles */
111
+ .section-title {
112
+ font-size: 0.7rem; color: var(--text-dim);
113
+ text-transform: uppercase; letter-spacing: 0.1em;
114
+ margin: 2rem 0 0.65rem; padding-bottom: 0.35rem;
115
+ border-bottom: 1px solid var(--border);
116
+ display: flex; justify-content: space-between; align-items: baseline;
117
+ gap: 0.5rem;
118
+ }
119
+ .section-title .section-count { color: var(--text-dim); font-size: 0.65rem; text-transform: none; letter-spacing: 0; }
120
+ .section-title a.more { color: var(--accent); font-size: 0.65rem; text-transform: none; letter-spacing: 0; }
121
+ .section-title a.more:hover { text-decoration: underline; }
122
+
123
+ /* Rows (on-you / on-me) */
124
+ .row {
125
+ display: flex; align-items: flex-start; gap: 0.7rem;
126
+ padding: 0.65rem 0.2rem;
127
+ border-bottom: 1px solid var(--bg-highlight);
128
+ cursor: pointer;
129
+ transition: background 0.08s;
130
+ }
131
+ .row:last-child { border-bottom: none; }
132
+ .row:hover { background: var(--bg-surface); border-radius: 4px; }
133
+ .row .pill {
134
+ font-size: 0.55rem; padding: 0.14rem 0.45rem; border-radius: 3px;
135
+ font-weight: 700; flex-shrink: 0; margin-top: 0.15rem;
136
+ }
137
+ .pill.p-0 { background: var(--red); color: var(--bg); }
138
+ .pill.p-1 { background: var(--orange); color: var(--bg); }
139
+ .pill.p-2 { background: var(--yellow); color: var(--bg); }
140
+ .pill.p-3 { background: transparent; color: var(--text-dim); border: 1px solid var(--border); }
141
+ .pill.blocked { background: var(--red); color: var(--bg); }
142
+ .row .body { flex: 1; min-width: 0; }
143
+ .row .t { color: var(--text-bright); font-size: 0.88rem; font-weight: 500; line-height: 1.35; }
144
+ .row .m { font-size: 0.67rem; color: var(--text-dim); margin-top: 0.22rem; display: flex; gap: 0.6rem; flex-wrap: wrap; }
145
+ .row .m .state { padding: 0.05rem 0.32rem; border-radius: 3px; font-size: 0.58rem; text-transform: uppercase; letter-spacing: 0.04em; }
146
+ .row .m .state.in-progress { background: var(--cyan); color: var(--bg); }
147
+ .row .m .state.blocked { background: var(--red); color: var(--bg); }
148
+ .row .m .state.planned { background: var(--yellow); color: var(--bg); }
149
+ .row .m .state.draft { background: var(--bg-highlight); color: var(--text-dim); }
150
+ .row .m .proj { color: var(--purple); }
151
+ .row-empty { color: var(--text-dim); font-size: 0.78rem; padding: 0.7rem 0.2rem; font-style: italic; }
152
+
153
+ /* Pulse strip — small card-blocks, one per signal */
154
+ .pulse {
155
+ margin-top: 2.5rem;
156
+ padding-top: 1.25rem;
157
+ border-top: 1px solid var(--border);
158
+ display: grid;
159
+ grid-template-columns: repeat(3, minmax(0, 1fr));
160
+ gap: 0.7rem;
161
+ }
162
+ @media (max-width: 840px) {
163
+ .pulse { grid-template-columns: repeat(2, minmax(0, 1fr)); }
164
+ }
165
+ @media (max-width: 520px) {
166
+ .pulse { grid-template-columns: 1fr; }
167
+ }
168
+ .pulse .item {
169
+ background: var(--bg-surface);
170
+ border: 1px solid var(--border);
171
+ border-radius: 6px;
172
+ padding: 0.7rem 0.85rem;
173
+ display: flex; flex-direction: column; gap: 0.3rem;
174
+ min-height: 74px;
175
+ }
176
+ .pulse .item .k {
177
+ color: var(--text-dim); font-size: 0.58rem;
178
+ text-transform: uppercase; letter-spacing: 0.08em;
179
+ font-weight: 600;
180
+ }
181
+ .pulse .item .v {
182
+ color: var(--text-bright);
183
+ font-size: 1.05rem;
184
+ font-weight: 700;
185
+ line-height: 1.15;
186
+ font-variant-numeric: tabular-nums;
187
+ }
188
+ .pulse .item .v.alert { color: var(--red); }
189
+ .pulse .item .v.warn { color: var(--orange); }
190
+ .pulse .item .v.ok { color: var(--green); }
191
+ .pulse .item .v.info { color: var(--cyan); }
192
+ .pulse .item .sub {
193
+ font-size: 0.66rem;
194
+ color: var(--text-dim);
195
+ line-height: 1.35;
196
+ margin-top: auto;
197
+ overflow: hidden;
198
+ text-overflow: ellipsis;
199
+ white-space: nowrap;
200
+ }
201
+
202
+ /* Deck: project + note chiclets */
203
+ .deck {
204
+ display: flex; gap: 0.55rem; overflow-x: auto;
205
+ padding-bottom: 0.4rem;
206
+ scrollbar-color: var(--border) transparent;
207
+ scrollbar-width: thin;
208
+ }
209
+ .deck::-webkit-scrollbar { height: 6px; }
210
+ .deck::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
211
+ .deck .deck-empty { color: var(--text-dim); font-size: 0.78rem; padding: 0.4rem 0.1rem; font-style: italic; }
212
+ .card {
213
+ flex-shrink: 0; width: 240px; min-height: 86px;
214
+ background: var(--bg-surface); border: 1px solid var(--border);
215
+ border-left: 3px solid var(--purple);
216
+ border-radius: 6px; padding: 0.7rem 0.85rem;
217
+ display: flex; flex-direction: column; gap: 0.3rem;
218
+ cursor: pointer; transition: border-color 0.1s, transform 0.08s;
219
+ }
220
+ .card:hover { border-color: var(--accent); transform: translateY(-1px); }
221
+ .card .id { font-size: 0.58rem; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.06em; }
222
+ .card .n { color: var(--text-bright); font-size: 0.85rem; font-weight: 600; line-height: 1.25; }
223
+ .card .s { color: var(--text-dim); font-size: 0.66rem; line-height: 1.35;
224
+ overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
225
+ .card .f { display: flex; justify-content: space-between; margin-top: auto; align-items: baseline; font-size: 0.6rem; }
226
+ .card .f .status { padding: 0.05rem 0.4rem; border-radius: 3px; border: 1px solid; }
227
+ .card .f .status.in-progress { border-color: var(--green); color: var(--green); }
228
+ .card .f .status.planned { border-color: var(--yellow); color: var(--yellow); }
229
+ .card .f .status.blocked { border-color: var(--red); color: var(--red); }
230
+ .card .f .status.draft { border-color: var(--text-dim); color: var(--text-dim); }
231
+ .card .f .prio { color: var(--text-dim); }
232
+ .card.note-card { border-left-color: var(--cyan); }
233
+ .card.note-card .tag {
234
+ font-size: 0.56rem; padding: 0.06rem 0.35rem;
235
+ border-radius: 3px; color: var(--text-dim); border: 1px solid var(--border);
236
+ display: inline-block;
237
+ }
238
+
239
+ /* Aside panels */
240
+ .aside-panel {
241
+ background: var(--bg-surface);
242
+ border: 1px solid var(--border);
243
+ border-radius: 6px;
244
+ padding: 0.85rem 0.95rem;
245
+ }
246
+ .aside-panel h3 {
247
+ font-size: 0.7rem;
248
+ color: var(--text-dim);
249
+ text-transform: uppercase;
250
+ letter-spacing: 0.08em;
251
+ font-weight: 600;
252
+ margin-bottom: 0.55rem;
253
+ padding-bottom: 0.4rem;
254
+ border-bottom: 1px solid var(--bg-highlight);
255
+ display: flex;
256
+ justify-content: space-between;
257
+ align-items: baseline;
258
+ gap: 0.5rem;
259
+ }
260
+ .aside-panel h3 .ap-meta {
261
+ font-size: 0.6rem; color: var(--text-dim);
262
+ text-transform: none; letter-spacing: 0; font-weight: 400;
263
+ flex-shrink: 0;
264
+ }
265
+ .aside-panel .ap-lede {
266
+ font-size: 0.72rem; color: var(--text-dim);
267
+ line-height: 1.5; margin-bottom: 0.6rem;
268
+ font-style: italic;
269
+ }
270
+ .aside-panel a.ap-more {
271
+ display: block; font-size: 0.65rem; color: var(--accent);
272
+ margin-top: 0.55rem; text-align: right;
273
+ }
274
+ .aside-panel a.ap-more:hover { text-decoration: underline; }
275
+ .aside-panel .ap-empty { font-size: 0.72rem; color: var(--text-dim); font-style: italic; padding: 0.3rem 0; }
276
+
277
+ /* "What I've noticed this session" rows */
278
+ .nts-row {
279
+ display: flex; justify-content: space-between; gap: 0.5rem;
280
+ align-items: baseline;
281
+ font-size: 0.7rem; padding: 0.3rem 0;
282
+ border-bottom: 1px dashed var(--bg-highlight);
283
+ }
284
+ .nts-row:last-child { border-bottom: none; }
285
+ .nts-row .cat {
286
+ font-size: 0.55rem; padding: 0.06rem 0.4rem; border-radius: 3px;
287
+ text-transform: lowercase; letter-spacing: 0.02em;
288
+ flex-shrink: 0;
289
+ }
290
+ .nts-row .cat.preference { background: rgba(122,162,247,0.15); color: var(--accent); }
291
+ .nts-row .cat.correction { background: rgba(247,118,142,0.18); color: var(--red); }
292
+ .nts-row .cat.decision { background: rgba(187,154,247,0.18); color: var(--purple); }
293
+ .nts-row .cat.pattern { background: rgba(158,206,106,0.15); color: var(--green); }
294
+ .nts-row .cat.feedback { background: rgba(255,158,100,0.18); color: var(--orange); }
295
+ .nts-row .cat.contact,
296
+ .nts-row .cat.domain { background: rgba(125,207,255,0.15); color: var(--cyan); }
297
+ .nts-row .cat.other { background: var(--bg-highlight); color: var(--text-dim); }
298
+ .nts-row .label { color: var(--text-bright); font-weight: 600; }
299
+ .nts-foot {
300
+ margin-top: 0.5rem; font-size: 0.62rem; color: var(--text-dim);
301
+ display: flex; justify-content: space-between;
302
+ }
303
+ .nts-foot .v { color: var(--text); }
304
+
305
+ /* "Topics I track" rows */
306
+ .topic-row {
307
+ display: flex; justify-content: space-between; gap: 0.4rem; align-items: baseline;
308
+ padding: 0.32rem 0;
309
+ border-bottom: 1px dashed var(--bg-highlight);
310
+ font-size: 0.74rem;
311
+ }
312
+ .topic-row:last-child { border-bottom: none; }
313
+ .topic-row .topic-name { color: var(--text-bright); font-weight: 500; }
314
+ .topic-row .topic-meta { display: flex; gap: 0.4rem; align-items: baseline; flex-shrink: 0; }
315
+ .topic-row .topic-count { color: var(--text-dim); font-size: 0.62rem; font-variant-numeric: tabular-nums; }
316
+ .topic-row .topic-health {
317
+ font-size: 0.54rem; padding: 0.05rem 0.35rem; border-radius: 3px;
318
+ text-transform: uppercase; letter-spacing: 0.04em;
319
+ }
320
+ .topic-row .topic-health.fresh { background: rgba(158,206,106,0.18); color: var(--green); }
321
+ .topic-row .topic-health.warm { background: rgba(224,175,104,0.18); color: var(--yellow); }
322
+ .topic-row .topic-health.stale { background: rgba(247,118,142,0.18); color: var(--red); }
323
+ .topic-row .topic-health.thin { background: var(--bg-highlight); color: var(--text-dim); }
324
+
325
+ /* Sparse (fresh / onboarding) fork */
326
+ body.sparse .normal-layout { display: none; }
327
+ body.sparse .sparse-layout { display: block; }
328
+ body.sparse .container { display: block; max-width: 720px; }
329
+ body.sparse .aside { display: none; }
330
+ .sparse-layout { display: none; }
331
+ .sparse-layout .hero { text-align: center; padding: 3rem 1rem 2rem; }
332
+ .sparse-layout .hero .logo {
333
+ display: inline-block; width: 60px; height: 60px;
334
+ background: var(--accent); color: var(--bg);
335
+ border-radius: 14px; line-height: 60px;
336
+ font-size: 2rem; font-weight: 800;
337
+ margin-bottom: 1.25rem;
338
+ }
339
+ .sparse-layout .hero h1 {
340
+ font-size: 2rem; color: var(--text-bright);
341
+ letter-spacing: -0.02em; margin-bottom: 0.6rem;
342
+ }
343
+ .sparse-layout .hero p {
344
+ color: var(--text-dim); font-size: 0.95rem;
345
+ max-width: 640px; margin: 0 auto 1.75rem;
346
+ }
347
+ .sparse-layout .hero .cta {
348
+ display: inline-block; background: var(--accent); color: var(--bg);
349
+ padding: 0.7rem 1.4rem; border-radius: 6px;
350
+ font-weight: 700; font-size: 0.85rem;
351
+ margin: 0.3rem;
352
+ }
353
+ .sparse-layout .hero .cta.secondary {
354
+ background: transparent; color: var(--accent);
355
+ border: 1px solid var(--accent);
356
+ }
357
+ .sparse-layout .hero .cta:hover { background: var(--text-bright); color: var(--bg); border-color: var(--text-bright); }
358
+ .sparse-layout .next-steps {
359
+ max-width: 720px; margin: 2rem auto 0;
360
+ border-top: 1px solid var(--border); padding-top: 2rem;
361
+ }
362
+ .sparse-layout .next-steps .step {
363
+ display: grid; grid-template-columns: auto 1fr;
364
+ gap: 1rem; align-items: start;
365
+ padding: 0.85rem 0; border-bottom: 1px solid var(--bg-highlight);
366
+ }
367
+ .sparse-layout .next-steps .step:last-child { border-bottom: none; }
368
+ .sparse-layout .next-steps .step .idx {
369
+ color: var(--text-dim); font-size: 0.7rem;
370
+ font-variant-numeric: tabular-nums;
371
+ }
372
+ .sparse-layout .next-steps .step .title {
373
+ color: var(--text-bright); font-size: 0.88rem; font-weight: 600;
374
+ margin-bottom: 0.2rem;
375
+ }
376
+ .sparse-layout .next-steps .step .desc { color: var(--text-dim); font-size: 0.74rem; }
377
+ .sparse-layout .next-steps .step a.go { color: var(--accent); font-size: 0.72rem; }
378
+ .sparse-layout .next-steps .step a.go:hover { text-decoration: underline; }
379
+ .sparse-layout .next-steps .step.done .title { color: var(--text-dim); text-decoration: line-through; }
380
+ .sparse-layout .next-steps .step .idx.done { color: var(--green); }
381
+
382
+ /* Mode toggle (bottom-right) */
383
+ .mode-toggle {
384
+ position: fixed; right: 1rem; bottom: 1rem; z-index: 100;
385
+ background: var(--bg-surface); border: 1px solid var(--border);
386
+ color: var(--text-dim); font-family: inherit; font-size: 0.65rem;
387
+ padding: 0.35rem 0.6rem; border-radius: 4px; cursor: pointer;
388
+ }
389
+ .mode-toggle:hover { color: var(--text); border-color: var(--accent); }
390
+ </style>
391
+ <script src="/banner.js" defer></script>
392
+ </head>
393
+ <body>
394
+ <div id="global-banner"></div>
395
+
396
+ <div class="container">
397
+
398
+ <!-- ═════════ POPULATED LAYOUT ═════════ -->
399
+ <div class="main normal-layout">
400
+
401
+ <div class="greet-block">
402
+ <div class="greet-time"><span class="live-dot"></span><span id="greet-time">—</span></div>
403
+ <div class="greet-line"><span id="greet-hail">Hello</span>, <span class="name" id="greet-name">—</span>.</div>
404
+ <div class="briefing" id="briefing">Reading the state of things…</div>
405
+ </div>
406
+
407
+ <!-- Pick-up card (sourced from /__api/next-session). Hidden until present. -->
408
+ <div class="pickup hidden" id="pickup">
409
+ <div class="tag">Pick up where you left off</div>
410
+ <div class="pickup-title" id="pickup-title">—</div>
411
+ <div class="pickup-body" id="pickup-body">—</div>
412
+ <div class="pickup-actions" id="pickup-actions">
413
+ <a class="btn" onclick="nav('/tasks.html')">See all tasks</a>
414
+ </div>
415
+ </div>
416
+
417
+ <!-- On you (items where assignee=operator, non-done) -->
418
+ <div class="section-title">
419
+ <span>On you</span>
420
+ <span><span class="section-count" id="on-you-count">—</span> &nbsp; <a class="more" onclick="nav('/tasks.html')">see all →</a></span>
421
+ </div>
422
+ <div id="on-you-list"></div>
423
+
424
+ <!-- On me (items where assignee=PA identifier, non-done) -->
425
+ <div class="section-title">
426
+ <span>On me</span>
427
+ <span><span class="section-count" id="on-me-count">—</span> &nbsp; <a class="more" onclick="nav('/tasks.html')">see all →</a></span>
428
+ </div>
429
+ <div id="on-me-list"></div>
430
+
431
+ <!-- Active projects rail -->
432
+ <div class="section-title">
433
+ <span>Active projects</span>
434
+ <span><span class="section-count" id="projects-count">—</span> &nbsp; <a class="more" onclick="nav('/projects.html')">all →</a></span>
435
+ </div>
436
+ <div class="deck" id="projects-deck"></div>
437
+
438
+ <!-- Open discussions and notes rail -->
439
+ <div class="section-title">
440
+ <span>Open discussions and notes</span>
441
+ <span><span class="section-count" id="notes-count">—</span> &nbsp; <a class="more" onclick="nav('/notes.html')">all →</a></span>
442
+ </div>
443
+ <div class="deck" id="notes-deck"></div>
444
+
445
+ <!-- Pulse strip -->
446
+ <div class="pulse">
447
+ <div class="item">
448
+ <span class="k">Open PRs</span>
449
+ <span class="v" id="pulse-prs">—</span>
450
+ <span class="sub" id="pulse-prs-sub"></span>
451
+ </div>
452
+ <div class="item">
453
+ <span class="k">Team activity</span>
454
+ <span class="v info" id="pulse-team">—</span>
455
+ <span class="sub" id="pulse-team-sub"></span>
456
+ </div>
457
+ <div class="item">
458
+ <span class="k">To remember</span>
459
+ <span class="v" id="pulse-remember">—</span>
460
+ <span class="sub" id="pulse-remember-sub"></span>
461
+ </div>
462
+ <div class="item">
463
+ <span class="k">Schedules</span>
464
+ <span class="v" id="pulse-schedules">—</span>
465
+ <span class="sub" id="pulse-schedules-sub"></span>
466
+ </div>
467
+ <div class="item">
468
+ <span class="k">What I know</span>
469
+ <span class="v" id="pulse-know">—</span>
470
+ <span class="sub" id="pulse-know-sub"></span>
471
+ </div>
472
+ <div class="item">
473
+ <span class="k">Session</span>
474
+ <span class="v" id="pulse-uptime">up 0s</span>
475
+ <span class="sub">since reload</span>
476
+ </div>
477
+ </div>
478
+
479
+ </div>
480
+
481
+ <!-- ═════════ ASIDE ═════════ -->
482
+ <aside class="aside normal-layout">
483
+
484
+ <div class="aside-panel" id="ap-noticed">
485
+ <h3>What I've noticed this session <span class="ap-meta" id="ap-noticed-count">—</span></h3>
486
+ <div class="ap-lede">Loose observations I've picked up. The 03:00 sweep files them where they belong.</div>
487
+ <div id="nts-list"><div class="ap-empty">Nothing new to file.</div></div>
488
+ <div class="nts-foot">
489
+ <span>Oldest</span><span class="v" id="nts-oldest">—</span>
490
+ </div>
491
+ <a class="ap-more" onclick="nav('/staging.html')">browse →</a>
492
+ </div>
493
+
494
+ <div class="aside-panel" id="ap-topics">
495
+ <h3>Topics I track <span class="ap-meta" id="ap-topics-meta">—</span></h3>
496
+ <div class="ap-lede">The shape of what I know about. Health flags when an area's gone quiet.</div>
497
+ <div id="topic-list"><div class="ap-empty">No topics yet.</div></div>
498
+ <a class="ap-more" onclick="nav('/knowledge-map.html')">explore →</a>
499
+ </div>
500
+
501
+ </aside>
502
+
503
+ <!-- ═════════ SPARSE / FRESH FORK LAYOUT ═════════ -->
504
+ <div class="sparse-layout">
505
+ <div class="hero">
506
+ <div class="logo">D</div>
507
+ <h1>Welcome. Your workspace is empty.</h1>
508
+ <p>Dave is your personal assistant — a learned, on-repo AI colleague that tracks your projects, runs your team of sub-agents, and gets sharper the more you talk to it. There's nothing here yet because nothing's been set up. That takes about five minutes.</p>
509
+ <a class="cta" href="/onboarding.html" target="_top">Start onboarding →</a>
510
+ <a class="cta secondary" href="https://github.com/Stravica/dave" target="_blank" rel="noopener">Read the docs</a>
511
+ </div>
512
+
513
+ <div class="next-steps">
514
+ <div class="step done">
515
+ <div class="idx done">01 ●</div>
516
+ <div>
517
+ <div class="title">Workspace server running</div>
518
+ <div class="desc">You wouldn't be reading this otherwise. Nice.</div>
519
+ </div>
520
+ </div>
521
+ <div class="step">
522
+ <div class="idx">02 ○</div>
523
+ <div>
524
+ <div class="title">Tell Dave who you are <a class="go" href="/onboarding.html" target="_top">go →</a></div>
525
+ <div class="desc">Name, role, skills, purpose. Five fields, two minutes. This populates your profile and configures your PA.</div>
526
+ </div>
527
+ </div>
528
+ <div class="step">
529
+ <div class="idx">03 ○</div>
530
+ <div>
531
+ <div class="title">Name your PA <a class="go" href="/onboarding.html" target="_top">go →</a></div>
532
+ <div class="desc">The assistant has a name and a personality. Mine is Dave. Yours could be Jeeves, Max, Hal, whatever fits.</div>
533
+ </div>
534
+ </div>
535
+ <div class="step">
536
+ <div class="idx">04 ○</div>
537
+ <div>
538
+ <div class="title">Open your first project <a class="go" onclick="nav('/projects.html')">go →</a></div>
539
+ <div class="desc">Once onboarded, create a project. Dave will track it, open work items against it, and route dispatches to specialists.</div>
540
+ </div>
541
+ </div>
542
+ <div class="step">
543
+ <div class="idx">05 ○</div>
544
+ <div>
545
+ <div class="title">Browse the rest <a class="go" onclick="nav('/knowledge.html')">go →</a></div>
546
+ <div class="desc">Topics, Tasks, Notes, Schedules, Secrets — all empty, all ready when you are.</div>
547
+ </div>
548
+ </div>
549
+ </div>
550
+ </div>
551
+
552
+ </div>
553
+
554
+ <button class="mode-toggle" onclick="toggleSparse()">toggle sparse</button>
555
+
556
+ <script>
557
+ // ── Tiny helpers ────────────────────────────────────────────────
558
+ function nav(path) {
559
+ if (window.parent && typeof window.parent.navigate === 'function') window.parent.navigate(path);
560
+ else window.location.href = path;
561
+ }
562
+ function esc(s) {
563
+ var el = document.createElement('span');
564
+ el.textContent = (s == null ? '' : String(s));
565
+ return el.innerHTML;
566
+ }
567
+ function pluralise(n, single, plural) {
568
+ return (n === 1 ? single : (plural || (single + 's')));
569
+ }
570
+ function byId(id) { return document.getElementById(id); }
571
+ function setText(id, text) { var el = byId(id); if (el) el.textContent = text; }
572
+ function setHtml(id, html) { var el = byId(id); if (el) el.innerHTML = html; }
573
+
574
+ // ── Sparse mode control ────────────────────────────────────────
575
+ function applySparseFromUrl() {
576
+ if (window.location.search.indexOf('sparse=1') !== -1) document.body.classList.add('sparse');
577
+ }
578
+ function toggleSparse() { document.body.classList.toggle('sparse'); }
579
+ function forceSparse() { document.body.classList.add('sparse'); }
580
+ applySparseFromUrl();
581
+
582
+ // ── Greeting clock ─────────────────────────────────────────────
583
+ (function () {
584
+ var days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
585
+ var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
586
+ function pad(n) { return n < 10 ? '0' + n : '' + n; }
587
+ function render() {
588
+ var d = new Date();
589
+ var h = d.getHours();
590
+ var hail = 'Evening';
591
+ if (h < 6) hail = 'Late night';
592
+ else if (h < 12) hail = 'Morning';
593
+ else if (h < 17) hail = 'Afternoon';
594
+ var tod = h < 12 ? 'morning' : (h < 17 ? 'afternoon' : 'evening');
595
+ var tz;
596
+ try { tz = Intl.DateTimeFormat().resolvedOptions().timeZone || ''; } catch (e) { tz = ''; }
597
+ setText('greet-hail', hail);
598
+ setText('greet-time',
599
+ days[d.getDay()] + ' ' + tod + ' · ' +
600
+ pad(d.getDate()) + ' ' + months[d.getMonth()] + ' · ' +
601
+ pad(d.getHours()) + ':' + pad(d.getMinutes())
602
+ );
603
+ }
604
+ render();
605
+ setInterval(render, 30_000);
606
+ })();
607
+
608
+ // ── Live session uptime ────────────────────────────────────────
609
+ var SESSION_START = Date.now();
610
+ function fmtUptime(ms) {
611
+ var s = Math.floor(ms / 1000);
612
+ var h = Math.floor(s / 3600); s -= h * 3600;
613
+ var m = Math.floor(s / 60); s -= m * 60;
614
+ if (h > 0) return h + 'h ' + m + 'm';
615
+ if (m > 0) return m + 'm ' + s + 's';
616
+ return s + 's';
617
+ }
618
+ function tickUptime() { setText('pulse-uptime', 'up ' + fmtUptime(Date.now() - SESSION_START)); }
619
+ tickUptime(); setInterval(tickUptime, 1000);
620
+
621
+ // ── Data loaders ───────────────────────────────────────────────
622
+ //
623
+ // Each loader is resilient: a fetch failure leaves the affected region in
624
+ // its "—" placeholder state. The main overview fetch is the only one that
625
+ // can trigger sparse mode (on total failure or empty response).
626
+
627
+ var STATE_RANK = { 'blocked': 0, 'in-progress': 1, 'planned': 2, 'draft': 3 };
628
+ var DONE = { done: true, archived: true };
629
+
630
+ function fmtRelativeDate(iso) {
631
+ if (!iso) return '';
632
+ var t = Date.parse(iso);
633
+ if (!isFinite(t)) return '';
634
+ var ageMs = Date.now() - t;
635
+ if (ageMs < 0) return 'just now';
636
+ var days = Math.floor(ageMs / (24 * 60 * 60 * 1000));
637
+ if (days === 0) return 'today';
638
+ if (days === 1) return '1d';
639
+ if (days < 30) return days + 'd';
640
+ var months = Math.floor(days / 30);
641
+ return months + 'mo';
642
+ }
643
+
644
+ function renderRow(w, paName, operatorName) {
645
+ var priority = (w.priority == null ? 3 : Math.max(0, Math.min(3, w.priority)));
646
+ var pillClass = w.status === 'blocked' ? 'p-1 blocked' : ('p-' + priority);
647
+ var pillLabel = w.status === 'blocked' ? 'BLOCKED' : ('P' + priority);
648
+ var state = w.status || 'draft';
649
+ var ageBits = [];
650
+ if (w.updated) ageBits.push(esc(fmtRelativeDate(w.updated)));
651
+ var meta = '<span class="state ' + esc(state) + '">' + esc(state) + '</span>';
652
+ if (w.projectId) meta += '<span class="proj">' + esc(w.projectId) + '</span>';
653
+ if (w.category) meta += '<span>' + esc(w.category) + '</span>';
654
+ if (ageBits.length) meta += '<span>' + ageBits.join(' ') + '</span>';
655
+ var title = esc(w.title || w.id || '(untitled)');
656
+ return (
657
+ '<a class="row" data-id="' + esc(w.id || '') + '" onclick="nav(\'/tasks.html\')">' +
658
+ '<span class="pill ' + pillClass + '">' + pillLabel + '</span>' +
659
+ '<div class="body">' +
660
+ '<div class="t">' + title + '</div>' +
661
+ '<div class="m">' + meta + '</div>' +
662
+ '</div>' +
663
+ '</a>'
664
+ );
665
+ }
666
+
667
+ function renderProjectCard(p) {
668
+ var status = p.status || 'draft';
669
+ var prio = (p.priority == null ? null : ('P' + p.priority));
670
+ var id = p.id || '';
671
+ var summary = p.summary ? esc(p.summary) : '';
672
+ var label = 'project';
673
+ return (
674
+ '<a class="card" onclick="nav(\'/projects.html\')">' +
675
+ '<div class="id">' + esc((prio ? prio + ' · ' : '') + id) + '</div>' +
676
+ '<div class="n">' + esc(p.name || id) + '</div>' +
677
+ '<div class="s">' + summary + '</div>' +
678
+ '<div class="f">' +
679
+ '<span class="status ' + esc(status) + '">' + esc(status) + '</span>' +
680
+ (p.number != null ? '<span class="prio">#' + esc(p.number) + '</span>' : '') +
681
+ '</div>' +
682
+ '</a>'
683
+ );
684
+ }
685
+
686
+ function renderNoteCard(n) {
687
+ var name = n.name || '';
688
+ var tagMatch = /^([a-z]+)-/i.exec(name);
689
+ var tag = tagMatch ? tagMatch[1] : 'note';
690
+ var age = fmtRelativeDate(n.modified);
691
+ var summary = name.replace(/\.md$/, '').replace(/^[a-z]+-/i, '').replace(/-/g, ' ');
692
+ return (
693
+ '<a class="card note-card" onclick="nav(\'/viewer.html?file=' + encodeURIComponent(n.path) + '\')">' +
694
+ '<div class="id">' + esc((age ? age + ' · ' : '') + tag) + '</div>' +
695
+ '<div class="n">' + esc(n.title || n.name) + '</div>' +
696
+ '<div class="s">' + esc(summary) + '</div>' +
697
+ '<div class="f"><span class="tag">' + esc(tag) + '</span></div>' +
698
+ '</a>'
699
+ );
700
+ }
701
+
702
+ // Build the top briefing paragraph from overview + repos + delegations + schedules.
703
+ function composeBriefing(state) {
704
+ var work = state.work || [];
705
+ var projects = state.projects || [];
706
+ var active = work.filter(function (w) { return !DONE[w.status]; });
707
+ var activeProjects = projects.filter(function (p) { return p.status === 'in-progress' || p.status === 'planned'; });
708
+ var onOp = active.filter(function (w) { return w.assignee === 'operator'; }).length;
709
+ var blocked = active.filter(function (w) { return w.status === 'blocked'; }).length;
710
+ var parts = [];
711
+ parts.push(
712
+ "You've got <span class=\"em\">" + activeProjects.length + ' active ' + pluralise(activeProjects.length, 'project') +
713
+ '</span> and <span class=\"em\">' + active.length + ' work ' + pluralise(active.length, 'item') +
714
+ '</span> in flight.'
715
+ );
716
+ if (onOp > 0) {
717
+ parts.push(
718
+ '<span class="alert">' + onOp + (onOp === 1 ? ' is on you' : ' are on you') + '</span>' +
719
+ (blocked > 0 ? ' — ' + (blocked === 1 ? 'one is blocked' : blocked + ' are blocked') : '') + '.'
720
+ );
721
+ } else if (blocked > 0) {
722
+ parts.push('<span class="warn">' + blocked + ' ' + pluralise(blocked, 'item') + ' blocked</span>.');
723
+ } else {
724
+ parts.push('<span class="ok">Nothing on you right now.</span>');
725
+ }
726
+ if (state.openPrs != null) {
727
+ if (state.openPrs > 0) {
728
+ parts.push('<span class="warn">' + state.openPrs + ' ' + pluralise(state.openPrs, 'PR') + '</span> open.');
729
+ } else {
730
+ parts.push('<span class="ok">No open PRs.</span>');
731
+ }
732
+ }
733
+ if (state.inFlight != null && state.inFlight > 0) {
734
+ parts.push('<span class="em">' + state.inFlight + ' ' + pluralise(state.inFlight, 'dispatch', 'dispatches') + '</span> in flight.');
735
+ }
736
+ if (state.scheduleToday != null) {
737
+ if (state.scheduleToday > 0) {
738
+ parts.push('<span class="em">' + state.scheduleToday + ' scheduled ' + pluralise(state.scheduleToday, 'run') + '</span> today.');
739
+ }
740
+ }
741
+ return parts.join(' ');
742
+ }
743
+
744
+ // Friendly label fallback when /__api/knowledge-map displayName is null
745
+ // (e.g. older domains.json without the field populated).
746
+ var DOMAIN_LABEL_FALLBACK = {
747
+ engineering: 'Engineering',
748
+ hr: 'People & team',
749
+ systems: 'Systems & infra',
750
+ owner: 'About you',
751
+ 'operator-profile': 'About you',
752
+ claudeCodeLearnings: 'Claude Code learnings',
753
+ 'claude-code-learnings': 'Claude Code learnings'
754
+ };
755
+ function domainDisplayLabel(d) {
756
+ if (!d) return '';
757
+ if (d.displayName) return d.displayName;
758
+ if (DOMAIN_LABEL_FALLBACK[d.id]) return DOMAIN_LABEL_FALLBACK[d.id];
759
+ if (d.name && d.name !== d.id) return d.name;
760
+ // Capitalise a plain id like "engineering" → "Engineering"
761
+ if (!d.id) return '';
762
+ return d.id.charAt(0).toUpperCase() + d.id.slice(1);
763
+ }
764
+ function topicHealthClass(d) {
765
+ var docs = d.documentCount || 0;
766
+ if (docs <= 3) return 'thin';
767
+ var health = d.health;
768
+ if (health === 'red') return 'stale';
769
+ if (health === 'warn') return 'warm';
770
+ if (health === 'good') return 'fresh';
771
+ return 'fresh';
772
+ }
773
+
774
+ // ── Main orchestration ─────────────────────────────────────────
775
+ (function load() {
776
+ // Core data that drives the whole page. If /__api/overview fails outright,
777
+ // we fall into sparse mode — that's the signal that this workspace isn't
778
+ // live yet.
779
+ var overviewP = fetch('/__api/overview', { cache: 'no-store' }).then(function (r) { return r.json(); });
780
+
781
+ // Everything else is additive — each has its own catch and degrades gracefully.
782
+ var notesP = fetch('/__api/notes', { cache: 'no-store' }).then(function (r) { return r.json(); }).catch(function () { return null; });
783
+ var reposP = fetch('/__api/repos', { cache: 'no-store' }).then(function (r) { return r.json(); }).catch(function () { return null; });
784
+ var stagingP = fetch('/__api/staging', { cache: 'no-store' }).then(function (r) { return r.json(); }).catch(function () { return null; });
785
+ var domainsP = fetch('/__api/knowledge-map', { cache: 'no-store' }).then(function (r) { return r.json(); }).catch(function () { return null; });
786
+ var delegationsP = fetch('/__api/delegations', { cache: 'no-store' }).then(function (r) { return r.json(); }).catch(function () { return null; });
787
+ var nextSessionP = fetch('/__api/next-session', { cache: 'no-store' }).then(function (r) {
788
+ // Older deployments (pre Phase A) may 404 — treat as absent-but-fine.
789
+ if (!r.ok) return { present: false };
790
+ return r.json();
791
+ }).catch(function () { return { present: false }; });
792
+ var schedulesP = fetch('/__api/schedules', { cache: 'no-store' }).then(function (r) { return r.json(); }).catch(function () { return null; });
793
+
794
+ overviewP.then(function (ov) {
795
+ if (!ov || typeof ov !== 'object') { forceSparse(); return; }
796
+ var work = Array.isArray(ov.work) ? ov.work : [];
797
+ var projects = Array.isArray(ov.projects) ? ov.projects : [];
798
+
799
+ var active = work.filter(function (w) { return !DONE[w.status]; });
800
+ var activeProjects = projects.filter(function (p) { return p.status === 'in-progress' || p.status === 'planned'; });
801
+
802
+ // Sparse auto-trigger: both projects and active work empty → show sparse.
803
+ if (active.length === 0 && activeProjects.length === 0) {
804
+ forceSparse();
805
+ return;
806
+ }
807
+
808
+ // Greeting: operator name preferred; fall back to /__api/config.
809
+ var operatorName = ov.operatorName;
810
+ var paName = ov.paName || null;
811
+ if (!operatorName) {
812
+ // /__api/config is a quick fetch — it gives a display-name-style "name"
813
+ // field on prefs.operator even when the profile JSON is absent.
814
+ fetch('/__api/config', { cache: 'no-store' })
815
+ .then(function (r) { return r.json(); })
816
+ .then(function (cfg) {
817
+ if (cfg && cfg.operator && cfg.operator.name) setText('greet-name', cfg.operator.name);
818
+ })
819
+ .catch(function () { /* leave placeholder */ });
820
+ } else {
821
+ setText('greet-name', operatorName);
822
+ }
823
+
824
+ // On you / On me
825
+ var onYou = active.filter(function (w) { return w.assignee === 'operator'; });
826
+ var onMe = active.filter(function (w) {
827
+ return w.assignee && w.assignee !== 'operator';
828
+ });
829
+ function sortWork(a, b) {
830
+ var sa = STATE_RANK[a.status] != null ? STATE_RANK[a.status] : 99;
831
+ var sb = STATE_RANK[b.status] != null ? STATE_RANK[b.status] : 99;
832
+ if (sa !== sb) return sa - sb;
833
+ return (a.priority == null ? 99 : a.priority) - (b.priority == null ? 99 : b.priority);
834
+ }
835
+ onYou.sort(sortWork);
836
+ onMe.sort(sortWork);
837
+
838
+ setText('on-you-count', onYou.length + ' ' + pluralise(onYou.length, 'item'));
839
+ setText('on-me-count', onMe.length + ' ' + pluralise(onMe.length, 'item'));
840
+ if (onYou.length === 0) {
841
+ setHtml('on-you-list', '<div class="row-empty">Nothing on you right now.</div>');
842
+ } else {
843
+ setHtml('on-you-list', onYou.slice(0, 6).map(function (w) { return renderRow(w, paName, operatorName); }).join(''));
844
+ }
845
+ if (onMe.length === 0) {
846
+ setHtml('on-me-list', '<div class="row-empty">No open items on me.</div>');
847
+ } else {
848
+ setHtml('on-me-list', onMe.slice(0, 6).map(function (w) { return renderRow(w, paName, operatorName); }).join(''));
849
+ }
850
+
851
+ // Projects deck
852
+ activeProjects.sort(function (a, b) {
853
+ var ra = a.status === 'in-progress' ? 0 : 1;
854
+ var rb = b.status === 'in-progress' ? 0 : 1;
855
+ if (ra !== rb) return ra - rb;
856
+ return (a.priority == null ? 99 : a.priority) - (b.priority == null ? 99 : b.priority);
857
+ });
858
+ var p0 = activeProjects.filter(function (p) { return p.priority === 0; }).length;
859
+ var p1 = activeProjects.filter(function (p) { return p.priority === 1; }).length;
860
+ var p2 = activeProjects.filter(function (p) { return p.priority === 2; }).length;
861
+ var countLabel = activeProjects.length + ' live';
862
+ var prBits = [];
863
+ if (p0 > 0) prBits.push(p0 + ' P0');
864
+ if (p1 > 0) prBits.push(p1 + ' P1');
865
+ if (p2 > 0) prBits.push(p2 + ' P2');
866
+ if (prBits.length) countLabel += ' · ' + prBits.join(' · ');
867
+ setText('projects-count', countLabel);
868
+ if (activeProjects.length === 0) {
869
+ setHtml('projects-deck', '<div class="deck-empty">No active projects.</div>');
870
+ } else {
871
+ setHtml('projects-deck', activeProjects.slice(0, 10).map(renderProjectCard).join(''));
872
+ }
873
+
874
+ // Build briefing as data arrives (two-pass: first with what we have,
875
+ // then again when additive data lands).
876
+ var briefingState = { work: work, projects: projects };
877
+ setHtml('briefing', composeBriefing(briefingState));
878
+
879
+ // Additive: notes rail
880
+ notesP.then(function (n) {
881
+ if (!n || !Array.isArray(n.notes)) { setHtml('notes-deck', '<div class="deck-empty">No open notes.</div>'); return; }
882
+ var notes = n.notes.slice(0, 8);
883
+ setText('notes-count', n.notes.length + ' total · ' + notes.length + ' shown');
884
+ if (notes.length === 0) {
885
+ setHtml('notes-deck', '<div class="deck-empty">No open notes.</div>');
886
+ } else {
887
+ setHtml('notes-deck', notes.map(renderNoteCard).join(''));
888
+ }
889
+ });
890
+
891
+ // Additive: pulse strip "Open PRs" + briefing line update
892
+ reposP.then(function (r) {
893
+ if (!r) return;
894
+ var prs = Array.isArray(r.openPrs) ? r.openPrs : [];
895
+ briefingState.openPrs = prs.length;
896
+ setText('pulse-prs', prs.length);
897
+ var prsEl = byId('pulse-prs');
898
+ if (prsEl) prsEl.className = 'v' + (prs.length === 0 ? ' ok' : ' warn');
899
+ var byHost = {};
900
+ for (var i = 0; i < prs.length; i++) {
901
+ var repoKey = prs[i].repo || 'other';
902
+ byHost[repoKey] = (byHost[repoKey] || 0) + 1;
903
+ }
904
+ var hostKeys = Object.keys(byHost);
905
+ if (hostKeys.length) {
906
+ var sub = hostKeys.sort().map(function (k) { return byHost[k] + ' ' + k; }).join(' · ');
907
+ setText('pulse-prs-sub', sub);
908
+ } else {
909
+ setText('pulse-prs-sub', '');
910
+ }
911
+ setHtml('briefing', composeBriefing(briefingState));
912
+ });
913
+
914
+ // Additive: pulse "Team activity"
915
+ delegationsP.then(function (d) {
916
+ if (!d) return;
917
+ var stats = d.stats || {};
918
+ var inFlight = stats.inFlight || 0;
919
+ var success = stats.success || 0;
920
+ briefingState.inFlight = inFlight;
921
+ setText('pulse-team', inFlight + ' in flight');
922
+ var teamEl = byId('pulse-team');
923
+ if (teamEl) teamEl.className = 'v' + (inFlight === 0 ? ' ok' : ' info');
924
+ var agentNames = (d.agents || []).map(function (a) { return a.name; }).join(' · ');
925
+ var subParts = [];
926
+ if (agentNames) subParts.push(agentNames);
927
+ if (success) subParts.push(success + ' done');
928
+ setText('pulse-team-sub', subParts.join(' · '));
929
+ setHtml('briefing', composeBriefing(briefingState));
930
+ });
931
+
932
+ // Additive: pulse "To remember" + aside "What I've noticed this session"
933
+ stagingP.then(function (s) {
934
+ if (!s || !s.stats) return;
935
+ var total = s.stats.totalItems || 0;
936
+ var byCat = s.stats.byCategory || {};
937
+ var oldest = s.stats.oldestAgeDays;
938
+ setText('pulse-remember', total + ' to file');
939
+ var rEl = byId('pulse-remember');
940
+ if (rEl) rEl.className = 'v' + (total === 0 ? ' ok' : (total >= 10 ? ' alert' : ' warn'));
941
+ setText('pulse-remember-sub', oldest == null ? 'none staged' : ('oldest ' + oldest + 'd'));
942
+
943
+ setText('ap-noticed-count', total);
944
+ var rows = [];
945
+ var LABEL = {
946
+ preference: { s: 'preference', p: 'preferences' },
947
+ correction: { s: 'correction', p: 'corrections' },
948
+ decision: { s: 'decision', p: 'decisions' },
949
+ pattern: { s: 'pattern', p: 'patterns' },
950
+ contact: { s: 'contact', p: 'contacts' },
951
+ domain: { s: 'topic note', p: 'topic notes' },
952
+ feedback: { s: 'piece of feedback', p: 'pieces of feedback' },
953
+ other: { s: 'other note', p: 'other notes' }
954
+ };
955
+ var keys = Object.keys(byCat).sort(function (a, b) { return byCat[b] - byCat[a]; });
956
+ for (var i = 0; i < keys.length; i++) {
957
+ var k = keys[i];
958
+ var n = byCat[k];
959
+ var lbl = LABEL[k] || { s: k, p: k + 's' };
960
+ var noun = n === 1 ? lbl.s : lbl.p;
961
+ rows.push(
962
+ '<div class="nts-row">' +
963
+ '<span class="label">' + n + ' ' + esc(noun) + '</span>' +
964
+ '<span class="cat ' + esc(k) + '">' + esc(k) + '</span>' +
965
+ '</div>'
966
+ );
967
+ }
968
+ setHtml('nts-list', rows.length ? rows.join('') : '<div class="ap-empty">Nothing new to file.</div>');
969
+ setText('nts-oldest', oldest == null ? '—' : (oldest + 'd — files at 03:00'));
970
+ });
971
+
972
+ // Additive: pulse "What I know" + aside "Topics I track"
973
+ domainsP.then(function (k) {
974
+ if (!k || !Array.isArray(k.domains)) return;
975
+ var totalDocs = (k.stats && k.stats.totalDocuments) || 0;
976
+ var areaCount = k.domains.length;
977
+ var needsReview = k.domains.filter(function (d) { return d.health === 'red' || d.health === 'warn'; }).length;
978
+ setText('pulse-know', totalDocs + ' docs · ' + areaCount + ' ' + pluralise(areaCount, 'area'));
979
+ setText('pulse-know-sub', needsReview === 0
980
+ ? 'all healthy'
981
+ : needsReview + ' ' + pluralise(needsReview, 'needs review', 'need review'));
982
+ setText('ap-topics-meta', areaCount + ' ' + pluralise(areaCount, 'area') + ' · ' + totalDocs + ' docs');
983
+
984
+ var sorted = k.domains.slice().sort(function (a, b) {
985
+ return (b.documentCount || 0) - (a.documentCount || 0);
986
+ });
987
+ var topicHtml = [];
988
+ for (var i = 0; i < sorted.length && i < 8; i++) {
989
+ var d = sorted[i];
990
+ var cls = topicHealthClass(d);
991
+ topicHtml.push(
992
+ '<div class="topic-row">' +
993
+ '<span class="topic-name">' + esc(domainDisplayLabel(d)) + '</span>' +
994
+ '<span class="topic-meta">' +
995
+ '<span class="topic-count">' + (d.documentCount || 0) + '</span>' +
996
+ '<span class="topic-health ' + cls + '">' + cls + '</span>' +
997
+ '</span>' +
998
+ '</div>'
999
+ );
1000
+ }
1001
+ setHtml('topic-list', topicHtml.length ? topicHtml.join('') : '<div class="ap-empty">No topics yet.</div>');
1002
+ });
1003
+
1004
+ // Additive: pulse "Schedules"
1005
+ schedulesP.then(function (s) {
1006
+ if (!s) return;
1007
+ var schedules = Array.isArray(s.schedules) ? s.schedules : [];
1008
+ var enabled = schedules.filter(function (x) { return x.enabled !== false; }).length;
1009
+ var todayRuns = (s.agenda && Array.isArray(s.agenda.today)) ? s.agenda.today.length : 0;
1010
+ briefingState.scheduleToday = todayRuns;
1011
+ setText('pulse-schedules', enabled + ' healthy');
1012
+ var schEl = byId('pulse-schedules');
1013
+ if (schEl) schEl.className = 'v' + (enabled > 0 ? ' ok' : '');
1014
+ var sub = s.hostname ? ('on ' + s.hostname) : '';
1015
+ if (todayRuns) sub = (sub ? (sub + ' · ') : '') + todayRuns + ' today';
1016
+ setText('pulse-schedules-sub', sub);
1017
+ setHtml('briefing', composeBriefing(briefingState));
1018
+ });
1019
+
1020
+ // Pick-up card from /__api/next-session
1021
+ nextSessionP.then(function (ns) {
1022
+ if (!ns || !ns.present || !ns.topPriority) return;
1023
+ var card = byId('pickup');
1024
+ if (!card) return;
1025
+ var tp = ns.topPriority;
1026
+ var title = tp.title || 'Pick up where you left off';
1027
+ // Render body as near-prose: strip heavy markdown but keep inline code,
1028
+ // bold, italics, and link text for warmth. Paths/ids use inline code.
1029
+ var body = (tp.body || '')
1030
+ // Inline code → <code>
1031
+ .replace(/`([^`]+)`/g, function (_m, t) { return '<code>' + esc(t) + '</code>'; })
1032
+ // Bold → <strong>
1033
+ .replace(/\*\*([^*]+)\*\*/g, function (_m, t) { return '<strong>' + esc(t) + '</strong>'; })
1034
+ // Italic → <em>
1035
+ .replace(/(^|[^*])\*([^*\n]+)\*/g, function (_m, pre, t) { return pre + '<em>' + esc(t) + '</em>'; })
1036
+ // Markdown links [x](y) → <a href=y>x</a>
1037
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, function (_m, text, href) {
1038
+ return '<a onclick="nav(\'' + esc(href) + '\')">' + esc(text) + '</a>';
1039
+ });
1040
+ // If no markdown was applied, escape the raw text for safety.
1041
+ if (body === tp.body) body = esc(body);
1042
+ setText('pickup-title', title);
1043
+ setHtml('pickup-body', body);
1044
+ // Actions: "See all tasks" + (if onBoot present) "Full handover"
1045
+ var actions = '<a class="btn primary" onclick="nav(\'/tasks.html\')">See all tasks</a>';
1046
+ if (ns.path) {
1047
+ actions += ' <a class="btn" onclick="nav(\'/viewer.html?file=' + encodeURIComponent(ns.path) + '\')">Open handover note</a>';
1048
+ }
1049
+ setHtml('pickup-actions', actions);
1050
+ card.classList.remove('hidden');
1051
+ });
1052
+ }).catch(function () {
1053
+ // Overview itself failed — this is the "workspace not wired" case.
1054
+ forceSparse();
1055
+ });
1056
+ })();
1057
+ </script>
1058
+
1059
+ </body>
1060
+ </html>