meerkat-taskpanel 0.0.0-stage → 0.1.1

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 (320) hide show
  1. package/.claude-plugin/marketplace.json +15 -0
  2. package/.claude-plugin/plugin.json +11 -0
  3. package/.pi/extensions/meerkat-taskpanel.ts +35 -0
  4. package/CHANGELOG.md +133 -0
  5. package/LICENSE +21 -0
  6. package/README.md +303 -2
  7. package/README.zh-CN.md +303 -0
  8. package/docs/README.md +77 -0
  9. package/docs/contract.md +312 -0
  10. package/docs/development.md +435 -0
  11. package/docs/docker.md +559 -0
  12. package/docs/events.md +269 -0
  13. package/docs/im-integration.md +332 -0
  14. package/docs/install.md +889 -0
  15. package/docs/migration.md +59 -0
  16. package/docs/observability.md +321 -0
  17. package/docs/projects.md +63 -0
  18. package/docs/publishing.md +387 -0
  19. package/docs/scheduling.md +1860 -0
  20. package/docs/security.md +138 -0
  21. package/docs/sla.md +344 -0
  22. package/docs/web-local-first.md +76 -0
  23. package/install.sh +729 -0
  24. package/package.json +67 -4
  25. package/scripts/build.mjs +41 -0
  26. package/scripts/install/_common.sh +769 -0
  27. package/scripts/install/claude.sh +39 -0
  28. package/scripts/install/cli.mjs +161 -0
  29. package/scripts/install/codex.sh +36 -0
  30. package/scripts/install/lib/apply.mjs +419 -0
  31. package/scripts/install/lib/server-install.mjs +262 -0
  32. package/scripts/install/lib/supervisor.mjs +925 -0
  33. package/scripts/install/lib/taskd-guard.mjs +926 -0
  34. package/scripts/install/lib/unit-path.mjs +151 -0
  35. package/scripts/install/openclaw.sh +35 -0
  36. package/scripts/install/pi.sh +49 -0
  37. package/scripts/install/server.sh +41 -0
  38. package/scripts/install/templates/agent/meerkat-taskpanel.env +53 -0
  39. package/scripts/install/templates/claude/commands/board.md +15 -0
  40. package/scripts/install/templates/claude/commands/claim.md +12 -0
  41. package/scripts/install/templates/claude/commands/deliver.md +12 -0
  42. package/scripts/install/templates/claude/session-start.sh +40 -0
  43. package/scripts/install/templates/codex/AGENTS.md.snippet +11 -0
  44. package/scripts/install/templates/env.example +67 -0
  45. package/scripts/install/templates/scheduling/cron/meerkat-taskpanel.cron +19 -0
  46. package/scripts/install/templates/scheduling/launchd/com.meerkat-taskpanel.continue.plist +44 -0
  47. package/scripts/install/templates/scheduling/launchd/com.meerkat-taskpanel.ping.plist +44 -0
  48. package/scripts/install/templates/scheduling/launchd/com.meerkat-taskpanel.session.plist +48 -0
  49. package/scripts/install/templates/scheduling/launchd/com.meerkat-taskpanel.subscribe.plist +41 -0
  50. package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-continue.service +14 -0
  51. package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-continue.timer +12 -0
  52. package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-ping.service +18 -0
  53. package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-ping.timer +12 -0
  54. package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-session.service +36 -0
  55. package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-subscribe.service +22 -0
  56. package/scripts/install/templates/server/taskctl +12 -0
  57. package/scripts/install/templates/server/taskd +12 -0
  58. package/scripts/install/templates/taskctl-shim.sh +32 -0
  59. package/scripts/install/templates/taskd/launchd/com.meerkat-taskpanel.taskd.plist +49 -0
  60. package/scripts/install/templates/taskd/systemd/meerkat-taskpanel-taskd.service +41 -0
  61. package/scripts/release/bump.mjs +738 -0
  62. package/scripts/release/pack-manifest.mjs +254 -0
  63. package/scripts/security/scan-gate.mjs +1037 -0
  64. package/scripts/security/scan-gate.test.mjs +850 -0
  65. package/scripts/security/waivers.json +16 -0
  66. package/scripts/security/workflow.test.mjs +204 -0
  67. package/scripts/verify/changelog.mjs +170 -0
  68. package/scripts/verify/cli-contract.mjs +297 -0
  69. package/scripts/verify/contract.mjs +904 -0
  70. package/scripts/verify/docker.mjs +235 -0
  71. package/scripts/verify/install-e2e.sh +136 -0
  72. package/scripts/verify/kind-cli.mjs +226 -0
  73. package/scripts/verify/kind-resume-matrix.mjs +463 -0
  74. package/scripts/verify/kind-runtime.mjs +343 -0
  75. package/scripts/verify/kind-session-matrix.mjs +245 -0
  76. package/scripts/verify/lib/base-image.mjs +164 -0
  77. package/scripts/verify/lib/bundle.mjs +399 -0
  78. package/scripts/verify/lib/docker-plan.mjs +165 -0
  79. package/scripts/verify/lib/frontmatter.mjs +39 -0
  80. package/scripts/verify/lib/mini-yaml.mjs +69 -0
  81. package/scripts/verify/lib/profiles.mjs +401 -0
  82. package/scripts/verify/manifests.mjs +132 -0
  83. package/scripts/verify/migrations.mjs +278 -0
  84. package/scripts/verify/paths.mjs +250 -0
  85. package/scripts/verify/profiles.mjs +70 -0
  86. package/scripts/verify/route-request.mjs +909 -0
  87. package/scripts/verify/server-install.mjs +202 -0
  88. package/scripts/verify/signposts.mjs +344 -0
  89. package/scripts/verify/skill.mjs +133 -0
  90. package/scripts/verify/version.mjs +260 -0
  91. package/scripts/verify/web-dist.mjs +382 -0
  92. package/skills/meerkat-loop/SKILL.md +250 -0
  93. package/skills/meerkat-loop/references/decision-policy.md +146 -0
  94. package/skills/meerkat-loop/references/operation.md +257 -0
  95. package/skills/meerkat-taskpanel/SKILL.md +274 -0
  96. package/skills/meerkat-taskpanel/references/capabilities.md +191 -0
  97. package/skills/meerkat-taskpanel/references/card-schema.md +288 -0
  98. package/skills/meerkat-taskpanel/references/cli.md +751 -0
  99. package/skills/meerkat-taskpanel/references/projects-json.md +102 -0
  100. package/skills/meerkat-taskpanel/references/review-workflow.md +235 -0
  101. package/skills/meerkat-taskpanel/references/status-lifecycle.md +428 -0
  102. package/skills/meerkat-taskpanel/scripts/run.mjs +211 -0
  103. package/skills/meerkat-taskpanel/scripts/session-id.mjs +160 -0
  104. package/skills/setup-meerkat/SKILL.md +328 -0
  105. package/skills/setup-meerkat/assets/team/standard/agents/claude/role.md.tmpl +17 -0
  106. package/skills/setup-meerkat/assets/team/standard/agents/codex/role.toml.tmpl +15 -0
  107. package/skills/setup-meerkat/assets/team/standard/agents/pi/role.md.tmpl +16 -0
  108. package/skills/setup-meerkat/assets/team/standard/decision-policy.md +69 -0
  109. package/skills/setup-meerkat/assets/team/standard/jobs/self-check.md +109 -0
  110. package/skills/setup-meerkat/assets/team/standard/jobs/ui-workflow.md +111 -0
  111. package/skills/setup-meerkat/assets/team/standard/jobs/workflow.md +226 -0
  112. package/skills/setup-meerkat/assets/team/standard/linus/architecture-workflow.md +543 -0
  113. package/skills/setup-meerkat/assets/team/standard/linus/implementation-workflow.md +106 -0
  114. package/skills/setup-meerkat/assets/team/standard/linus/self-check.md +110 -0
  115. package/skills/setup-meerkat/assets/team/standard/linus/workflow.md +121 -0
  116. package/skills/setup-meerkat/assets/team/standard/manifest.json +126 -0
  117. package/skills/setup-meerkat/assets/team/standard/reviewer/reviewer-prompt.md +42 -0
  118. package/skills/setup-meerkat/assets/team/standard/reviewer/workflow.md +127 -0
  119. package/skills/setup-meerkat/assets/team/standard/turing/performance-workflow.md +49 -0
  120. package/skills/setup-meerkat/assets/team/standard/turing/regression-workflow.md +67 -0
  121. package/skills/setup-meerkat/assets/team/standard/turing/self-check.md +73 -0
  122. package/skills/setup-meerkat/assets/team/standard/turing/test-design-workflow.md +87 -0
  123. package/skills/setup-meerkat/assets/team/standard/turing/workflow.md +96 -0
  124. package/skills/setup-meerkat/evals/evals.json +127 -0
  125. package/skills/setup-meerkat/references/detection.md +94 -0
  126. package/skills/setup-meerkat/references/evals.md +96 -0
  127. package/skills/setup-meerkat/references/install.md +82 -0
  128. package/skills/setup-meerkat/references/matt-pocock.md +47 -0
  129. package/skills/setup-meerkat/references/roles.md +267 -0
  130. package/skills/setup-meerkat/scripts/configure-env.mjs +147 -0
  131. package/skills/setup-meerkat/scripts/detect.mjs +574 -0
  132. package/skills/setup-meerkat/scripts/install-roles.mjs +399 -0
  133. package/skills/setup-meerkat/scripts/lib/agent-kinds.mjs +126 -0
  134. package/skills/setup-meerkat/scripts/lib/atomic.mjs +20 -0
  135. package/skills/setup-meerkat/scripts/lib/entry-guard.mjs +22 -0
  136. package/skills/setup-meerkat/scripts/lib/env-merge.mjs +95 -0
  137. package/skills/setup-meerkat/scripts/lib/validate.mjs +293 -0
  138. package/src/cli/activity-stream.mjs +71 -0
  139. package/src/cli/argv.mjs +347 -0
  140. package/src/cli/commands/attachment.mjs +171 -0
  141. package/src/cli/commands/comment.mjs +77 -0
  142. package/src/cli/commands/dict.mjs +42 -0
  143. package/src/cli/commands/events.mjs +270 -0
  144. package/src/cli/commands/export.mjs +822 -0
  145. package/src/cli/commands/index.mjs +98 -0
  146. package/src/cli/commands/issue.mjs +670 -0
  147. package/src/cli/commands/labels.mjs +42 -0
  148. package/src/cli/commands/loop.mjs +119 -0
  149. package/src/cli/commands/project.mjs +339 -0
  150. package/src/cli/commands/relation.mjs +65 -0
  151. package/src/cli/commands/report.mjs +328 -0
  152. package/src/cli/commands/session.mjs +196 -0
  153. package/src/cli/commands/sla.mjs +95 -0
  154. package/src/cli/commands/status.mjs +125 -0
  155. package/src/cli/commands/task-input.mjs +251 -0
  156. package/src/cli/commands/token.mjs +43 -0
  157. package/src/cli/hub/client.mjs +9 -0
  158. package/src/cli/hub/runtime.mjs +34 -0
  159. package/src/cli/hub/server.mjs +1046 -0
  160. package/src/cli/hub/stream.mjs +168 -0
  161. package/src/cli/index.mjs +317 -0
  162. package/src/cli/output/human.mjs +53 -0
  163. package/src/cli/output/index.mjs +61 -0
  164. package/src/cli/output/json.mjs +39 -0
  165. package/src/cli/usage.mjs +104 -0
  166. package/src/cli/watch-core.mjs +210 -0
  167. package/src/core/README.md +122 -0
  168. package/src/core/bootstrap.mjs +238 -0
  169. package/src/core/commands/acceptance.mjs +339 -0
  170. package/src/core/commands/agent-sessions.mjs +114 -0
  171. package/src/core/commands/attachments.mjs +239 -0
  172. package/src/core/commands/comments.mjs +106 -0
  173. package/src/core/commands/context.mjs +102 -0
  174. package/src/core/commands/delivery-report.mjs +28 -0
  175. package/src/core/commands/dictionary.mjs +202 -0
  176. package/src/core/commands/index.mjs +136 -0
  177. package/src/core/commands/labels.mjs +210 -0
  178. package/src/core/commands/logging.mjs +92 -0
  179. package/src/core/commands/projects.mjs +324 -0
  180. package/src/core/commands/relations.mjs +178 -0
  181. package/src/core/commands/reports.mjs +318 -0
  182. package/src/core/commands/rollup.mjs +802 -0
  183. package/src/core/commands/sla.mjs +132 -0
  184. package/src/core/commands/tasks-input.mjs +295 -0
  185. package/src/core/commands/tasks.mjs +1952 -0
  186. package/src/core/commands/workflow.mjs +133 -0
  187. package/src/core/domain/acceptance-mode.mjs +320 -0
  188. package/src/core/domain/acceptance.mjs +285 -0
  189. package/src/core/domain/awaiting.mjs +243 -0
  190. package/src/core/domain/blocked-reason.mjs +78 -0
  191. package/src/core/domain/claim.mjs +332 -0
  192. package/src/core/domain/comment.mjs +162 -0
  193. package/src/core/domain/delivery-gate.mjs +252 -0
  194. package/src/core/domain/dictionary.mjs +147 -0
  195. package/src/core/domain/enums.mjs +317 -0
  196. package/src/core/domain/idem.mjs +87 -0
  197. package/src/core/domain/index.mjs +27 -0
  198. package/src/core/domain/invariants.mjs +103 -0
  199. package/src/core/domain/labels.mjs +166 -0
  200. package/src/core/domain/priority.mjs +80 -0
  201. package/src/core/domain/relation.mjs +470 -0
  202. package/src/core/domain/report.mjs +541 -0
  203. package/src/core/domain/reviewer.mjs +32 -0
  204. package/src/core/domain/status.mjs +405 -0
  205. package/src/core/domain/task.mjs +600 -0
  206. package/src/core/domain/workflow.mjs +1347 -0
  207. package/src/core/index.mjs +58 -0
  208. package/src/core/storage/driver.mjs +178 -0
  209. package/src/core/storage/md/export.mjs +339 -0
  210. package/src/core/storage/md/frontmatter.mjs +298 -0
  211. package/src/core/storage/md/sections.mjs +621 -0
  212. package/src/core/storage/migrations/0001_init.sql +760 -0
  213. package/src/core/storage/migrations-runner.mjs +286 -0
  214. package/src/core/storage/paths.mjs +61 -0
  215. package/src/core/storage/repositories/activities.mjs +82 -0
  216. package/src/core/storage/repositories/agent-sessions.mjs +230 -0
  217. package/src/core/storage/repositories/attachments.mjs +139 -0
  218. package/src/core/storage/repositories/comments.mjs +98 -0
  219. package/src/core/storage/repositories/dictionary.mjs +224 -0
  220. package/src/core/storage/repositories/index.mjs +49 -0
  221. package/src/core/storage/repositories/labels.mjs +218 -0
  222. package/src/core/storage/repositories/projects.mjs +263 -0
  223. package/src/core/storage/repositories/relations.mjs +275 -0
  224. package/src/core/storage/repositories/reports.mjs +131 -0
  225. package/src/core/storage/repositories/tasks.mjs +864 -0
  226. package/src/core/storage/schema.mjs +71 -0
  227. package/src/core/storage/secrets/runtime-pointer.mjs +298 -0
  228. package/src/core/storage/secrets/token-store.mjs +156 -0
  229. package/src/core/storage/sqlite-errors.mjs +269 -0
  230. package/src/core/storage/unit-of-work.mjs +207 -0
  231. package/src/core/storage/writer-lock.mjs +205 -0
  232. package/src/foundation/README.md +54 -0
  233. package/src/foundation/attachments.mjs +149 -0
  234. package/src/foundation/board-compat.mjs +163 -0
  235. package/src/foundation/card-brief.mjs +71 -0
  236. package/src/foundation/card-write.mjs +124 -0
  237. package/src/foundation/constants.mjs +742 -0
  238. package/src/foundation/daemon-state.mjs +124 -0
  239. package/src/foundation/deliver-hint.mjs +30 -0
  240. package/src/foundation/entry-guard.mjs +69 -0
  241. package/src/foundation/env-config.mjs +349 -0
  242. package/src/foundation/env-file.mjs +127 -0
  243. package/src/foundation/errors.mjs +492 -0
  244. package/src/foundation/hub-client.mjs +506 -0
  245. package/src/foundation/ids.mjs +178 -0
  246. package/src/foundation/log.mjs +475 -0
  247. package/src/foundation/loop-paths.mjs +123 -0
  248. package/src/foundation/node-version.mjs +62 -0
  249. package/src/foundation/norm.mjs +49 -0
  250. package/src/foundation/project-dir.mjs +333 -0
  251. package/src/foundation/project-order.mjs +122 -0
  252. package/src/foundation/redact.mjs +102 -0
  253. package/src/foundation/report-warning.mjs +34 -0
  254. package/src/foundation/review-identity.mjs +126 -0
  255. package/src/foundation/role-prompt.mjs +182 -0
  256. package/src/foundation/roles.mjs +362 -0
  257. package/src/foundation/runtime-locator.mjs +176 -0
  258. package/src/foundation/scheduling.mjs +927 -0
  259. package/src/foundation/sla-config.mjs +426 -0
  260. package/src/foundation/sla-patrol.mjs +1562 -0
  261. package/src/foundation/sse-parse.mjs +89 -0
  262. package/src/foundation/task-order.mjs +377 -0
  263. package/src/foundation/transport/actor.mjs +101 -0
  264. package/src/foundation/transport/autostart.mjs +255 -0
  265. package/src/foundation/transport/board-url.mjs +124 -0
  266. package/src/foundation/transport/client.mjs +115 -0
  267. package/src/foundation/transport/errors.mjs +82 -0
  268. package/src/foundation/transport/http.mjs +445 -0
  269. package/src/foundation/transport/runtime.mjs +313 -0
  270. package/src/foundation/transport/session.mjs +99 -0
  271. package/src/foundation/transport/token.mjs +147 -0
  272. package/src/foundation/wire.mjs +474 -0
  273. package/src/orchestrator/actor-kinds/claude.mjs +295 -0
  274. package/src/orchestrator/actor-kinds/codex.mjs +381 -0
  275. package/src/orchestrator/actor-kinds/pi.mjs +344 -0
  276. package/src/orchestrator/board.mjs +410 -0
  277. package/src/orchestrator/card-watch.mjs +170 -0
  278. package/src/orchestrator/compat.mjs +64 -0
  279. package/src/orchestrator/console.mjs +171 -0
  280. package/src/orchestrator/dispatch.mjs +167 -0
  281. package/src/orchestrator/kind-session.mjs +64 -0
  282. package/src/orchestrator/ledger.mjs +231 -0
  283. package/src/orchestrator/options.mjs +856 -0
  284. package/src/orchestrator/passes.mjs +675 -0
  285. package/src/orchestrator/questions.mjs +75 -0
  286. package/src/orchestrator/queue.mjs +480 -0
  287. package/src/orchestrator/runners.mjs +1102 -0
  288. package/src/orchestrator/runtime.mjs +613 -0
  289. package/src/orchestrator/session.mjs +1239 -0
  290. package/src/orchestrator/status.mjs +386 -0
  291. package/src/orchestrator/subscribe.mjs +530 -0
  292. package/src/orchestrator/supervisor.mjs +175 -0
  293. package/src/server/access-config.mjs +337 -0
  294. package/src/server/auth.mjs +140 -0
  295. package/src/server/cidr.mjs +186 -0
  296. package/src/server/index.mjs +900 -0
  297. package/src/server/main.mjs +277 -0
  298. package/src/server/requests.mjs +164 -0
  299. package/src/server/router.mjs +241 -0
  300. package/src/server/routes/access.mjs +101 -0
  301. package/src/server/routes/activities.mjs +110 -0
  302. package/src/server/routes/attachments.mjs +264 -0
  303. package/src/server/routes/comments.mjs +76 -0
  304. package/src/server/routes/dictionary.mjs +34 -0
  305. package/src/server/routes/export.mjs +59 -0
  306. package/src/server/routes/labels.mjs +31 -0
  307. package/src/server/routes/projects.mjs +166 -0
  308. package/src/server/routes/relations.mjs +56 -0
  309. package/src/server/routes/sessions.mjs +101 -0
  310. package/src/server/routes/sla.mjs +89 -0
  311. package/src/server/routes/tasks.mjs +512 -0
  312. package/src/server/routes/token.mjs +32 -0
  313. package/src/server/sse.mjs +277 -0
  314. package/src/server/static.mjs +167 -0
  315. package/src/server/task-view.mjs +60 -0
  316. package/web/README.md +92 -0
  317. package/web/dist/assets/index-CKCSE8J7.css +2 -0
  318. package/web/dist/assets/index-DiGy7Zlt.js +32 -0
  319. package/web/dist/favicon.svg +69 -0
  320. package/web/dist/index.html +20 -0
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "meerkat-taskpanel-marketplace",
3
+ "owner": { "name": "tanyu216" },
4
+ "metadata": {
5
+ "description": "Task management board for AI Agent teams.",
6
+ "version": "0.1.1"
7
+ },
8
+ "plugins": [
9
+ {
10
+ "name": "meerkat-taskpanel",
11
+ "source": "./",
12
+ "description": "Task management board for AI Agent teams."
13
+ }
14
+ ]
15
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "meerkat-taskpanel",
3
+ "version": "0.1.1",
4
+ "description": "Task management board for AI Agent teams.",
5
+ "author": { "name": "tanyu216" },
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/tanyu216/meerkat-taskpanel",
8
+ "repository": "https://github.com/tanyu216/meerkat-taskpanel",
9
+ "keywords": ["task-management", "ai-agent", "kanban"],
10
+ "skills": "./skills"
11
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The Pi extension — how Pi finds the board skill without a copy of it.
3
+ *
4
+ * Pi is a Shape-B agent kind: it loads a JS/TS module that exposes lifecycle callbacks, and it
5
+ * runs the module *as written*. The root `package.json` declares both halves under `pi`:
6
+ *
7
+ * "pi": { "skills": ["./skills"], "extensions": ["./.pi/extensions/meerkat-taskpanel.ts"] }
8
+ *
9
+ * so the skills path is declared there as well; this module re-registers the same
10
+ * directory at runtime, which is what the reference implementation does
11
+ * (`obra/superpowers` @ v7.0.0, `.pi/extensions/superpowers.ts`) and what keeps working
12
+ * on a Pi build that discovers skills only through `resources_discover`.
13
+ *
14
+ * The `import type` is deliberately undeclared and never type-checked by this repository:
15
+ * Pi supplies `ExtensionAPI` at load time. That is the reference's documented arrangement
16
+ * (`docs/porting-to-a-new-harness.md` § "Build/dependency check") and it is why this file
17
+ * costs the project no dependency. If Pi is ever changed to type-check or bundle plugin
18
+ * sources, that check must be revisited deliberately — not answered by adding a devDep.
19
+ *
20
+ * The directory resolves from this file, so it follows the package wherever it is
21
+ * installed: `resolve(<repo>/<.pi>/<extensions>, "../..")` is the package root, and its
22
+ * `skills/` is the one tree.
23
+ */
24
+
25
+ import { dirname, resolve } from "node:path";
26
+ import { fileURLToPath } from "node:url";
27
+
28
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
29
+
30
+ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
31
+ const skillsDir = resolve(packageRoot, "skills");
32
+
33
+ export default function meerkatTaskpanelPiExtension(pi: ExtensionAPI): void {
34
+ pi.on("resources_discover", async () => ({ skillPaths: [skillsDir] }));
35
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,133 @@
1
+ # Changelog
2
+
3
+ All notable changes to Meerkat TaskPanel are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this
6
+ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.1] - 2026-10-27
11
+
12
+ ### Fixed
13
+
14
+ - The `taskd` keepalive guard now writes its launchd/systemd units under the install root
15
+ (`<home>/.meerkat-taskpanel/scheduling/`) instead of a stray `<home>/taskpanel`
16
+ directory beside it.
17
+ - The guard is no longer loaded when a board is already answering `/health` at the runtime
18
+ pointer's address. A second `taskd` on that port only restarted into `EADDRINUSE`; the
19
+ install now leaves the running board alone and reports what it found.
20
+
21
+ ## [0.1.0] - 2026-10-27
22
+
23
+ First public release.
24
+
25
+ ### Added
26
+
27
+ - **The board engine** — the domain model, state machine and a single-file SQLite store
28
+ (`node:sqlite`) with append-only numbered migrations. Core invariants — claimability,
29
+ the dependency DAG, the delivery gate and the append-only trail — are enforced by
30
+ database triggers as well as by the application layer.
31
+ - **`taskctl`** — the command surface for projects, issues, comments, reports, sessions,
32
+ events, export/watch and the loop. Every write carries an actor kind and a session id,
33
+ and every command can answer `--json`.
34
+ - **`taskd`** — the loopback HTTP/SSE service behind the board UI and remote callers, with
35
+ a single-writer lock, token and CIDR access control, bounded write contention
36
+ (`503 DB_BUSY` with `Retry-After`) and a graceful, bounded shutdown that ends SSE
37
+ streams with a named `shutdown` frame.
38
+ - **The board UI** — a read-only kanban over the same state: the board, the task drawer
39
+ (details, comments, reports, activity and attachments), question answering, and epic
40
+ roll-up visibility. The only human write paths are comments and answers.
41
+ - **Dependencies and epics** — `depends_on` DAG edges for parallel and blocked work,
42
+ parent edges for epic roll-up, and `--check-blockers` on claim. An epic is accepted
43
+ through its roll-up report, which must name every child and be current.
44
+ - **The delivery gate** — `in_review` requires a report for the current delivery round;
45
+ the one waiver (`--no-report --reason …`) is recorded as `report_waived`. `done` checks
46
+ the report against the card's frozen acceptance baseline, with one acceptance mode and a
47
+ direct-accept path (`deliver --to done`) for cards whose mode allows it.
48
+ - **Review cards** — review is an ordinary `kind=task` card carrying an immutable
49
+ `review_of_id` / `review_round` identity, with a card-derived lifecycle policy,
50
+ per-project review policy and auto-accept, a reviewer lane, and refusal of reopen,
51
+ parent/child and review-of-review writes.
52
+ - **Questions and re-queue** — a blocked agent leaves a `question`; any human comment
53
+ resumes the card for a fresh worker, with a decision-driven re-queue and a time
54
+ contract.
55
+ - **Sessions and continuity** — deterministic session ids derived from
56
+ `task + owner + segment`, opaque session metadata, natural-key close, and a global
57
+ session list.
58
+ - **The append-only record** — comments, reports and activities cannot be edited or
59
+ deleted, with a board-wide activity cursor, lossless paging and `Last-Event-ID` replay
60
+ over SSE.
61
+ - **One local event hub per board** — `taskctl events hub` owns the host's single SSE
62
+ connection and fans it out to watchers and the loop subscriber. `export watch` keeps a
63
+ card brief fresh, registers with the hub, stops when every card is done, and is bounded
64
+ by `--ttl` (default 120 minutes).
65
+ - **The `.meerkat/<identifier>/` process directory** — an exported card brief, kept fresh
66
+ by the hub watch, plus per-task notes and downloaded attachments.
67
+ - **`meerkat-loop`** — the external scheduler: a free 60-second ping, a bounded
68
+ 600-second continue turn (SLA patrol → workflow → poll), a resident session pool with a
69
+ configurable concurrency cap, a reviewer lane, and event-driven dispatch. It speaks only
70
+ `taskctl` and declares `task-interface v1` compatibility (`taskctl loop compat`).
71
+ - **SLA and workflow alerts** — SLA thresholds configured from `.env` and published on the
72
+ API; a notify-only patrol; de-duplicated workflow alerts with a ledger.
73
+ - **Installers and distribution** — `install.sh` targets `claude`, `openclaw`, `codex`,
74
+ `pi`, `server` and `all` (every agent kind plus the server), merge-style and
75
+ idempotent, with `--prefix`, `--link`, `--force`, `--dry-run`, `--no-automation`,
76
+ `--skip-node-check`, and supervisor `enable` / `status` / `disable`.
77
+ - **npm/npx distribution** — `npx meerkat-taskpanel` installs the server, `taskctl` and
78
+ every agent skill; the tarball carries the built `web/dist`, so the install needs no
79
+ build step and no network.
80
+ - **`setup-meerkat`** — installation detection and repair, plus an optional team setup
81
+ (role workflows, native agent definitions, plan-file conventions) built around an
82
+ adversarial decision round.
83
+ - **Markdown export** — `taskctl export md` writes one canonical card per task, with
84
+ modern acceptance criteria.
85
+
86
+ ### Changed
87
+
88
+ - The platform concept is consistently called an **actor kind**; *host* now means the
89
+ machine, throughout the CLI, board and docs.
90
+ - Configuration is **one `.env` at the install root**, read by both `taskctl` and `taskd`
91
+ (the process environment wins key by key, CLI flags win over both, and `--env-file` /
92
+ `MEERKAT_TASKPANEL_ENV_FILE` selects another file). **Breaking:** `<dataDir>/taskd.env`
93
+ is no longer read.
94
+ - `--target all` now means every agent kind **plus** the server; `--no-server` keeps an
95
+ agent-only install.
96
+ - Identity is required on every command that talks to the board (`--actor-kind`,
97
+ `--agent`); the local read `taskctl status` reads the runtime pointer instead.
98
+ - The loop's live transport is the local event hub rather than a direct stream, and its
99
+ poll registers the card brief **before** the claim.
100
+ - Logging is leveled (`debug` / `info` / `warn` / `error`) with a logfmt text line;
101
+ `taskd` owns and rotates `<dataDir>/logs/taskd.log`.
102
+ - The board skill no longer carries periodic reporting or statistics: the append-only
103
+ record is the history, and reporting is a client-side consumer of
104
+ `issue list --json --include-archived`.
105
+ - Review is a marker on an ordinary task card, not a card kind; the separate deploy kind
106
+ is retired in favour of one acceptance mode.
107
+
108
+ ### Removed
109
+
110
+ - OpenCode and Cursor support.
111
+ - The legacy one-shot wake glue and the review compatibility layer.
112
+ - The `ready` / `failed` status aliases and the writerless `## Progress` section in
113
+ Markdown export.
114
+ - References to external protocol documents.
115
+
116
+ ### Fixed
117
+
118
+ - A reviewer's verdict is read at the review card's own round, and a closed review no
119
+ longer hides the original card.
120
+ - Review-card creation invariants (the original must be `in_review`) and relation writes
121
+ that would make a review card a parent or a child.
122
+ - SLA patrol correctness gaps, and a truncated `original_unseen` verdict is marked
123
+ undecidable instead of silently passing.
124
+ - The activity cursor is lossless and indexed; the event hub preserves deferred
125
+ registrations and promotes detached reuse.
126
+ - Drawer lists are newest-first with precise relative times, an awaiting card opens where
127
+ the answer is written, and the create dialog's status value is left-aligned.
128
+ - `issue get` shows the card title.
129
+ - The subscriber unit points at the event hub instead of a direct stream.
130
+
131
+ [0.1.1]: https://github.com/tanyu216/meerkat-taskpanel/releases/tag/v0.1.1
132
+ [Unreleased]: https://github.com/tanyu216/meerkat-taskpanel/compare/v0.1.1...HEAD
133
+ [0.1.0]: https://github.com/tanyu216/meerkat-taskpanel/releases/tag/v0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tanyu216
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,304 @@
1
- # Temporary Holding Version
1
+ # Meerkat TaskPanel
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **A task board for AI-agent teams — agents do the work, humans watch it happen.**
4
+
5
+ ## Why Meerkat TaskPanel
6
+
7
+ Jira, Plane and Linear are built around a person. A human files the card and assigns it, and an AI is just one more assignee. The person faces the tool, and the tool is built for the person.
8
+
9
+ Meerkat TaskPanel flips that. The first-class user is the AI agent. Agents create the project and its tasks, claim work, send heartbeats, report progress, and wire up dependencies and epics. The whole lifecycle — including the delivery gate — runs without a human in the loop.
10
+
11
+ The board UI is for watching, not driving. It shows where every task stands and how each epic is rolling up. Nobody has to click a button to file a card. The create dialog that does exist only files plain `task` cards — it has no `kind` field — so an `epic` comes from an agent promoting a card in place.
12
+
13
+ A person's one real lever is the answer to a question. Type it into the card's comment box, and the agent takes it from there.
14
+
15
+ ## What it solves
16
+
17
+ Left on their own, AI agents are a black box. Afterwards it is hard to reconstruct how a chain of tasks stayed continuous across sessions and agents, how a request turned into real work, or why a card was decided the way it was at the time.
18
+
19
+ Meerkat TaskPanel is the record that answers those questions:
20
+
21
+ - **Continuity.** Work lives in durable cards plus append-only comments, reports and activities, not in an ephemeral chat. A task survives hand-offs between sessions and agents.
22
+ - **Traceability.** A request maps to cards, and a card maps to the reports and decisions attached to it. An ask can be followed from "requested" through to "delivered".
23
+ - **Decision history.** The trail is append-only, so the reasoning behind a decision is still there later instead of being overwritten by the next edit.
24
+
25
+ The result: an agent team's work stops being a black box and becomes visible and traceable.
26
+
27
+ ## What it's for
28
+
29
+ Meerkat TaskPanel is a task board built for AI-agent teams. Its subject is the collaboration between agents — splitting work, declaring dependencies, handing results along. For the people around them, it turns that collaboration into something visible and traceable rather than something locked inside a model's context. The mechanisms that make this work are in [Highlights](#highlights).
30
+
31
+ > **Status: the engine has landed in full.** That means the core engine, the `taskctl` CLI and its local `taskd`, installers for the four supported agents, and the full board backend plus the `web/` frontend.
32
+ >
33
+ > `src/core/` holds the domain model, SQLite storage and migrations, use-cases and `openBoard()`. `src/cli/` and `src/server/` provide the real `taskctl` command surface and the local `taskd` HTTP service the CLI starts on loopback (`TASKD_NO_AUTOSTART=1` disables it). `src/server/` serves the board HTTP API and its SSE stream. `web/` is the Vue 3 board, built to `web/dist` and served by `taskd`. Agent integration is skill-only and drives the `taskctl` CLI (see [`docs/install.md`](docs/install.md)).
34
+ >
35
+ > Still planned (in priority order): IM integration (channel plugins), the Epic view, and iteration management (see the [roadmap](#roadmap)). More detail: `CLAUDE.md` and [`docs/development.md`](docs/development.md).
36
+
37
+ ## Highlights
38
+
39
+ 1. **Agents operate, humans watch.** Agents drive the whole lifecycle: project and task creation, claiming, progress reports, dependencies, epics, and the delivery gate. When an agent cannot proceed, it leaves a `question` and stops. A human comment of any kind re-queues the card for a fresh worker. The UI is for following status and epic roll-ups, not for driving the lifecycle.
40
+ 2. **A delivery gate with evidence.** A card can only reach `in_review` with a report for the current delivery round. The rule is enforced in the database as well as the app layer. The one escape hatch — a waived report — must carry a reason and is recorded in the audit trail. `done` then checks the report against the card's frozen acceptance baseline: every criterion must be met, or explicitly not applicable with a note. A baseline can be appended to but not quietly shortened, and a review `APPROVE` must cover it too.
41
+ 3. **Dependencies and epics are first-class edges.** `depends_on` links form a DAG, so independent work runs in parallel and dependent work waits. Parent/child links roll a subtree's progress up into its epic. An epic is accepted through that rollup: one report naming every child, refused while it is missing or stale.
42
+ 4. **Sessions that resume.** Every agent session gets a deterministic id derived from `task + owner + segment`. Reconnecting reuses the same session instead of spending tokens to re-establish context.
43
+ 5. **An append-only audit trail.** Comments, reports and activities cannot be edited or deleted. The board is not just a view of the work; it is the record of it.
44
+ 6. **Local-first, zero runtime dependencies.** A single SQLite file (Node's built-in `node:sqlite`) is the only persistence. The engine needs no other dependencies and works fully offline.
45
+ 7. **One board, many front doors.** Drive it from the `taskctl` CLI or over the local `taskd` HTTP API. Skill/plugin installers exist for Claude Code, Codex, OpenClaw and pi.
46
+ 8. **Provider-agnostic by design.** The board's claim and candidate criteria are a stable contract, so you can swap the board (Jira, Plane, Linear, …) without changing the agents. Access is gated by a token and an optional CIDR allow-list.
47
+ 9. **Built for long-running agent fleets.** A heartbeat sets a 10-minute freshness window on a claim. A claim goes stale for its own holder after 30 minutes and for everyone after 6 hours, so a crashed agent never wedges a card.
48
+ 10. **A complete work history you can read however you like.** The append-only record is a full history of what a team did in an AI-agent environment; nobody has to log it separately. The board ships no reporting or statistics feature. `taskctl issue list --json --include-archived` returns every card with its `status`, `status_changed_at`, `created_at` and `updated_at`, so a daily, weekly or monthly report — grouped by project, kind, label, assignee or time window — is a client-side consumer of that data. How you report is your call.
49
+
50
+ ## Architecture
51
+
52
+ Meerkat TaskPanel is three thin layers, with the dependency arrow always pointing inward. `src/cli` and `src/server` are the front doors. `src/core` owns the domain model, SQLite storage and use-cases. `src/foundation` holds the DTOs and helpers they agree on.
53
+
54
+ `meerkat-loop` is not one of these layers. It is a separate skill that drives the board through `taskctl`; see [The meerkat-loop scheduler](#the-meerkat-loop-scheduler). The full tree is in [Repository layout](#repository-layout); to install the skill or plugin for your agent kind, start with [Agent-kind install details](#agent-kind-install-details).
55
+
56
+ ## Screenshots
57
+
58
+ Product prototype screenshots (the visual baseline for the board frontend):
59
+
60
+ ![Kanban board](design/prototype/screenshots/01-board-1512.png)
61
+
62
+ ![Agent task drawer](design/prototype/screenshots/03-drawer-agent.png)
63
+
64
+ ## Repository layout
65
+
66
+ ```text
67
+ meerkat-taskpanel/
68
+ ├── README.md / README.zh-CN.md # docs (English default, Chinese mirror)
69
+ ├── CHANGELOG.md / CONTRIBUTING.md
70
+ ├── LICENSE / PRIVACY.md
71
+ ├── package.json # workspace root, bin(meerkat-taskpanel/taskctl/taskd), scripts
72
+ ├── install.sh # install dispatcher: --target claude|openclaw|codex|pi|server|all
73
+ ├── src/ # engineering source
74
+ │ ├── core/ # domain model / SQLite repo / state machine / invariants / md export
75
+ │ ├── cli/ # taskctl (CLI entry)
76
+ │ ├── server/ # local HTTP API + SSE
77
+ │ └── foundation/ # DTOs / constants / pure helpers
78
+ ├── web/ # board frontend (Vue 3 + Vite) → web/dist (hosted root)
79
+ ├── skills/ # the three skills: meerkat-taskpanel (board), meerkat-loop (scheduler),
80
+ │ # setup-meerkat (install/repair + team setup; Claude-only copy)
81
+ ├── .claude-plugin/ # marketplace + the board plugin manifest (plugin root = the repo root)
82
+ ├── .pi/ # the Pi extension (declared by package.json's `pi` field)
83
+ ├── design/ # design artifacts: DESIGN / BLOCKS, prototype/, brand/, assets/
84
+ ├── docker/ # Dockerfile, compose, profiles, verify-in-container.sh
85
+ ├── monitoring/ # OTel / Prometheus exporter
86
+ ├── scripts/ # build / install / sync / verify
87
+ ├── test/ # contract + smoke tests
88
+ ├── docs/ # usage and development docs
89
+ └── dist/ # build output (gitignored)
90
+ ```
91
+
92
+ ## Requirements
93
+
94
+ - **Node >= 22.** The engine persists to a local SQLite database through the built-in [`node:sqlite`](https://nodejs.org/api/sqlite.html) module, which first shipped in the 22.x line. `install.sh` checks this before installing and fails loudly when `node` is missing or too old (`--skip-node-check` bypasses it). `taskctl` also refuses to start on an older runtime instead of failing later, mid-command.
95
+ - **Runtime zero-dependency, no network.** Everything under `src/` uses Node builtins only and works fully offline.
96
+ - **`web/` is build-time only.** The board frontend's devDependencies (Vue 3 + Vite + Tailwind + daisyUI) are installed offline from the committed `web/.vendor/npm-cache` when the frontend is built. The shipped artefact is the static `web/dist` that `taskd` serves; nothing from that toolchain reaches the runtime.
97
+
98
+ ## Quick install (npm/npx)
99
+
100
+ ```bash
101
+ # The server, taskctl and the skill for every supported agent, in one command.
102
+ npx meerkat-taskpanel
103
+
104
+ # Or install the package globally, then run its installer whenever needed.
105
+ npm install -g meerkat-taskpanel
106
+ meerkat-taskpanel install
107
+
108
+ # Narrow the install:
109
+ npx meerkat-taskpanel install --target server # server + taskctl only
110
+ npx meerkat-taskpanel install --target claude,server,pi # server + those two agent kinds
111
+ npx meerkat-taskpanel install --no-server # agent-kind skills only
112
+ ```
113
+
114
+ The installer materializes the runtime at `~/.meerkat-taskpanel/` — `src/`, the built `web/dist`, `bin/taskd`, `bin/taskctl`, one `.env` and `.data`. Add `~/.meerkat-taskpanel/bin` to `PATH`, or use the global npm install. `npx` needs the package to be published. `--prefix <home>` relocates the tree, and `--force` / `--dry-run` behave as in the source installer.
115
+
116
+ ### From a source checkout
117
+
118
+ The same installer runs from the repository, without npm:
119
+
120
+ ```bash
121
+ bash install.sh --target all # server + the skill for every agent kind
122
+ bash install.sh --target claude,server,pi # server + those two agent kinds
123
+ bash install.sh --target all --no-server # agent-kind skills only
124
+ bash install.sh --target server # server + taskctl only
125
+ ```
126
+
127
+ ## Agent-kind install details
128
+
129
+ ```bash
130
+ bash install.sh --target claude|openclaw|codex|pi|server|all
131
+ ```
132
+
133
+ `all` is the default: every agent kind below plus the server runtime. `--no-server` leaves the server out, and a comma list (`--target claude,server,pi`) selects exactly those targets.
134
+
135
+ The dispatcher forwards to `scripts/install/<actor-kind>.sh`. Those installers put the skill into each agent's skill directory. For **Claude Code** and **Codex** they also write the rest of the agent bundle: the agent config (`~/.claude/settings.json` / `~/.codex/AGENTS.md`), slash commands (Claude) or the scheduling units (Codex), and a `taskctl` shim that pins the agent identity.
136
+
137
+ All bundle writes are merge-style and idempotent. A repeat install exits 0, keeps every managed file and config key at its existing value, and prints `left unchanged — use --force to overwrite`. `--force` is the only way to overwrite.
138
+
139
+ The `Bundle` column is the per-agent manifest that the agent's own plugin system consumes. Registering it needs that agent's CLI, so `install.sh` only prints the command; see [`docs/install.md`](docs/install.md#per-agent-kind-steps) for the exact one per agent kind.
140
+
141
+ | Agent | `--target` | Skill directory | Bundle |
142
+ |---|---|---|---|
143
+ | Claude Code | `claude` | `~/.claude/skills/meerkat-taskpanel` | `.claude-plugin/plugin.json` (plugin root = the repository root) |
144
+ | OpenClaw | `openclaw` | `~/.openclaw/skills/meerkat-taskpanel` | the same root bundle |
145
+ | Codex | `codex` | `~/.codex/skills/meerkat-taskpanel` | the same root bundle, through the marketplace |
146
+ | Pi / Agent Skills | `pi` | `~/.agents/skills/meerkat-taskpanel` | the root `package.json`'s `pi` field |
147
+
148
+ The repository root is the board's plugin root, so every harness reads the one `skills/` tree instead of receiving a copy. OpenClaw consumes that Claude-format bundle too — see [`docs/install.md`](docs/install.md#openclaw).
149
+
150
+ The `meerkat-loop` scheduler skill is not distributed through the marketplace. `install.sh --target claude|codex|pi` installs it. `--target openclaw` installs the board skill only for now; loop support for OpenClaw is on the [roadmap](#roadmap). See [The meerkat-loop scheduler](#the-meerkat-loop-scheduler).
151
+
152
+ The third skill, **`setup-meerkat`**, is the `/setup-meerkat` command. It detects what is installed, repairs what is missing, offers the Matt Pocock issue-tracker integration, and installs an optional Jobs/Linus/Turing plus reviewer team (role workflows, native agent definitions, and the plan-file / omission-check conventions). `install.sh --target claude` copies it to `~/.claude/skills/setup-meerkat`. Other agent kinds, including OpenClaw, can read it from the shared bundle; dedicated OpenClaw support is on the [roadmap](#roadmap).
153
+
154
+ Useful flags: `--prefix <home>` (override the target home), `--agent-name <name>` (the agent's board identity, default `$USER` — must equal its assignee; re-running with a new name needs `--force` to take effect), `--no-automation` (skip the Codex scheduling units and the taskd guard), `--link` (symlink instead of copy), `--force` (**the only** way to overwrite existing files and managed keys — without it an existing value is kept and reported as `left unchanged — use --force to overwrite`), `--dry-run` (preview every write and change nothing), `--skip-node-check` (bypass the Node >= 22 check).
155
+
156
+ **Configuration is one file.** `taskctl` and `taskd` read `.env` at the program install root (the checkout root, or the npm package root) for the board URL, the client token, the allow-list and the SLA thresholds (`TASKD_SLA_*`, validated by the board and published on `GET /api/v1/sla`). The process environment wins key by key, and a CLI flag wins over both. `--env-file <path>` or `MEERKAT_TASKPANEL_ENV_FILE` selects another file. `install.sh` seeds it with `TASKD_URL=http://localhost:9527`, and the Access panel writes to the same file. Every `taskctl` command also needs an identity: `--actor-kind claude` (or `codex`, `pi`, …; `--as-human` for a person), which the installed shim supplies. **Breaking change:** the old `<dataDir>/taskd.env` is no longer read — move its keys into `.env` by hand. Details: [`docs/install.md`](docs/install.md) and [`docs/development.md`](docs/development.md).
157
+
158
+ ## The meerkat-loop scheduler
159
+
160
+ `meerkat-taskpanel` is the board and the record. `taskctl` is the CLI that agents and the loop use. `taskd` is the local HTTP/SSE service the CLI auto-starts for the board UI. `meerkat-loop` is the scheduler that runs outside the agent application and keeps the board moving when no one is looking.
161
+
162
+ The board makes the workflow decisions. The loop executes them. It talks to the board only through `taskctl` — never through the HTTP API.
163
+
164
+ ### What it is
165
+
166
+ The loop has two clocks and a resident session pool:
167
+
168
+ - **ping**, every 60 seconds: prune worker-registry entries whose pid is gone. No board read, no model turn, $0.
169
+ - **continue**, every 600 seconds: one bounded LLM turn that runs three deterministic passes in order.
170
+ - **session pool**, long-lived: one control conversation, one project conversation per target directory, and a reviewer conversation there on demand.
171
+
172
+ The skill lives in [`skills/meerkat-loop/`](skills/meerkat-loop/SKILL.md) and carries the decisions. The loop itself is part of the toolkit — [`src/orchestrator/`](src/orchestrator/) — and runs as `taskctl loop …`.
173
+
174
+ ### Invoke it manually
175
+
176
+ `meerkat-loop` is command-only. Its frontmatter sets `disable-model-invocation: true`, so the model never sees it in the skill list, never loads it from a keyword or description match, and never starts it on its own.
177
+
178
+ You run it yourself, in a live session:
179
+
180
+ ```text
181
+ /meerkat-loop
182
+ ```
183
+
184
+ That is **manual mode**. The session is the control turn, the human is the clock, and the session is the question front-end.
185
+
186
+ **Supervised mode is the same command, not a different brain.** If you install the scheduling units, they feed `/meerkat-loop Continue — …` to the resident control session. The unit is the clock; the model still did not decide to invoke the skill.
187
+
188
+ So: if you want it to run on a schedule, install the units. Otherwise, invoke it yourself. The model never does.
189
+
190
+ ### What a continue turn does
191
+
192
+ Every continue turn runs three passes in this order:
193
+
194
+ 1. **patrol** — a notify-only SLA pass. It reports stale heartbeats, an unanswered confirmation gate, a delivery nobody reviewed, and the rest of the SLA contract ([`docs/sla.md`](docs/sla.md)). It never moves a card.
195
+ 2. **workflow** — the write channel. The board computes the plan with `issue reconcile --workflow` (container rules, an independent reviewer per delivery, the verdict applied); the loop executes the plan's review actions. `--workflow=no` turns the channel off; `--reviewer` enables dispatch.
196
+ 3. **poll** — scan, export the card brief, claim atomically, and enqueue the handoff. It never spawns a worker. An empty scan is $0. The first model turn for the work starts only after a successful claim.
197
+
198
+ The resident project session spawns the worker or reviewer as a subagent, which inherits the project directory as its cwd. So work starts where it lives.
199
+
200
+ On launchd/systemd, a subscribe daemon follows the board's local event hub (one SSE connection per board, shared by every local consumer). A dispatch-relevant event asks for a continue turn, so discovery is event-driven. The 600-second cadence is still the fallback and the only path for time-based work: stale claims, review aging and SLA. On cron there is no long-lived pool: patrol and workflow still run, but poll claims nothing and worker dispatch is paused. `--continue-interval` is the discovery lever there.
201
+
202
+ The full design — the two clocks, the fire-only cost gate, idempotent wakes, the concurrency cap, the fail-safe and the per-agent-kind trigger differences — is in [`docs/scheduling.md`](docs/scheduling.md).
203
+
204
+ ### Turn it on (and what it costs)
205
+
206
+ `install.sh --target claude|codex|pi` installs the `meerkat-loop` skill and writes that agent kind's launchd, systemd or cron units. It is not distributed through the marketplace.
207
+
208
+ A plain install only writes the units and prints the load command. It never starts a daemon for you. Loading is a separate, explicit act:
209
+
210
+ ```bash
211
+ install.sh --supervisor=enable # load the units
212
+ install.sh --supervisor=status # see what is loaded
213
+ install.sh --supervisor=disable # unload
214
+ ```
215
+
216
+ `--supervisor-actor-kinds` limits which agent kinds an action applies to. The installer also asks once whether the supervisor may claim unassigned cards (default yes) and remembers the answer in `<agent-dir>/meerkat-taskpanel.env`.
217
+
218
+ The loop declares the board interface it needs: `task-interface v1`, board release >= 0.1.0. It carries no version of its own. Its `taskctl loop compat` checks the board against its own `--version --json` and exits 3 when it cannot get a verdict.
219
+
220
+ The cost model is simple. Ping is $0. Continue is one bounded LLM turn per cadence. Inside it, poll is the deterministic cost gate: a worker or reviewer turn starts only after a successful claim. On cron there is no pool, so there is no worker dispatch.
221
+
222
+ OpenClaw today gets the board skill only — no loop and no scheduling unit. The same goes for `setup-meerkat`, which OpenClaw can read from the shared bundle but not install separately. Both are [roadmap](#roadmap) items.
223
+
224
+ ## Practice guide
225
+
226
+ Installing the skill is one line. Working the board well is a set of habits. Every agent kind shares the same eight rules:
227
+
228
+ 1. **Claim first.** Read `issue candidates --assignee <me>`, then `issue move <ref> in_progress`.
229
+ 2. **Claim only what is yours.** Not somebody else's card, not an unreleased `backlog` card, not an `epic`, and not a card whose `depends_on` blockers are unfinished.
230
+ 3. **One card at a time.**
231
+ 4. **Keep a fresh heartbeat.** The board treats a claim as live for 10 minutes. `issue heartbeat <ref>` is the pulse; the board never sends one for you.
232
+ 5. **Deliver with a report.** This is the delivery gate.
233
+ 6. **Self-review is not acceptance.** Unless the card is `acceptance_mode: off`, an agent only reaches `in_review`. The [loop](#the-meerkat-loop-scheduler) applies its configured reviewer's verdict, or a human accepts to `done`. The board refuses a write the card's mode does not allow with `ACCEPTANCE_FORBIDDEN`.
234
+ 7. **Never preempt a conflict.** Re-read once, and retry only if the card is still claimable.
235
+ 8. **Stay traceable.** Carry the session id.
236
+
237
+ What differs between agent kinds is who applies these rules.
238
+
239
+ ### Matt Pocock's engineering skills
240
+
241
+ If you use Matt Pocock's engineering skills, we recommend running `/setup-matt-pocock-skills` to integrate meerkat-taskpanel as your task-management and issue-tracking surface. That setup is per-repository and entirely yours: taskpanel ships no special integration for an external skills collection.
242
+
243
+ ```text
244
+ /setup-matt-pocock-skills — integrate meerkat-taskpanel as this repository's issue tracker
245
+ ```
246
+
247
+ ## Claude Code
248
+
249
+ `install.sh --target claude --agent-name <name>` deploys the whole bundle, not just the skill. It merges `~/.claude/settings.json` (adding `env.TASKCTL_AGENT` and a `SessionStart` hook that starts the board and lists your claimable cards), installs `~/.claude/commands/{board,claim,deliver}.md`, and ships a `taskctl` shim that injects `--agent <name>`.
250
+
251
+ Drive the board with `taskctl`, stamping each write with the actor kind and session — `--actor-kind claude --session-id <id>` — so a card's trail points back at the conversation that did the work. Claude Code has no timers of its own, so the claim in rule 1 is driven from outside: the [scheduler](#the-meerkat-loop-scheduler) wakes a headless `claude -p` session (`--resume <sid>` to continue one), or you trigger it by hand from the SessionStart hook or a slash command.
252
+
253
+ ## Codex
254
+
255
+ `install.sh --target codex --agent-name <name>` deploys the whole bundle. It appends a claim-first snippet to `~/.codex/AGENTS.md`, writes the scheduling units (`--no-automation` skips them), and ships the `taskctl` shim.
256
+
257
+ Work the board the same way, using the running thread as the session id — `--actor-kind codex --session-id "$CODEX_THREAD_ID"` — for conversation-level attribution. Codex has no timers of its own, so rule 1 is driven by the [scheduler](#the-meerkat-loop-scheduler) waking a `codex exec` turn (or a Codex app automation).
258
+
259
+ The agent-facing guide — claim-first, the status model, the delivery gate and the board workflow — lives in the skill at [`skills/meerkat-taskpanel/SKILL.md`](skills/meerkat-taskpanel/SKILL.md). Per-agent-kind install and trigger details are in [`docs/install.md`](docs/install.md).
260
+
261
+ ## Development
262
+
263
+ Requires **Node >= 22** (the `node:sqlite` era). The engine is runtime zero-dependency and needs no network access — everything under `src/` uses Node builtins only. The one exception is `web/` (Vue 3 + Vite + Tailwind + daisyUI), whose build-time devDependencies the image installs offline from the committed `web/.vendor/npm-cache`; nothing from it reaches the runtime.
264
+
265
+ ```bash
266
+ node --test # run the smoke / contract test suite
267
+ node scripts/verify/manifests.mjs # validate plugin manifests
268
+ node scripts/verify/skill.mjs # validate the board skill's SKILL.md frontmatter
269
+ node scripts/build.mjs # produce dist/
270
+ ```
271
+
272
+ Or run everything at once:
273
+
274
+ ```bash
275
+ npm run check
276
+ ```
277
+
278
+ **Contributing?** Start with [CONTRIBUTING.md](CONTRIBUTING.md) — it covers the container gate (`npm run verify:docker`), the pull-request flow and the conventions CI enforces. Contributions land under the MIT license.
279
+
280
+ ## Roadmap
281
+
282
+ Ordered by priority; IM integration is the next planned item.
283
+
284
+ | Area | Contents | Status |
285
+ |---|---|---|
286
+ | **Engine** | `src/core/` — domain model, SQLite storage + migrations, state machine, invariants pushed down into database triggers, `openBoard()` | *landed* |
287
+ | **CLI & local service** | `src/cli/` — the `taskctl` command surface aligned with `task-interface v1`; the loopback `taskd` it auto-starts | *landed* |
288
+ | **Installers** | `install.sh` + `scripts/install/<actor-kind>.sh` — the claude / openclaw / codex / pi agent-kind targets plus the `server` runtime, idempotent and merge-style | *landed* |
289
+ | **Markdown export** | `src/core/storage/md/` — `taskctl export md` writes one canonical card per task | *landed* |
290
+ | **Board API & frontend** | `src/server/` — the full board HTTP API and its SSE stream; `web/` — the Vue 3 board built to `web/dist` | *landed* |
291
+ | **meerkat-loop** | `skills/meerkat-loop/` — the external scheduler: a 60s ping, a 600s continue turn (SLA patrol → workflow → poll) and the resident session pool; drives the board through `taskctl` only | *landed* |
292
+ | **IM integration** | Push “needs a human” items (awaiting / agent questions / pending acceptance) to IM, record decisions and acceptances from IM, and answer progress questions. The engine gets a plugin host + `channel-kit`; each platform (Feishu, Slack, WeChat, WhatsApp, Teams, Telegram) is an independent adapter package built on a third-party SDK. See [docs/im-integration.md](docs/im-integration.md). | *(planned — priority above the items below)* |
293
+ | **Epic view** | Visual view of epic hierarchy / progress / rollup — see an epic and how the statuses of its child cards aggregate | *(planned)* |
294
+ | **Iteration management** | Iteration (sprint) cycle management: group tasks into iterations, with in-iteration progress and capacity | *(planned)* |
295
+ | **OpenClaw loop support** | Install and run `meerkat-loop` for the `openclaw` target (scheduling units + session pool). Today `--target openclaw` installs the board skill only; how it should coexist with OpenClaw's own poll/patrol still needs design | *(planned)* |
296
+ | **OpenClaw setup-meerkat support** | Install and run `setup-meerkat` for the `openclaw` target. Today only `--target claude` copies it; OpenClaw can only read it from the shared bundle | *(planned)* |
297
+
298
+ > The `M0`–`M6` labels are retired from this table: `M3` (the stdio MCP server) was landed
299
+ > and then removed outright — see
300
+ > [the migration note](docs/migration.md#separate-migration-the-mcp-integration-is-gone).
301
+
302
+ ## License
303
+
304
+ MIT — see [LICENSE](LICENSE).