@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,187 @@
1
+ /**
2
+ * Shared Markdown → HTML renderer.
3
+ * Browser: exposes window.renderMd(md) → html
4
+ * Node: exports { renderMd } via module.exports
5
+ *
6
+ * Features: H1-H6, bold/italic/bold-italic, inline code, fenced code blocks,
7
+ * links, pipe tables (with alignment), horizontal rules, blockquotes, ul/ol lists.
8
+ *
9
+ * Self-test: node core/tools/workspace/app/assets/md.js → prints "OK"
10
+ */
11
+ (function (root) {
12
+ 'use strict';
13
+
14
+ var BLOCK_RE = /^<(ul|ol|table|pre|h[1-6]|hr|blockquote)/;
15
+
16
+ function renderMd(md) {
17
+ if (!md) return '';
18
+
19
+ // 1. HTML-escape (before any markdown substitution)
20
+ var s = md.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
21
+
22
+ // 2. Protect fenced code blocks with placeholders
23
+ var codeBlocks = [];
24
+ s = s.replace(/```([^\n]*)\n([\s\S]*?)```/g, function (_, lang, code) {
25
+ codeBlocks.push('<pre><code>' + code + '</code></pre>');
26
+ return '\x00CB' + (codeBlocks.length - 1) + '\x00';
27
+ });
28
+
29
+ // 3. Inline code
30
+ s = s.replace(/`([^`\n]+)`/g, '<code>$1</code>');
31
+
32
+ // 4. Headings H1-H6 (longest match first)
33
+ s = s.replace(/^###### (.+)$/gm, '<h6>$1</h6>');
34
+ s = s.replace(/^##### (.+)$/gm, '<h5>$1</h5>');
35
+ s = s.replace(/^#### (.+)$/gm, '<h4>$1</h4>');
36
+ s = s.replace(/^### (.+)$/gm, '<h3>$1</h3>');
37
+ s = s.replace(/^## (.+)$/gm, '<h2>$1</h2>');
38
+ s = s.replace(/^# (.+)$/gm, '<h1>$1</h1>');
39
+
40
+ // 5. Horizontal rules (own line, 3+ dashes/underscores/asterisks)
41
+ s = s.replace(/^(-{3,}|_{3,}|\*{3,})$/gm, '<hr>');
42
+
43
+ // 6. Bold-italic, bold, italic, links
44
+ s = s.replace(/\*\*\*(.+?)\*\*\*/g, '<strong><em>$1</em></strong>');
45
+ s = s.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
46
+ s = s.replace(/\*(.+?)\*/g, '<em>$1</em>');
47
+ s = s.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" rel="noopener">$1</a>');
48
+
49
+ // 7. Block pass — walk lines to handle tables, blockquotes, lists
50
+ var lines = s.split('\n');
51
+ var out = [];
52
+ var i = 0;
53
+
54
+ while (i < lines.length) {
55
+ var line = lines[i];
56
+
57
+ // ── Pipe table ──
58
+ // Detected when current line starts with '|' AND next line is a separator row
59
+ if (/^\|/.test(line) && i + 1 < lines.length && /^\|[\s\-:|]+\|/.test(lines[i + 1])) {
60
+ var rows = [];
61
+ while (i < lines.length && /^\|/.test(lines[i])) { rows.push(lines[i]); i++; }
62
+
63
+ var hdrCells = rows[0].replace(/^\||\|$/g, '').split('|').map(function (c) { return c.trim(); });
64
+ var aligns = rows[1].replace(/^\||\|$/g, '').split('|').map(function (c) {
65
+ c = c.trim();
66
+ if (/^:-+:$/.test(c)) return 'center';
67
+ if (/^-+:$/.test(c)) return 'right';
68
+ return 'left';
69
+ });
70
+
71
+ var thead = '<thead><tr>' + hdrCells.map(function (c, j) {
72
+ return '<th style="text-align:' + (aligns[j] || 'left') + '">' + c + '</th>';
73
+ }).join('') + '</tr></thead>';
74
+
75
+ var tbody = '';
76
+ if (rows.length > 2) {
77
+ tbody = '<tbody>' + rows.slice(2).map(function (row) {
78
+ var cells = row.replace(/^\||\|$/g, '').split('|').map(function (c) { return c.trim(); });
79
+ return '<tr>' + cells.map(function (c, j) {
80
+ return '<td style="text-align:' + (aligns[j] || 'left') + '">' + c + '</td>';
81
+ }).join('') + '</tr>';
82
+ }).join('') + '</tbody>';
83
+ }
84
+ out.push('<table>' + thead + tbody + '</table>');
85
+ continue;
86
+ }
87
+
88
+ // ── Blockquote ── (HTML-escaped '>' becomes '&gt;')
89
+ if (/^&gt; /.test(line)) {
90
+ var bqLines = [];
91
+ while (i < lines.length && /^&gt; /.test(lines[i])) {
92
+ bqLines.push(lines[i].replace(/^&gt; /, ''));
93
+ i++;
94
+ }
95
+ out.push('<blockquote>' + bqLines.join('\n') + '</blockquote>');
96
+ continue;
97
+ }
98
+
99
+ // ── Unordered list ──
100
+ if (/^[*\-] /.test(line)) {
101
+ out.push('<ul>');
102
+ while (i < lines.length && /^[*\-] /.test(lines[i])) {
103
+ out.push('<li>' + lines[i].replace(/^[*\-] /, '') + '</li>');
104
+ i++;
105
+ }
106
+ out.push('</ul>');
107
+ continue;
108
+ }
109
+
110
+ // ── Ordered list ──
111
+ if (/^\d+\. /.test(line)) {
112
+ out.push('<ol>');
113
+ while (i < lines.length && /^\d+\. /.test(lines[i])) {
114
+ out.push('<li>' + lines[i].replace(/^\d+\. /, '') + '</li>');
115
+ i++;
116
+ }
117
+ out.push('</ol>');
118
+ continue;
119
+ }
120
+
121
+ out.push(line);
122
+ i++;
123
+ }
124
+ s = out.join('\n');
125
+
126
+ // 8. Paragraph wrapping — split on blank lines; skip block-level HTML
127
+ s = s.split(/\n\n+/).map(function (block) {
128
+ block = block.trim();
129
+ if (!block) return '';
130
+ var first = block.split('\n')[0];
131
+ if (BLOCK_RE.test(first) || first.charAt(0) === '\x00') return block;
132
+ return '<p>' + block.replace(/\n/g, '<br>') + '</p>';
133
+ }).join('\n');
134
+
135
+ // 9. Restore code blocks
136
+ codeBlocks.forEach(function (blk, idx) {
137
+ s = s.replace('\x00CB' + idx + '\x00', blk);
138
+ });
139
+
140
+ return s;
141
+ }
142
+
143
+ // ── Export ──
144
+ if (typeof module !== 'undefined' && module.exports) {
145
+ module.exports = { renderMd: renderMd };
146
+ } else {
147
+ root.renderMd = renderMd;
148
+ }
149
+
150
+ // ── Self-test (runs when invoked directly: node md.js → prints "OK") ──
151
+ // Works in both CJS and ESM contexts (no require needed).
152
+ if (typeof process !== 'undefined' && process.argv && process.argv[1] &&
153
+ process.argv[1].indexOf('md.js') !== -1) {
154
+ var _f = 0;
155
+ function _chk(cond, name) { if (!cond) { console.error('FAIL: ' + name); _f++; } }
156
+
157
+ var _t = renderMd('| A | B |\n|---|---|\n| 1 | 2 |');
158
+ _chk(_t.includes('<table>'), 'table: <table>');
159
+ _chk(_t.includes('<thead>'), 'table: <thead>');
160
+ _chk(_t.includes('<th'), 'table: <th>');
161
+ _chk(_t.includes('<tbody>'), 'table: <tbody>');
162
+ _chk(_t.includes('<td'), 'table: <td>');
163
+
164
+ _chk(renderMd('---').includes('<hr>'), 'hr: ---');
165
+ _chk(renderMd('___').includes('<hr>'), 'hr: ___');
166
+ _chk(renderMd('***').includes('<hr>'), 'hr: ***');
167
+
168
+ _chk(renderMd('#### h4').includes('<h4>'), 'h4');
169
+ _chk(renderMd('##### h5').includes('<h5>'), 'h5');
170
+ _chk(renderMd('###### h6').includes('<h6>'), 'h6');
171
+
172
+ var _l = renderMd('- alpha\n- beta\n- gamma');
173
+ _chk(_l.includes('<ul>'), 'list: <ul>');
174
+ _chk(_l.includes('<li>'), 'list: <li>');
175
+ _chk(!_l.includes('<br>'), 'list: no <br> inside list');
176
+
177
+ _chk(renderMd('**bold**').includes('<strong>bold</strong>'), 'bold');
178
+ _chk(renderMd('*em*').includes('<em>em</em>'), 'italic');
179
+ _chk(renderMd('> quote').includes('<blockquote>'), 'blockquote');
180
+ _chk(renderMd('`code`').includes('<code>code</code>'), 'inline code');
181
+ _chk(renderMd('```js\nconsole.log(1);\n```').includes('<pre><code>'), 'fenced code');
182
+
183
+ if (_f) process.exit(1);
184
+ console.log('OK');
185
+ }
186
+
187
+ }(typeof window !== 'undefined' ? window : {}));
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Shared modal helper for workspace pages.
3
+ *
4
+ * Provides a tiny imperative API without pulling in a framework:
5
+ * - openModal({ title, html }) — show modal, set heading + body HTML
6
+ * - closeModal() — hide modal
7
+ * - initModal() — idempotently injects the DOM + CSS into
8
+ * the current document and wires backdrop
9
+ * + ESC handlers. Call once on page boot
10
+ * (safe to call multiple times).
11
+ *
12
+ * Styling follows the Tokyo Night palette already used across the four
13
+ * audit pages. The modal uses max-height + internal scroll so long records
14
+ * remain readable without blowing out the viewport. No external CSS needed.
15
+ *
16
+ * Browser: exposes window.openModal / window.closeModal / window.initModal
17
+ * Self-test: none — this is DOM-only glue, covered indirectly by e2e.
18
+ */
19
+ (function (root) {
20
+ 'use strict';
21
+
22
+ var CSS =
23
+ '.ws-modal-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,0.65);z-index:200;align-items:center;justify-content:center;padding:1rem}' +
24
+ '.ws-modal-overlay.open{display:flex}' +
25
+ '.ws-modal{background:var(--bg-surface,#1f2335);border:1px solid var(--border,#3b4261);border-radius:10px;max-width:780px;width:100%;max-height:85vh;display:flex;flex-direction:column;position:relative;font-family:inherit}' +
26
+ '.ws-modal-header{padding:1rem 1.25rem 0.5rem;border-bottom:1px solid var(--border,#3b4261);display:flex;align-items:center;gap:0.75rem}' +
27
+ '.ws-modal-title{color:var(--text-bright,#e0e6ff);font-size:1rem;font-weight:600;flex:1;min-width:0;word-break:break-word}' +
28
+ '.ws-modal-close{background:var(--bg-highlight,#292e42);border:1px solid var(--border,#3b4261);border-radius:4px;color:var(--text-dim,#565f89);font-size:0.72rem;padding:0.25rem 0.6rem;cursor:pointer;font-family:inherit;flex-shrink:0}' +
29
+ '.ws-modal-close:hover{color:var(--text-bright,#e0e6ff);border-color:var(--accent,#7aa2f7)}' +
30
+ '.ws-modal-body{padding:1rem 1.25rem 1.25rem;overflow-y:auto;color:var(--text,#c0caf5);font-size:0.8rem;line-height:1.6}' +
31
+ '.ws-modal-body pre{background:var(--bg-highlight,#292e42);border:1px solid var(--border,#3b4261);border-radius:5px;padding:0.6rem;overflow-x:auto;font-size:0.72rem;white-space:pre-wrap;word-break:break-word}' +
32
+ '.ws-modal-body code{background:var(--bg-highlight,#292e42);border:1px solid var(--border,#3b4261);border-radius:3px;padding:0.05rem 0.3rem;font-size:0.78em;color:var(--cyan,#7dcfff)}' +
33
+ '.ws-modal-body pre code{background:transparent;border:none;padding:0;color:inherit}' +
34
+ '.ws-modal-body h1,.ws-modal-body h2,.ws-modal-body h3,.ws-modal-body h4{color:var(--text-bright,#e0e6ff);margin:0.75rem 0 0.35rem}' +
35
+ '.ws-modal-body h1{font-size:1rem}.ws-modal-body h2{font-size:0.9rem;border-bottom:1px solid var(--border,#3b4261);padding-bottom:0.15rem}' +
36
+ '.ws-modal-body h3{font-size:0.82rem;color:var(--purple,#bb9af7)}' +
37
+ '.ws-modal-body p{margin-bottom:0.5rem}' +
38
+ '.ws-modal-body ul,.ws-modal-body ol{padding-left:1.3rem;margin-bottom:0.5rem}' +
39
+ '.ws-modal-body li{margin-bottom:0.1rem}' +
40
+ '.ws-modal-body a{color:var(--accent,#7aa2f7);text-decoration:none}' +
41
+ '.ws-modal-body a:hover{text-decoration:underline}' +
42
+ '.ws-modal-body .kv{display:grid;grid-template-columns:7rem 1fr;gap:0.35rem 0.75rem;font-size:0.76rem;margin-bottom:0.75rem}' +
43
+ '.ws-modal-body .kv .k{color:var(--text-dim,#565f89);text-transform:uppercase;letter-spacing:0.05em;font-size:0.64rem;padding-top:0.1rem}' +
44
+ '.ws-modal-body .kv .v{color:var(--text,#c0caf5);word-break:break-word}' +
45
+ '.ws-modal-body .kv .v.mono{font-family:"SF Mono","JetBrains Mono",monospace;font-size:0.72rem;color:var(--cyan,#7dcfff)}' +
46
+ '.ws-modal-body .section-label{color:var(--text-dim,#565f89);text-transform:uppercase;letter-spacing:0.05em;font-size:0.64rem;margin-top:0.75rem;margin-bottom:0.3rem}';
47
+
48
+ var initialised = false;
49
+ var keyHandlerAttached = false;
50
+
51
+ function ensureStyles() {
52
+ if (document.getElementById('ws-modal-styles')) return;
53
+ var style = document.createElement('style');
54
+ style.id = 'ws-modal-styles';
55
+ style.textContent = CSS;
56
+ document.head.appendChild(style);
57
+ }
58
+
59
+ function ensureDom() {
60
+ if (document.getElementById('ws-modal-overlay')) return;
61
+ var overlay = document.createElement('div');
62
+ overlay.className = 'ws-modal-overlay';
63
+ overlay.id = 'ws-modal-overlay';
64
+ overlay.setAttribute('role', 'dialog');
65
+ overlay.setAttribute('aria-modal', 'true');
66
+ overlay.innerHTML =
67
+ '<div class="ws-modal" id="ws-modal">' +
68
+ '<div class="ws-modal-header">' +
69
+ '<div class="ws-modal-title" id="ws-modal-title"></div>' +
70
+ '<button class="ws-modal-close" id="ws-modal-close" type="button">Close ✕</button>' +
71
+ '</div>' +
72
+ '<div class="ws-modal-body" id="ws-modal-body"></div>' +
73
+ '</div>';
74
+ document.body.appendChild(overlay);
75
+ // Backdrop click closes modal; clicks inside panel do not propagate.
76
+ overlay.addEventListener('click', function (e) {
77
+ if (e.target === overlay) closeModal();
78
+ });
79
+ document.getElementById('ws-modal').addEventListener('click', function (e) {
80
+ e.stopPropagation();
81
+ });
82
+ document.getElementById('ws-modal-close').addEventListener('click', closeModal);
83
+ }
84
+
85
+ function attachKeyHandler() {
86
+ if (keyHandlerAttached) return;
87
+ document.addEventListener('keydown', function (e) {
88
+ if (e.key === 'Escape') closeModal();
89
+ });
90
+ keyHandlerAttached = true;
91
+ }
92
+
93
+ function initModal() {
94
+ if (initialised) return;
95
+ ensureStyles();
96
+ ensureDom();
97
+ attachKeyHandler();
98
+ initialised = true;
99
+ }
100
+
101
+ function openModal(opts) {
102
+ initModal();
103
+ var title = (opts && opts.title) || '';
104
+ var html = (opts && opts.html) || '';
105
+ var t = document.getElementById('ws-modal-title');
106
+ var b = document.getElementById('ws-modal-body');
107
+ if (t) t.textContent = title;
108
+ if (b) b.innerHTML = html;
109
+ document.getElementById('ws-modal-overlay').classList.add('open');
110
+ }
111
+
112
+ function closeModal() {
113
+ var o = document.getElementById('ws-modal-overlay');
114
+ if (o) o.classList.remove('open');
115
+ }
116
+
117
+ root.openModal = openModal;
118
+ root.closeModal = closeModal;
119
+ root.initModal = initModal;
120
+ }(typeof window !== 'undefined' ? window : {}));
@@ -0,0 +1,132 @@
1
+ /*
2
+ * Workspace theme tokens — single source of truth for every page's palette.
3
+ *
4
+ * Two themes live here: dark (default) and light, toggled by the operator
5
+ * via the banner button. Selection is persisted in localStorage under
6
+ * `dave.theme` and applied to `documentElement.dataset.theme` before first
7
+ * paint by the inline init script in each page's <head>.
8
+ *
9
+ * Token set is the union of every page's prior `:root` block. Both themes
10
+ * MUST define the same set of names — any unilateral token becomes invisible
11
+ * text in the opposite theme. The unit test at `test/theme.test.mjs` pins
12
+ * this parity.
13
+ *
14
+ * Palette choice: Slate-Indigo (was: 7 pages). Picked over Tokyo-Night
15
+ * because Slate's `--text-dim` already passes WCAG AAA (~7.2:1 against
16
+ * `--bg`) where Tokyo's `--text-dim: #565f89` failed AA (~2.8:1) and could
17
+ * not be lifted without breaking the cool family. Tokyo pages adopt this
18
+ * palette transparently — their var(--accent), var(--bg), etc. references
19
+ * resolve to the Slate values.
20
+ *
21
+ * `--amber` and `--blue` from the old Slate set were aliases of `--yellow`
22
+ * and `--accent` respectively; their two usages (project-detail.html,
23
+ * secrets.html) were rewritten to reference the canonical token names.
24
+ */
25
+
26
+ :root,
27
+ [data-theme="dark"] {
28
+ /* Surfaces */
29
+ --bg: #121218;
30
+ --bg-surface: #1a1a24;
31
+ --bg-highlight: #22222e;
32
+ --bg-inset: #0e0e14;
33
+ --border: #333346;
34
+
35
+ /* Text */
36
+ --text: #d4d4d8;
37
+ --text-dim: #a1a1aa;
38
+ --text-bright: #fafafa;
39
+
40
+ /* Accent + interactive */
41
+ --accent: #6366f1;
42
+ --accent-hover: #818cf8;
43
+
44
+ /* Prose emphasis — used by viewer.html's `.content strong` to make bold
45
+ * function as a visible scan-anchor. Lighter than --accent on dark so
46
+ * it clears WCAG AA (~6.3:1 vs --accent's ~4.2:1) without losing the
47
+ * indigo family signal. */
48
+ --emphasis: #818cf8;
49
+
50
+ /* Semantic */
51
+ --green: #22c55e;
52
+ --yellow: #f59e0b;
53
+ --red: #ef4444;
54
+ --purple: #a78bfa;
55
+ --cyan: #22d3ee;
56
+ --orange: #fb923c;
57
+ }
58
+
59
+ [data-theme="light"] {
60
+ /* Surfaces — soft off-white background, true-white surface so cards lift. */
61
+ --bg: #f6f6fa;
62
+ --bg-surface: #ffffff;
63
+ --bg-highlight: #ececf3;
64
+ --bg-inset: #e4e4ec;
65
+ --border: #d4d4dc;
66
+
67
+ /* Text — near-black for AAA on the soft background. */
68
+ --text: #18181b;
69
+ --text-dim: #52525b;
70
+ --text-bright: #09090b;
71
+
72
+ /* Accent + interactive — same indigo family, slightly darker for AA on white. */
73
+ --accent: #4f46e5;
74
+ --accent-hover: #6366f1;
75
+
76
+ /* Prose emphasis — sits at the accent's darkness so bold reads as a
77
+ * deliberate marker against the soft background without leaving the
78
+ * indigo family. ~5.8:1 against --bg (passes AA for body text). */
79
+ --emphasis: #4f46e5;
80
+
81
+ /* Semantic — darkened to clear AA against the light surfaces. */
82
+ --green: #15803d;
83
+ --yellow: #b45309;
84
+ --red: #b91c1c;
85
+ --purple: #6d28d9;
86
+ --cyan: #0e7490;
87
+ --orange: #c2410c;
88
+ }
89
+
90
+ /*
91
+ * Theme-toggle button: lives in the banner chrome (#global-banner). The
92
+ * button persists across banner.js's incident-row re-renders because
93
+ * banner.js clears only `[data-banner-row]` children (not `[data-theme-chrome]`).
94
+ */
95
+ #global-banner [data-theme-chrome] {
96
+ display: flex;
97
+ align-items: center;
98
+ justify-content: flex-end;
99
+ width: 100%;
100
+ padding: 4px 12px;
101
+ box-sizing: border-box;
102
+ background: var(--bg-surface);
103
+ border-bottom: 1px solid var(--border);
104
+ }
105
+
106
+ #global-banner [data-theme-toggle] {
107
+ background: transparent;
108
+ border: 1px solid var(--border);
109
+ border-radius: 4px;
110
+ width: 26px;
111
+ height: 22px;
112
+ padding: 0;
113
+ display: inline-flex;
114
+ align-items: center;
115
+ justify-content: center;
116
+ font-size: 13px;
117
+ line-height: 1;
118
+ color: var(--text-dim);
119
+ cursor: pointer;
120
+ transition: border-color 0.12s, color 0.12s, background 0.12s;
121
+ }
122
+
123
+ #global-banner [data-theme-toggle]:hover {
124
+ border-color: var(--accent);
125
+ color: var(--text-bright);
126
+ background: var(--bg-highlight);
127
+ }
128
+
129
+ #global-banner [data-theme-toggle]:focus-visible {
130
+ outline: 2px solid var(--accent);
131
+ outline-offset: 1px;
132
+ }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Workspace theme toggle.
3
+ *
4
+ * Two responsibilities split across two surfaces:
5
+ *
6
+ * 1. Pre-paint init. Each page also embeds a tiny inline <script> in <head>
7
+ * that reads `localStorage.dave.theme` and sets
8
+ * `documentElement.dataset.theme` BEFORE first paint. That avoids a
9
+ * light-flash on a dark-preference user (FOUC). The inline script is the
10
+ * duplicate of `applyStoredTheme()` below; keeping it inline is the
11
+ * explicit trade — a separate script file would race the first paint.
12
+ *
13
+ * 2. Toggle button + cross-frame coordination. The shell (index.html)
14
+ * iframes every page. When the user clicks the toggle in the shell's
15
+ * banner, the shell flips its own `data-theme`, persists, and broadcasts
16
+ * to the iframe via postMessage so the embedded page applies the same
17
+ * theme without reloading. The toggle is only rendered in the top-level
18
+ * context (matching banner.js's behaviour) so a page opened directly
19
+ * still owns its own toggle.
20
+ *
21
+ * Storage: localStorage key `dave.theme`, values 'dark' | 'light'.
22
+ * Default when unset: 'dark' (operator preference — see CLAUDE.md). We do
23
+ * NOT consult prefers-color-scheme; dark is the chosen default and we don't
24
+ * want auto-detection overriding it on first load.
25
+ */
26
+ (function () {
27
+ 'use strict';
28
+
29
+ var STORAGE_KEY = 'dave.theme';
30
+ var DEFAULT_THEME = 'dark';
31
+ var VALID = { dark: 1, light: 1 };
32
+ var MESSAGE_TYPE = 'dave.theme.set';
33
+
34
+ function readStored() {
35
+ try {
36
+ var raw = localStorage.getItem(STORAGE_KEY);
37
+ if (raw && VALID[raw]) return raw;
38
+ } catch (_e) { /* storage unavailable — fall through to default */ }
39
+ return DEFAULT_THEME;
40
+ }
41
+
42
+ function writeStored(theme) {
43
+ try { localStorage.setItem(STORAGE_KEY, theme); }
44
+ catch (_e) { /* storage unavailable — silently no-op */ }
45
+ }
46
+
47
+ function applyTheme(theme) {
48
+ if (!VALID[theme]) theme = DEFAULT_THEME;
49
+ document.documentElement.dataset.theme = theme;
50
+ var btn = document.querySelector('#global-banner [data-theme-toggle]');
51
+ if (btn) {
52
+ // Glyph shows the theme you'd switch TO, which is the universal
53
+ // convention (a moon means "switch to dark", a sun means "switch to
54
+ // light"). The label encodes the action, not the current state.
55
+ var next = theme === 'dark' ? 'light' : 'dark';
56
+ btn.textContent = next === 'dark' ? '☾' : '☀';
57
+ btn.setAttribute('aria-label', 'Switch to ' + next + ' theme');
58
+ btn.setAttribute('title', 'Switch to ' + next + ' theme');
59
+ btn.setAttribute('data-current-theme', theme);
60
+ }
61
+ }
62
+
63
+ function isTopLevel() {
64
+ try { return window.top === window.self; } catch (_e) { return false; }
65
+ }
66
+
67
+ function broadcastToFrames(theme) {
68
+ // Notify every same-origin iframe so embedded pages flip without
69
+ // reloading. Cross-origin frames silently throw; we catch and skip.
70
+ var frames = document.querySelectorAll('iframe');
71
+ for (var i = 0; i < frames.length; i++) {
72
+ try {
73
+ var win = frames[i].contentWindow;
74
+ if (!win) continue;
75
+ win.postMessage({ type: MESSAGE_TYPE, theme: theme }, window.location.origin);
76
+ } catch (_e) { /* ignore — cross-origin or detached */ }
77
+ }
78
+ }
79
+
80
+ function ensureChrome() {
81
+ var slot = document.getElementById('global-banner');
82
+ if (!slot) {
83
+ // Belt + braces: every page ships #global-banner in body, but if a
84
+ // future page forgets it, mount one so the toggle still appears.
85
+ slot = document.createElement('div');
86
+ slot.id = 'global-banner';
87
+ if (document.body.firstChild) document.body.insertBefore(slot, document.body.firstChild);
88
+ else document.body.appendChild(slot);
89
+ }
90
+ var chrome = slot.querySelector('[data-theme-chrome]');
91
+ if (chrome) return chrome;
92
+ chrome = document.createElement('div');
93
+ chrome.setAttribute('data-theme-chrome', '');
94
+ var btn = document.createElement('button');
95
+ btn.type = 'button';
96
+ btn.setAttribute('data-theme-toggle', '');
97
+ btn.addEventListener('click', function () {
98
+ var current = document.documentElement.dataset.theme || DEFAULT_THEME;
99
+ var next = current === 'dark' ? 'light' : 'dark';
100
+ writeStored(next);
101
+ applyTheme(next);
102
+ broadcastToFrames(next);
103
+ });
104
+ chrome.appendChild(btn);
105
+ // Append rather than insert-first so existing incident rows (added by
106
+ // banner.js) stay at the top; the toggle row sits below them. That
107
+ // keeps the loudest signal (an incident) in the primary position.
108
+ slot.appendChild(chrome);
109
+ return chrome;
110
+ }
111
+
112
+ function applyStoredTheme() { applyTheme(readStored()); }
113
+
114
+ // Pre-paint init: the inline <head> script already ran. We re-apply here
115
+ // in case the inline script was disabled (CSP) or theme.js loads in
116
+ // isolation (tests, embeds).
117
+ applyStoredTheme();
118
+
119
+ // Listen for theme messages from the parent (shell). Applies the theme
120
+ // and updates storage so a subsequent direct page-load matches the shell.
121
+ window.addEventListener('message', function (evt) {
122
+ if (evt.origin !== window.location.origin) return;
123
+ var data = evt.data || {};
124
+ if (data.type !== MESSAGE_TYPE) return;
125
+ if (!VALID[data.theme]) return;
126
+ writeStored(data.theme);
127
+ applyTheme(data.theme);
128
+ });
129
+
130
+ // Storage events fire in OTHER tabs when this tab writes — keeps multiple
131
+ // workspace windows in sync.
132
+ window.addEventListener('storage', function (evt) {
133
+ if (evt.key !== STORAGE_KEY) return;
134
+ if (!VALID[evt.newValue]) return;
135
+ applyTheme(evt.newValue);
136
+ });
137
+
138
+ function boot() {
139
+ // Toggle button: only at the top level. The shell already renders the
140
+ // banner and toggle; iframed pages stay quiet to avoid a second button.
141
+ if (isTopLevel()) ensureChrome();
142
+ applyStoredTheme();
143
+ }
144
+
145
+ if (document.readyState === 'loading') {
146
+ document.addEventListener('DOMContentLoaded', boot);
147
+ } else {
148
+ boot();
149
+ }
150
+
151
+ // Expose for tests + the inline init helper.
152
+ window.__daveTheme = {
153
+ read: readStored,
154
+ write: writeStored,
155
+ apply: applyTheme,
156
+ storageKey: STORAGE_KEY,
157
+ defaultTheme: DEFAULT_THEME,
158
+ };
159
+ })();