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.
- package/.claude-plugin/marketplace.json +15 -0
- package/.claude-plugin/plugin.json +11 -0
- package/.pi/extensions/meerkat-taskpanel.ts +35 -0
- package/CHANGELOG.md +133 -0
- package/LICENSE +21 -0
- package/README.md +303 -2
- package/README.zh-CN.md +303 -0
- package/docs/README.md +77 -0
- package/docs/contract.md +312 -0
- package/docs/development.md +435 -0
- package/docs/docker.md +559 -0
- package/docs/events.md +269 -0
- package/docs/im-integration.md +332 -0
- package/docs/install.md +889 -0
- package/docs/migration.md +59 -0
- package/docs/observability.md +321 -0
- package/docs/projects.md +63 -0
- package/docs/publishing.md +387 -0
- package/docs/scheduling.md +1860 -0
- package/docs/security.md +138 -0
- package/docs/sla.md +344 -0
- package/docs/web-local-first.md +76 -0
- package/install.sh +729 -0
- package/package.json +67 -4
- package/scripts/build.mjs +41 -0
- package/scripts/install/_common.sh +769 -0
- package/scripts/install/claude.sh +39 -0
- package/scripts/install/cli.mjs +161 -0
- package/scripts/install/codex.sh +36 -0
- package/scripts/install/lib/apply.mjs +419 -0
- package/scripts/install/lib/server-install.mjs +262 -0
- package/scripts/install/lib/supervisor.mjs +925 -0
- package/scripts/install/lib/taskd-guard.mjs +926 -0
- package/scripts/install/lib/unit-path.mjs +151 -0
- package/scripts/install/openclaw.sh +35 -0
- package/scripts/install/pi.sh +49 -0
- package/scripts/install/server.sh +41 -0
- package/scripts/install/templates/agent/meerkat-taskpanel.env +53 -0
- package/scripts/install/templates/claude/commands/board.md +15 -0
- package/scripts/install/templates/claude/commands/claim.md +12 -0
- package/scripts/install/templates/claude/commands/deliver.md +12 -0
- package/scripts/install/templates/claude/session-start.sh +40 -0
- package/scripts/install/templates/codex/AGENTS.md.snippet +11 -0
- package/scripts/install/templates/env.example +67 -0
- package/scripts/install/templates/scheduling/cron/meerkat-taskpanel.cron +19 -0
- package/scripts/install/templates/scheduling/launchd/com.meerkat-taskpanel.continue.plist +44 -0
- package/scripts/install/templates/scheduling/launchd/com.meerkat-taskpanel.ping.plist +44 -0
- package/scripts/install/templates/scheduling/launchd/com.meerkat-taskpanel.session.plist +48 -0
- package/scripts/install/templates/scheduling/launchd/com.meerkat-taskpanel.subscribe.plist +41 -0
- package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-continue.service +14 -0
- package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-continue.timer +12 -0
- package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-ping.service +18 -0
- package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-ping.timer +12 -0
- package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-session.service +36 -0
- package/scripts/install/templates/scheduling/systemd/meerkat-taskpanel-subscribe.service +22 -0
- package/scripts/install/templates/server/taskctl +12 -0
- package/scripts/install/templates/server/taskd +12 -0
- package/scripts/install/templates/taskctl-shim.sh +32 -0
- package/scripts/install/templates/taskd/launchd/com.meerkat-taskpanel.taskd.plist +49 -0
- package/scripts/install/templates/taskd/systemd/meerkat-taskpanel-taskd.service +41 -0
- package/scripts/release/bump.mjs +738 -0
- package/scripts/release/pack-manifest.mjs +254 -0
- package/scripts/security/scan-gate.mjs +1037 -0
- package/scripts/security/scan-gate.test.mjs +850 -0
- package/scripts/security/waivers.json +16 -0
- package/scripts/security/workflow.test.mjs +204 -0
- package/scripts/verify/changelog.mjs +170 -0
- package/scripts/verify/cli-contract.mjs +297 -0
- package/scripts/verify/contract.mjs +904 -0
- package/scripts/verify/docker.mjs +235 -0
- package/scripts/verify/install-e2e.sh +136 -0
- package/scripts/verify/kind-cli.mjs +226 -0
- package/scripts/verify/kind-resume-matrix.mjs +463 -0
- package/scripts/verify/kind-runtime.mjs +343 -0
- package/scripts/verify/kind-session-matrix.mjs +245 -0
- package/scripts/verify/lib/base-image.mjs +164 -0
- package/scripts/verify/lib/bundle.mjs +399 -0
- package/scripts/verify/lib/docker-plan.mjs +165 -0
- package/scripts/verify/lib/frontmatter.mjs +39 -0
- package/scripts/verify/lib/mini-yaml.mjs +69 -0
- package/scripts/verify/lib/profiles.mjs +401 -0
- package/scripts/verify/manifests.mjs +132 -0
- package/scripts/verify/migrations.mjs +278 -0
- package/scripts/verify/paths.mjs +250 -0
- package/scripts/verify/profiles.mjs +70 -0
- package/scripts/verify/route-request.mjs +909 -0
- package/scripts/verify/server-install.mjs +202 -0
- package/scripts/verify/signposts.mjs +344 -0
- package/scripts/verify/skill.mjs +133 -0
- package/scripts/verify/version.mjs +260 -0
- package/scripts/verify/web-dist.mjs +382 -0
- package/skills/meerkat-loop/SKILL.md +250 -0
- package/skills/meerkat-loop/references/decision-policy.md +146 -0
- package/skills/meerkat-loop/references/operation.md +257 -0
- package/skills/meerkat-taskpanel/SKILL.md +274 -0
- package/skills/meerkat-taskpanel/references/capabilities.md +191 -0
- package/skills/meerkat-taskpanel/references/card-schema.md +288 -0
- package/skills/meerkat-taskpanel/references/cli.md +751 -0
- package/skills/meerkat-taskpanel/references/projects-json.md +102 -0
- package/skills/meerkat-taskpanel/references/review-workflow.md +235 -0
- package/skills/meerkat-taskpanel/references/status-lifecycle.md +428 -0
- package/skills/meerkat-taskpanel/scripts/run.mjs +211 -0
- package/skills/meerkat-taskpanel/scripts/session-id.mjs +160 -0
- package/skills/setup-meerkat/SKILL.md +328 -0
- package/skills/setup-meerkat/assets/team/standard/agents/claude/role.md.tmpl +17 -0
- package/skills/setup-meerkat/assets/team/standard/agents/codex/role.toml.tmpl +15 -0
- package/skills/setup-meerkat/assets/team/standard/agents/pi/role.md.tmpl +16 -0
- package/skills/setup-meerkat/assets/team/standard/decision-policy.md +69 -0
- package/skills/setup-meerkat/assets/team/standard/jobs/self-check.md +109 -0
- package/skills/setup-meerkat/assets/team/standard/jobs/ui-workflow.md +111 -0
- package/skills/setup-meerkat/assets/team/standard/jobs/workflow.md +226 -0
- package/skills/setup-meerkat/assets/team/standard/linus/architecture-workflow.md +543 -0
- package/skills/setup-meerkat/assets/team/standard/linus/implementation-workflow.md +106 -0
- package/skills/setup-meerkat/assets/team/standard/linus/self-check.md +110 -0
- package/skills/setup-meerkat/assets/team/standard/linus/workflow.md +121 -0
- package/skills/setup-meerkat/assets/team/standard/manifest.json +126 -0
- package/skills/setup-meerkat/assets/team/standard/reviewer/reviewer-prompt.md +42 -0
- package/skills/setup-meerkat/assets/team/standard/reviewer/workflow.md +127 -0
- package/skills/setup-meerkat/assets/team/standard/turing/performance-workflow.md +49 -0
- package/skills/setup-meerkat/assets/team/standard/turing/regression-workflow.md +67 -0
- package/skills/setup-meerkat/assets/team/standard/turing/self-check.md +73 -0
- package/skills/setup-meerkat/assets/team/standard/turing/test-design-workflow.md +87 -0
- package/skills/setup-meerkat/assets/team/standard/turing/workflow.md +96 -0
- package/skills/setup-meerkat/evals/evals.json +127 -0
- package/skills/setup-meerkat/references/detection.md +94 -0
- package/skills/setup-meerkat/references/evals.md +96 -0
- package/skills/setup-meerkat/references/install.md +82 -0
- package/skills/setup-meerkat/references/matt-pocock.md +47 -0
- package/skills/setup-meerkat/references/roles.md +267 -0
- package/skills/setup-meerkat/scripts/configure-env.mjs +147 -0
- package/skills/setup-meerkat/scripts/detect.mjs +574 -0
- package/skills/setup-meerkat/scripts/install-roles.mjs +399 -0
- package/skills/setup-meerkat/scripts/lib/agent-kinds.mjs +126 -0
- package/skills/setup-meerkat/scripts/lib/atomic.mjs +20 -0
- package/skills/setup-meerkat/scripts/lib/entry-guard.mjs +22 -0
- package/skills/setup-meerkat/scripts/lib/env-merge.mjs +95 -0
- package/skills/setup-meerkat/scripts/lib/validate.mjs +293 -0
- package/src/cli/activity-stream.mjs +71 -0
- package/src/cli/argv.mjs +347 -0
- package/src/cli/commands/attachment.mjs +171 -0
- package/src/cli/commands/comment.mjs +77 -0
- package/src/cli/commands/dict.mjs +42 -0
- package/src/cli/commands/events.mjs +270 -0
- package/src/cli/commands/export.mjs +822 -0
- package/src/cli/commands/index.mjs +98 -0
- package/src/cli/commands/issue.mjs +670 -0
- package/src/cli/commands/labels.mjs +42 -0
- package/src/cli/commands/loop.mjs +119 -0
- package/src/cli/commands/project.mjs +339 -0
- package/src/cli/commands/relation.mjs +65 -0
- package/src/cli/commands/report.mjs +328 -0
- package/src/cli/commands/session.mjs +196 -0
- package/src/cli/commands/sla.mjs +95 -0
- package/src/cli/commands/status.mjs +125 -0
- package/src/cli/commands/task-input.mjs +251 -0
- package/src/cli/commands/token.mjs +43 -0
- package/src/cli/hub/client.mjs +9 -0
- package/src/cli/hub/runtime.mjs +34 -0
- package/src/cli/hub/server.mjs +1046 -0
- package/src/cli/hub/stream.mjs +168 -0
- package/src/cli/index.mjs +317 -0
- package/src/cli/output/human.mjs +53 -0
- package/src/cli/output/index.mjs +61 -0
- package/src/cli/output/json.mjs +39 -0
- package/src/cli/usage.mjs +104 -0
- package/src/cli/watch-core.mjs +210 -0
- package/src/core/README.md +122 -0
- package/src/core/bootstrap.mjs +238 -0
- package/src/core/commands/acceptance.mjs +339 -0
- package/src/core/commands/agent-sessions.mjs +114 -0
- package/src/core/commands/attachments.mjs +239 -0
- package/src/core/commands/comments.mjs +106 -0
- package/src/core/commands/context.mjs +102 -0
- package/src/core/commands/delivery-report.mjs +28 -0
- package/src/core/commands/dictionary.mjs +202 -0
- package/src/core/commands/index.mjs +136 -0
- package/src/core/commands/labels.mjs +210 -0
- package/src/core/commands/logging.mjs +92 -0
- package/src/core/commands/projects.mjs +324 -0
- package/src/core/commands/relations.mjs +178 -0
- package/src/core/commands/reports.mjs +318 -0
- package/src/core/commands/rollup.mjs +802 -0
- package/src/core/commands/sla.mjs +132 -0
- package/src/core/commands/tasks-input.mjs +295 -0
- package/src/core/commands/tasks.mjs +1952 -0
- package/src/core/commands/workflow.mjs +133 -0
- package/src/core/domain/acceptance-mode.mjs +320 -0
- package/src/core/domain/acceptance.mjs +285 -0
- package/src/core/domain/awaiting.mjs +243 -0
- package/src/core/domain/blocked-reason.mjs +78 -0
- package/src/core/domain/claim.mjs +332 -0
- package/src/core/domain/comment.mjs +162 -0
- package/src/core/domain/delivery-gate.mjs +252 -0
- package/src/core/domain/dictionary.mjs +147 -0
- package/src/core/domain/enums.mjs +317 -0
- package/src/core/domain/idem.mjs +87 -0
- package/src/core/domain/index.mjs +27 -0
- package/src/core/domain/invariants.mjs +103 -0
- package/src/core/domain/labels.mjs +166 -0
- package/src/core/domain/priority.mjs +80 -0
- package/src/core/domain/relation.mjs +470 -0
- package/src/core/domain/report.mjs +541 -0
- package/src/core/domain/reviewer.mjs +32 -0
- package/src/core/domain/status.mjs +405 -0
- package/src/core/domain/task.mjs +600 -0
- package/src/core/domain/workflow.mjs +1347 -0
- package/src/core/index.mjs +58 -0
- package/src/core/storage/driver.mjs +178 -0
- package/src/core/storage/md/export.mjs +339 -0
- package/src/core/storage/md/frontmatter.mjs +298 -0
- package/src/core/storage/md/sections.mjs +621 -0
- package/src/core/storage/migrations/0001_init.sql +760 -0
- package/src/core/storage/migrations-runner.mjs +286 -0
- package/src/core/storage/paths.mjs +61 -0
- package/src/core/storage/repositories/activities.mjs +82 -0
- package/src/core/storage/repositories/agent-sessions.mjs +230 -0
- package/src/core/storage/repositories/attachments.mjs +139 -0
- package/src/core/storage/repositories/comments.mjs +98 -0
- package/src/core/storage/repositories/dictionary.mjs +224 -0
- package/src/core/storage/repositories/index.mjs +49 -0
- package/src/core/storage/repositories/labels.mjs +218 -0
- package/src/core/storage/repositories/projects.mjs +263 -0
- package/src/core/storage/repositories/relations.mjs +275 -0
- package/src/core/storage/repositories/reports.mjs +131 -0
- package/src/core/storage/repositories/tasks.mjs +864 -0
- package/src/core/storage/schema.mjs +71 -0
- package/src/core/storage/secrets/runtime-pointer.mjs +298 -0
- package/src/core/storage/secrets/token-store.mjs +156 -0
- package/src/core/storage/sqlite-errors.mjs +269 -0
- package/src/core/storage/unit-of-work.mjs +207 -0
- package/src/core/storage/writer-lock.mjs +205 -0
- package/src/foundation/README.md +54 -0
- package/src/foundation/attachments.mjs +149 -0
- package/src/foundation/board-compat.mjs +163 -0
- package/src/foundation/card-brief.mjs +71 -0
- package/src/foundation/card-write.mjs +124 -0
- package/src/foundation/constants.mjs +742 -0
- package/src/foundation/daemon-state.mjs +124 -0
- package/src/foundation/deliver-hint.mjs +30 -0
- package/src/foundation/entry-guard.mjs +69 -0
- package/src/foundation/env-config.mjs +349 -0
- package/src/foundation/env-file.mjs +127 -0
- package/src/foundation/errors.mjs +492 -0
- package/src/foundation/hub-client.mjs +506 -0
- package/src/foundation/ids.mjs +178 -0
- package/src/foundation/log.mjs +475 -0
- package/src/foundation/loop-paths.mjs +123 -0
- package/src/foundation/node-version.mjs +62 -0
- package/src/foundation/norm.mjs +49 -0
- package/src/foundation/project-dir.mjs +333 -0
- package/src/foundation/project-order.mjs +122 -0
- package/src/foundation/redact.mjs +102 -0
- package/src/foundation/report-warning.mjs +34 -0
- package/src/foundation/review-identity.mjs +126 -0
- package/src/foundation/role-prompt.mjs +182 -0
- package/src/foundation/roles.mjs +362 -0
- package/src/foundation/runtime-locator.mjs +176 -0
- package/src/foundation/scheduling.mjs +927 -0
- package/src/foundation/sla-config.mjs +426 -0
- package/src/foundation/sla-patrol.mjs +1562 -0
- package/src/foundation/sse-parse.mjs +89 -0
- package/src/foundation/task-order.mjs +377 -0
- package/src/foundation/transport/actor.mjs +101 -0
- package/src/foundation/transport/autostart.mjs +255 -0
- package/src/foundation/transport/board-url.mjs +124 -0
- package/src/foundation/transport/client.mjs +115 -0
- package/src/foundation/transport/errors.mjs +82 -0
- package/src/foundation/transport/http.mjs +445 -0
- package/src/foundation/transport/runtime.mjs +313 -0
- package/src/foundation/transport/session.mjs +99 -0
- package/src/foundation/transport/token.mjs +147 -0
- package/src/foundation/wire.mjs +474 -0
- package/src/orchestrator/actor-kinds/claude.mjs +295 -0
- package/src/orchestrator/actor-kinds/codex.mjs +381 -0
- package/src/orchestrator/actor-kinds/pi.mjs +344 -0
- package/src/orchestrator/board.mjs +410 -0
- package/src/orchestrator/card-watch.mjs +170 -0
- package/src/orchestrator/compat.mjs +64 -0
- package/src/orchestrator/console.mjs +171 -0
- package/src/orchestrator/dispatch.mjs +167 -0
- package/src/orchestrator/kind-session.mjs +64 -0
- package/src/orchestrator/ledger.mjs +231 -0
- package/src/orchestrator/options.mjs +856 -0
- package/src/orchestrator/passes.mjs +675 -0
- package/src/orchestrator/questions.mjs +75 -0
- package/src/orchestrator/queue.mjs +480 -0
- package/src/orchestrator/runners.mjs +1102 -0
- package/src/orchestrator/runtime.mjs +613 -0
- package/src/orchestrator/session.mjs +1239 -0
- package/src/orchestrator/status.mjs +386 -0
- package/src/orchestrator/subscribe.mjs +530 -0
- package/src/orchestrator/supervisor.mjs +175 -0
- package/src/server/access-config.mjs +337 -0
- package/src/server/auth.mjs +140 -0
- package/src/server/cidr.mjs +186 -0
- package/src/server/index.mjs +900 -0
- package/src/server/main.mjs +277 -0
- package/src/server/requests.mjs +164 -0
- package/src/server/router.mjs +241 -0
- package/src/server/routes/access.mjs +101 -0
- package/src/server/routes/activities.mjs +110 -0
- package/src/server/routes/attachments.mjs +264 -0
- package/src/server/routes/comments.mjs +76 -0
- package/src/server/routes/dictionary.mjs +34 -0
- package/src/server/routes/export.mjs +59 -0
- package/src/server/routes/labels.mjs +31 -0
- package/src/server/routes/projects.mjs +166 -0
- package/src/server/routes/relations.mjs +56 -0
- package/src/server/routes/sessions.mjs +101 -0
- package/src/server/routes/sla.mjs +89 -0
- package/src/server/routes/tasks.mjs +512 -0
- package/src/server/routes/token.mjs +32 -0
- package/src/server/sse.mjs +277 -0
- package/src/server/static.mjs +167 -0
- package/src/server/task-view.mjs +60 -0
- package/web/README.md +92 -0
- package/web/dist/assets/index-CKCSE8J7.css +2 -0
- package/web/dist/assets/index-DiGy7Zlt.js +32 -0
- package/web/dist/favicon.svg +69 -0
- 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
|
-
#
|
|
1
|
+
# Meerkat TaskPanel
|
|
2
2
|
|
|
3
|
-
|
|
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
|
+

|
|
61
|
+
|
|
62
|
+

|
|
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).
|