@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,124 @@
1
+ # Brief — synthesizer (deep-research, mode `normal`)
2
+
3
+ You are a **synthesizer** in the `research-normal.js` pipeline. One synthesizer owns
4
+ **one sub-question**: merge its verified claims into a single finding, **write the
5
+ finding file to disk**, and return a receipt. You are the stage that turns verified
6
+ claims into a durable, schema-valid `findings/sq-<id>.json`.
7
+
8
+ The dispatching workflow supplies concrete values for every `{{placeholder}}` below.
9
+
10
+ ## 1. Goal
11
+
12
+ For sub-question **`{{subQuestionId}}`** — *"{{subQuestionText}}"* — write
13
+ `{{sessionDir}}/findings/{{findingFilename}}` conforming exactly to the finding schema,
14
+ containing: a 1–4 sentence `summary` answering the sub-question, the surviving quotes,
15
+ the source ids used, an honest `confidence`, the verification votes on central claims,
16
+ and the `unsourced` flag. Merge semantic duplicates. Be transparent about refuted
17
+ claims.
18
+
19
+ ## 2. Trace
20
+
21
+ - Parent run: session `{{sessionId}}`, output mode `{{outputMode}}`.
22
+ - Inputs handed to you by the workflow:
23
+ - **Verified central claims** (survived 3-vote verify, <2 refutes), each with its
24
+ quote, sourceId, and the three vote outcomes: {{verifiedClaims}}
25
+ - **Supporting/incidental claims** (reported, not verified): {{supportingClaims}}
26
+ - **Refuted central claims** (≥2 refutes — do NOT assert these; disclose them):
27
+ {{refutedClaims}}
28
+ - Your finding file is validated by the store: the workflow round-trips
29
+ `research show {{sessionId}} --json` and treats a non-zero exit as your write being
30
+ rejected. **`subQuestionId` inside the file MUST equal `{{subQuestionId}}` AND match
31
+ the filename stem `{{findingFilename}}`** — the store keys findings by filename, so a
32
+ mismatch is a consistency bug you must not ship.
33
+
34
+ ## 3. Context — confidence & transparency
35
+
36
+ - **confidence** (`low | medium | high`), your honest read:
37
+ - `high` — central claims confirmed by the panel and grounded in `primary` sources
38
+ that agree.
39
+ - `medium` — mostly confirmed but thinner sourcing, some `secondary`-only support,
40
+ or minor unresolved tension.
41
+ - `low` — sparse/gated sources, unresolved contradictions, or several central claims
42
+ refuted.
43
+ - **Refuted-claim transparency is mandatory.** Do not silently drop refuted central
44
+ claims — name them in the `summary` (e.g. "A common claim that X was tested and did
45
+ not hold: …") so the reader sees what was checked and rejected.
46
+ - **Merge duplicates**: collapse claims that say the same thing; keep the strongest
47
+ quote/source.
48
+ - `unsourced` is `true` iff any assertion in your `summary` lacks a supporting quote in
49
+ `quotes[]`. Aim for `false` — every summary sentence should trace to a quote.
50
+
51
+ ## 4. Tools & sources
52
+
53
+ - `Read` to inspect the inputs and the schema at
54
+ `{{schemaDir}}/finding.schema.json` if you need it.
55
+ - `Write` to create the finding file.
56
+ - `Bash` to round-trip: `{{cli}} show {{sessionId}} --json` —
57
+ exit 0 means every finding on disk (including yours) validates.
58
+
59
+ ## 5. Boundaries
60
+
61
+ - One finding file, for `{{subQuestionId}}` only. Do not write `sources.json`,
62
+ `manifest.json`, the session answer, or any sibling's finding — the workflow's
63
+ finalise stage owns those.
64
+ - Do not invent quotes or source ids: every `quotes[].sourceId` and every id in
65
+ `sources[]` must come from the claims you were handed.
66
+ - Do not mark the session done — the finalise stage does that after all findings land.
67
+
68
+ ## 6. Output format
69
+
70
+ ### The file you write — `findings/{{findingFilename}}` (finding schema)
71
+
72
+ ```json
73
+ {
74
+ "subQuestionId": "{{subQuestionId}}",
75
+ "summary": "1–4 sentences answering the sub-question, incl. a refuted-claim note if any.",
76
+ "quotes": [
77
+ { "text": "verbatim quote", "sourceId": "s1-1", "importance": "central" }
78
+ ],
79
+ "sources": ["s1-1", "s1-2"],
80
+ "confidence": "high",
81
+ "verificationVotes": [
82
+ { "outcome": "confirmed", "lens": "contradiction-search", "note": "re: claim c-1 — no contradicting source found" }
83
+ ],
84
+ "unsourced": false
85
+ }
86
+ ```
87
+
88
+ - `quotes[].importance` ∈ `central | supporting | incidental` (optional per field but
89
+ include it). `confidence` ∈ `low | medium | high`.
90
+ - `verificationVotes[].outcome` ∈ `confirmed | refuted | unverified-infra`; `lens` and
91
+ `note` are optional but use `note` to name which central claim each vote concerns
92
+ (the schema has no per-claim vote linkage, so the note carries it).
93
+ - **No extra top-level fields** — the validator rejects unknown keys.
94
+
95
+ ### Your structured return to the workflow (the receipt)
96
+
97
+ ```json
98
+ {
99
+ "subQuestionId": "{{subQuestionId}}",
100
+ "written": true,
101
+ "path": "findings/{{findingFilename}}",
102
+ "confidence": "high",
103
+ "claimCount": 5,
104
+ "centralConfirmed": 3,
105
+ "centralRefuted": 1,
106
+ "unsourcedCount": 0,
107
+ "refutedTransparency": "one line naming any refuted central claims, or 'none'"
108
+ }
109
+ ```
110
+
111
+ ## 7. Done when
112
+
113
+ - `findings/{{findingFilename}}` exists, its `subQuestionId` equals `{{subQuestionId}}`
114
+ and the filename stem, and `research show {{sessionId}} --json` exits 0 (your file
115
+ and every sibling's validate). Your receipt reports the real counts.
116
+
117
+ ## 8. Escalation
118
+
119
+ - **The store rejects your file** (`show --json` exits 2 with a named error) → read the
120
+ error, fix the offending field, rewrite, re-run `show`. Never return `written: true`
121
+ while the round-trip is red.
122
+ - **Schema and a coherent answer genuinely cannot agree** → return `written: false`
123
+ with `refutedTransparency` explaining the conflict; the workflow escalates rather
124
+ than shipping a broken finding.
@@ -0,0 +1,86 @@
1
+ # Brief — verifier (deep-research, mode `normal`)
2
+
3
+ You are a **verifier** in the `research-normal.js` pipeline. You cast **one adversarial
4
+ vote** on **one claim**. Three independent verifiers vote on each central claim; the
5
+ workflow tallies. Your job is to *try to break the claim*, not to confirm it.
6
+
7
+ The dispatching workflow supplies concrete values for every `{{placeholder}}` below.
8
+
9
+ ## 1. Goal
10
+
11
+ Decide whether this claim survives an honest attempt to refute it:
12
+
13
+ - Claim: **"{{claimText}}"**
14
+ - Supporting quote (from the extractor): *"{{quote}}"*
15
+ - Cited source: {{sourceUrl}}
16
+ - In service of sub-question: *"{{subQuestionText}}"*
17
+ - Your assigned lens (if any): **{{lens}}**
18
+
19
+ Return one of three outcomes: `confirmed`, `refuted`, `unverified-infra`.
20
+
21
+ ## 2. Trace
22
+
23
+ - Parent run: session `{{sessionId}}`. You are one of a 3-vote panel on this claim.
24
+ - Downstream rule the workflow applies to the panel: **≥ 2 `refuted` → the claim is
25
+ dropped** from the finding and reported as refuted. `unverified-infra` votes do
26
+ **not** count toward refutation — they record that verification could not run, not
27
+ that the claim is false.
28
+
29
+ ## 3. Context — the adversarial posture
30
+
31
+ - **Default to `refuted` when uncertain.** The burden is on the claim to survive, not
32
+ on you to disprove it beyond doubt. A claim you cannot corroborate from an
33
+ independent angle is not "probably fine" — it is `refuted`.
34
+ - Vote `confirmed` only when an **independent** check agrees: the quote genuinely
35
+ supports the claim AND (where checkable) a second source, the primary source itself,
36
+ or first-principles reasoning agrees. Do not confirm on the strength of the single
37
+ cited source alone if the claim is checkable elsewhere.
38
+ - Vote `refuted` when: the quote does not actually support the claim (quote–claim
39
+ mismatch is a top failure mode — read it literally); an independent source
40
+ contradicts it; the claim is stale (superseded version/date); or it overreaches
41
+ beyond what any source supports.
42
+ - Lens focus (if `{{lens}}` is set): `quote-support` = does the quote prove the claim;
43
+ `contradiction-search` = actively search for a source that disagrees;
44
+ `recency-source-fit` = is it current and is the source the right kind of authority.
45
+ With no lens, apply all three.
46
+
47
+ ## 4. Tools & sources
48
+
49
+ - `WebSearch` + `WebFetch` to seek contradiction and corroboration. Keep it lean —
50
+ a few targeted calls, not a re-research. You are testing one claim, not rebuilding
51
+ the sub-question.
52
+
53
+ ## 5. Boundaries
54
+
55
+ - One claim, one vote. Do not re-extract, do not evaluate sibling claims, do not write
56
+ files.
57
+ - Do not soften a genuine refutation into `unverified-infra` to be polite —
58
+ `unverified-infra` is **only** for infrastructure failure (rate limits, everything
59
+ you fetched timed out / errored), never for "I found it doubtful."
60
+ - Conversely, do not report a real infra failure as `refuted` — that would falsely
61
+ sink a possibly-true claim.
62
+
63
+ ## 6. Output format — structured return (enforced by the workflow's schema)
64
+
65
+ ```json
66
+ {
67
+ "outcome": "confirmed",
68
+ "note": "one line: what you checked and why it lands here (cite the contradicting/corroborating source if any)"
69
+ }
70
+ ```
71
+
72
+ - `outcome` ∈ `confirmed | refuted | unverified-infra` (exact spelling; these are the
73
+ finding schema's vote outcomes).
74
+ - `note` is mandatory and must name the evidence — a bare outcome is not auditable.
75
+
76
+ ## 7. Done when
77
+
78
+ - You have one `outcome` backed by a one-line, evidence-citing `note`, reached under
79
+ the adversarial default (uncertain ⇒ refuted).
80
+
81
+ ## 8. Escalation
82
+
83
+ - **All your fetches failed (rate limit / network)** → `unverified-infra` with a note
84
+ naming the failure. Do not guess an outcome from the claim's plausibility.
85
+ - You never block or hand back — a vote is always due; when truly unable to check and
86
+ it is not an infra failure, the adversarial default (`refuted`) applies.
@@ -0,0 +1,141 @@
1
+ // research — deep-research session store CLI.
2
+ //
3
+ // The ONLY module that owns exit codes. Commands return a number or throw an
4
+ // Error carrying `.exitCode`; this wrapper translates:
5
+ // 0 — ok
6
+ // 1 — usage error (bad args, unknown verb, bad enum, missing sessionId)
7
+ // 2 — operational (session not found, malformed session dir, explicit prune matched nothing)
8
+ // 3 — transport/IO (disk read/write failure)
9
+ //
10
+ // Shape: `main(argv)` returns the exit code as a number (async). The bin shim
11
+ // converts to `process.exit`; `pa research <verb>` in `pa/cli.mjs` awaits the
12
+ // number so `pa` can surface the same code. Same pattern as `pa/knowledge/cli.mjs`.
13
+
14
+ import { realpathSync } from 'node:fs';
15
+ import { resolve } from 'node:path';
16
+ import { fileURLToPath } from 'node:url';
17
+
18
+ const HELP = `research — deep-research session store
19
+
20
+ Creates, validates, inspects and prunes research sessions under
21
+ <repoRoot>/.cache/research/sessions/<sessionId>/. Owns the schemas every
22
+ research workflow reads. Zero runtime dependencies.
23
+
24
+ Usage:
25
+ research run --mode <light|normal|deep> --question "..." [--gate <policy>]
26
+ [--intent "..."] [--output <mode>] [--dry-run]
27
+ Create a session (dir + manifest + skeleton plan), validate inputs, print
28
+ the plan, and return. Does NOT orchestrate research. --dry-run validates and
29
+ prints without persisting. Gate policy: operatorPresent | background | worker.
30
+ Output mode: shortAnswer | article | structured (default shortAnswer).
31
+
32
+ research list [--status <status>] [--all] [--json]
33
+ List sessions, newest first. Default: 20 most recent. --all lists every one.
34
+
35
+ research show <sessionId> [--json]
36
+ Dump one session: manifest, findings summary, gate summary.
37
+
38
+ research gates --list [<sessionId>] | --retry <sessionId> | --append <sessionId>
39
+ --list aggregates the gate queue across all sessions (or one if given).
40
+ --retry marks eligible (pending/retrying) gates as retrying and prints them.
41
+ --append reads gate records (JSON array on stdin, or --record '<json>' for a
42
+ single one) and appends them to the session's gates.json with fresh g-N ids.
43
+
44
+ research prune [--older-than <days>] [--status <status>] [--dry-run]
45
+ Delete sessions older than N days and/or matching a status. At least one
46
+ filter is required. --dry-run prints what would be deleted without deleting.
47
+
48
+ research mark <done|aborted> <sessionId> [--no-promote | --promote]
49
+ Set a terminal status on a session: done (finalised) or aborted (abandoned).
50
+ Bumps updatedAt. Both transitions are one-way — a session already done or
51
+ aborted is refused (exit 2). The one verb that mutates a session's status.
52
+ On mark done, a normal/deep session's answer.md is promoted into the
53
+ operator knowledge library (operator/knowledge/research/); light is never
54
+ promoted (--promote on light is a usage error). --no-promote skips promotion
55
+ on normal/deep with a note. Aborted sessions are never promoted.
56
+
57
+ research paths [--json]
58
+ Emit the resolved absolute paths the /research skill and workflow scripts
59
+ consume: sessionsDir, briefsDir, workflowsDir, cli. Text default; --json
60
+ for machine input. Uses the same repo-root resolver as pa knowledge / pa
61
+ work: \$DAVE_REPO_ROOT / \$PA_REPO_ROOT, else walk upward for a .git entry.
62
+
63
+ research --help | -h This message.
64
+
65
+ Exit codes: 0 ok, 1 usage error, 2 operational failure, 3 transport/IO failure.
66
+ `;
67
+
68
+ export async function main(argv) {
69
+ if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
70
+ process.stdout.write(HELP);
71
+ return 0;
72
+ }
73
+
74
+ const verb = argv[0];
75
+ const rest = argv.slice(1);
76
+
77
+ try {
78
+ switch (verb) {
79
+ case 'run': {
80
+ const { runCommand } = await import('./commands/run.mjs');
81
+ return (await runCommand(rest)) ?? 0;
82
+ }
83
+ case 'list': {
84
+ const { listCommand } = await import('./commands/list.mjs');
85
+ return (await listCommand(rest)) ?? 0;
86
+ }
87
+ case 'show': {
88
+ const { showCommand } = await import('./commands/show.mjs');
89
+ return (await showCommand(rest)) ?? 0;
90
+ }
91
+ case 'gates': {
92
+ const { gatesCommand } = await import('./commands/gates.mjs');
93
+ return (await gatesCommand(rest)) ?? 0;
94
+ }
95
+ case 'prune': {
96
+ const { pruneCommand } = await import('./commands/prune.mjs');
97
+ return (await pruneCommand(rest)) ?? 0;
98
+ }
99
+ case 'mark': {
100
+ const { markCommand } = await import('./commands/mark.mjs');
101
+ return (await markCommand(rest)) ?? 0;
102
+ }
103
+ case 'paths': {
104
+ const { pathsCommand } = await import('./commands/paths.mjs');
105
+ return (await pathsCommand(rest)) ?? 0;
106
+ }
107
+ default:
108
+ process.stderr.write(`unknown command: ${verb}\n\n`);
109
+ process.stderr.write(HELP);
110
+ return 1;
111
+ }
112
+ } catch (err) {
113
+ // parseArgs strict-mode errors and our own usage errors both surface here.
114
+ const exitCode = err && err.exitCode != null ? err.exitCode : 1;
115
+ process.stderr.write(`${err && err.message ? err.message : err}\n`);
116
+ return exitCode;
117
+ }
118
+ }
119
+
120
+ // Allow `node src/research/cli.mjs ...` in addition to the bin shim.
121
+ //
122
+ // ISMAIN-AUDIT (bug-3 sweep): the previous strict `file://${argv[1]}`
123
+ // equality has the same fragility as the endsWith idiom fixed elsewhere —
124
+ // no realpath resolution on argv[1], so a symlinked invocation path (e.g.
125
+ // via a pnpm .bin shim) would silently fail to match import.meta.url
126
+ // (which Node always resolves to the real path). Not proven to fire in
127
+ // production today (the shipped `bin/research` imports and calls main()
128
+ // directly, bypassing this branch entirely) but fixed defensively to match
129
+ // the robust realpath-on-both-sides pattern used across the repo.
130
+ function isDirectlyInvoked() {
131
+ if (!process.argv[1]) return false;
132
+ try {
133
+ return fileURLToPath(import.meta.url) === realpathSync(resolve(process.argv[1]));
134
+ } catch {
135
+ return false;
136
+ }
137
+ }
138
+
139
+ if (isDirectlyInvoked()) {
140
+ main(process.argv.slice(2)).then((code) => process.exit(code));
141
+ }
@@ -0,0 +1,176 @@
1
+ // research gates --list [<sessionId>] | --retry <sessionId> | --append <sessionId>
2
+ //
3
+ // --list aggregates the gate queue across all sessions (or one, if given).
4
+ // --retry marks eligible (pending/retrying) gates as `retrying` and prints them.
5
+ // Actual re-execution is workflow-side (w-018+); this only marks + prints.
6
+ // --append reads gate records (JSON array on stdin, or --record '<json>' for a single
7
+ // one) and appends them to the session's gates.json with fresh g-N ids. The
8
+ // caller supplies the semantic fields ({url,gateType,whatIsNeeded,subQuestionId?});
9
+ // the verb assigns the id, sets blockedAt from the clock, defaults status:pending.
10
+ // The write goes through the store chokepoint (store.writeGates → validateGates).
11
+ import { parseArgs } from 'node:util';
12
+ import { getDefaultStore } from '../store/index.mjs';
13
+ import { markEligibleForRetry, GATE_STATUSES } from '../store/gates.mjs';
14
+ import { isObject } from '../store/validate.mjs';
15
+ import { table, truncate } from '../format.mjs';
16
+
17
+ function usage(msg) {
18
+ return Object.assign(new Error(`usage: research gates --list [<sessionId>] | --retry <sessionId> | --append <sessionId> [--record '<json>'] [--json]${msg ? `\n${msg}` : ''}`), { exitCode: 1 });
19
+ }
20
+ function notFound(msg) {
21
+ return Object.assign(new Error(msg), { exitCode: 2 });
22
+ }
23
+
24
+ // Read all of a readable stream to a utf8 string. Injected in tests.
25
+ async function readAllStdin(stream = process.stdin) {
26
+ const chunks = [];
27
+ for await (const chunk of stream) chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
28
+ return Buffer.concat(chunks).toString('utf8');
29
+ }
30
+
31
+ // Collect every gate across sessions (or one session) into flat rows carrying
32
+ // their sessionId. Pure over the store's reads.
33
+ async function collectGates(store, onlyId) {
34
+ const ids = onlyId
35
+ ? [onlyId]
36
+ : (await store.listSessions()).filter((s) => s.manifest).map((s) => s.id);
37
+ const rows = [];
38
+ for (const id of ids) {
39
+ const gates = await store.readGates(id);
40
+ for (const g of gates.queue) rows.push({ sessionId: id, ...g });
41
+ }
42
+ return rows;
43
+ }
44
+
45
+ // Parse a caller-supplied record/records blob. Bad JSON is USER input → exit 1
46
+ // (not the store validator's exit 2). Returns a normalised array.
47
+ function parseRecords(text, where) {
48
+ let raw;
49
+ try {
50
+ raw = JSON.parse(text);
51
+ } catch (e) {
52
+ throw usage(`invalid JSON on ${where}: ${e.message}`);
53
+ }
54
+ return Array.isArray(raw) ? raw : [raw];
55
+ }
56
+
57
+ // Turn one caller record into a full gate item. Validates input fields (exit 1 on a
58
+ // bad one) and stamps the verb-owned fields (id, blockedAt, default status).
59
+ function buildGateItem(r, id, nowIso, i) {
60
+ const at = `record[${i}]`;
61
+ if (!isObject(r)) throw usage(`${at} must be a JSON object`);
62
+ const KNOWN = new Set(['url', 'gateType', 'whatIsNeeded', 'subQuestionId', 'status']);
63
+ for (const k of Object.keys(r)) {
64
+ if (!KNOWN.has(k)) throw usage(`${at} has unexpected field "${k}" (allowed: url, gateType, whatIsNeeded, subQuestionId, status)`);
65
+ }
66
+ const reqStr = (k) => {
67
+ if (typeof r[k] !== 'string' || r[k].length === 0) throw usage(`${at}.${k} must be a non-empty string`);
68
+ return r[k];
69
+ };
70
+ const item = {
71
+ id,
72
+ url: reqStr('url'),
73
+ gateType: reqStr('gateType'),
74
+ whatIsNeeded: reqStr('whatIsNeeded'),
75
+ status: 'pending',
76
+ blockedAt: nowIso,
77
+ };
78
+ if (r.subQuestionId != null) {
79
+ if (typeof r.subQuestionId !== 'string' || r.subQuestionId.length === 0) throw usage(`${at}.subQuestionId must be a non-empty string if present`);
80
+ item.subQuestionId = r.subQuestionId;
81
+ }
82
+ if (r.status != null) {
83
+ if (!GATE_STATUSES.includes(r.status)) throw usage(`${at}.status must be one of ${GATE_STATUSES.join(' | ')} (got ${JSON.stringify(r.status)})`);
84
+ item.status = r.status;
85
+ }
86
+ return item;
87
+ }
88
+
89
+ export async function gatesCommand(argv, { store, stdout = process.stdout, now = Date.now, readStdin = readAllStdin } = {}) {
90
+ if (!store) store = await getDefaultStore();
91
+ let parsed;
92
+ try {
93
+ parsed = parseArgs({
94
+ args: argv,
95
+ options: {
96
+ list: { type: 'boolean' },
97
+ retry: { type: 'string' },
98
+ append: { type: 'boolean' },
99
+ record: { type: 'string' },
100
+ json: { type: 'boolean' },
101
+ },
102
+ allowPositionals: true,
103
+ strict: true,
104
+ });
105
+ } catch (e) {
106
+ throw usage(e.message);
107
+ }
108
+ const v = parsed.values;
109
+ const modes = [v.list && 'list', v.retry != null && 'retry', v.append && 'append'].filter(Boolean);
110
+ if (modes.length !== 1) throw usage('exactly one of --list, --retry <sessionId>, or --append <sessionId> is required');
111
+ if (v.record != null && !v.append) throw usage('--record is only valid with --append');
112
+
113
+ if (v.list) {
114
+ const onlyId = parsed.positionals[0];
115
+ if (parsed.positionals.length > 1) throw usage('--list takes at most one <sessionId>');
116
+ if (onlyId != null) {
117
+ if (!store.isValidSessionId(onlyId)) throw usage(`"${onlyId}" is not a valid sessionId`);
118
+ if (!store.exists(onlyId)) throw notFound(`session ${onlyId} not found`);
119
+ }
120
+ const rows = await collectGates(store, onlyId);
121
+ if (v.json) { stdout.write(JSON.stringify(rows, null, 2) + '\n'); return 0; }
122
+ if (rows.length === 0) { stdout.write('no gates\n'); return 0; }
123
+ stdout.write(table(
124
+ ['SESSION', 'GATE', 'STATUS', 'TYPE', 'URL', 'NEEDED'],
125
+ rows.map((r) => [r.sessionId, r.id, r.status, r.gateType, truncate(r.url, 40), truncate(r.whatIsNeeded, 40)]),
126
+ ));
127
+ return 0;
128
+ }
129
+
130
+ if (v.append) {
131
+ const id = parsed.positionals[0];
132
+ if (!id) throw usage('--append requires a <sessionId>');
133
+ if (parsed.positionals.length > 1) throw usage('--append takes exactly one <sessionId>');
134
+ if (!store.isValidSessionId(id)) throw usage(`"${id}" is not a valid sessionId`);
135
+ if (!store.exists(id)) throw notFound(`session ${id} not found`);
136
+
137
+ const text = v.record != null ? v.record : await readStdin();
138
+ const records = parseRecords(text, v.record != null ? '--record' : 'stdin');
139
+ if (records.length === 0) throw notFound('no gate records supplied');
140
+
141
+ const existing = await store.readGates(id);
142
+ let maxN = 0;
143
+ for (const it of existing.queue) {
144
+ const m = /^g-(\d+)$/.exec(it.id);
145
+ if (m) maxN = Math.max(maxN, Number(m[1]));
146
+ }
147
+ const nowIso = new Date(now()).toISOString();
148
+ const newItems = records.map((r, i) => buildGateItem(r, `g-${maxN + i + 1}`, nowIso, i));
149
+ const next = { ...existing, queue: [...existing.queue, ...newItems] };
150
+ await store.writeGates(id, next); // chokepoint: validates the whole file before persist
151
+
152
+ if (v.json) { stdout.write(JSON.stringify(newItems, null, 2) + '\n'); return 0; }
153
+ stdout.write(`appended ${newItems.length} gate(s) to ${id}: ${newItems.map((it) => it.id).join(', ')}\n`);
154
+ return 0;
155
+ }
156
+
157
+ // --retry <sessionId>
158
+ const id = v.retry;
159
+ if (!store.isValidSessionId(id)) throw usage(`"${id}" is not a valid sessionId`);
160
+ if (!store.exists(id)) throw notFound(`session ${id} not found`);
161
+
162
+ const gates = await store.readGates(id);
163
+ const { gates: next, marked } = markEligibleForRetry(gates);
164
+ if (marked.length === 0) {
165
+ stdout.write('no eligible gates to retry\n');
166
+ return 0;
167
+ }
168
+ await store.writeGates(id, next);
169
+ if (v.json) { stdout.write(JSON.stringify(marked, null, 2) + '\n'); return 0; }
170
+ stdout.write(`marked ${marked.length} gate(s) as retrying in ${id}:\n`);
171
+ stdout.write(table(
172
+ ['GATE', 'TYPE', 'URL', 'NEEDED'],
173
+ marked.map((r) => [r.id, r.gateType, truncate(r.url, 40), truncate(r.whatIsNeeded, 40)]),
174
+ ));
175
+ return 0;
176
+ }
@@ -0,0 +1,56 @@
1
+ // research list — list sessions, newest first (sessionId sorts by creation time).
2
+ // Default: 20 most recent. --all: every session. --status: filter. --json: machine output.
3
+ import { parseArgs } from 'node:util';
4
+ import { getDefaultStore } from '../store/index.mjs';
5
+ import { STATUSES } from '../store/manifest.mjs';
6
+ import { table, truncate } from '../format.mjs';
7
+
8
+ const DEFAULT_LIMIT = 20;
9
+
10
+ function usage(msg) {
11
+ return Object.assign(new Error(`usage: research list [--status <${STATUSES.join('|')}>] [--all] [--json]${msg ? `\n${msg}` : ''}`), { exitCode: 1 });
12
+ }
13
+
14
+ export async function listCommand(argv, { store, stdout = process.stdout } = {}) {
15
+ if (!store) store = await getDefaultStore();
16
+ let parsed;
17
+ try {
18
+ parsed = parseArgs({
19
+ args: argv,
20
+ options: {
21
+ status: { type: 'string' },
22
+ all: { type: 'boolean' },
23
+ json: { type: 'boolean' },
24
+ },
25
+ allowPositionals: false,
26
+ strict: true,
27
+ });
28
+ } catch (e) {
29
+ throw usage(e.message);
30
+ }
31
+ const v = parsed.values;
32
+ if (v.status != null && !STATUSES.includes(v.status)) throw usage(`--status must be one of ${STATUSES.join(' | ')}`);
33
+
34
+ let sessions = await store.listSessions();
35
+ if (v.status != null) sessions = sessions.filter((s) => s.manifest && s.manifest.status === v.status);
36
+ const limited = v.all ? sessions : sessions.slice(0, DEFAULT_LIMIT);
37
+
38
+ if (v.json) {
39
+ stdout.write(JSON.stringify(limited.map((s) => (s.manifest ? s.manifest : { sessionId: s.id, error: s.error })), null, 2) + '\n');
40
+ return 0;
41
+ }
42
+
43
+ if (limited.length === 0) {
44
+ stdout.write('no sessions\n');
45
+ return 0;
46
+ }
47
+
48
+ const rows = limited.map((s) => s.manifest
49
+ ? [s.id, s.manifest.mode, s.manifest.status, s.manifest.createdAt, truncate(s.manifest.question, 50)]
50
+ : [s.id, '?', 'MALFORMED', '?', truncate(s.error, 50)]);
51
+ stdout.write(table(['SESSION', 'MODE', 'STATUS', 'CREATED', 'QUESTION'], rows));
52
+ if (!v.all && sessions.length > limited.length) {
53
+ stdout.write(`\n… ${sessions.length - limited.length} more (use --all)\n`);
54
+ }
55
+ return 0;
56
+ }