trantor 0.17.76 → 0.17.78
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/plugin.json +1 -1
- package/README.md +35 -6
- package/bin/crew-runner.mjs +1 -1
- package/bin/slop-gate.mjs +48 -0
- package/package.json +7 -3
- package/skills/crew/SKILL.md +7 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trantor",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.78",
|
|
4
4
|
"description": "Trantor — the hub-world for AI agent crews: live message bus, presence, project Kanban/flow board + crew orchestration for independent AI coding agents (Claude, Codex, Gemini, Kimi, DeepSeek)",
|
|
5
5
|
"mcpServers": {
|
|
6
6
|
"relay": {
|
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ heartbeats, inbox delivery, handoff/baton pass, sub-agent cards):
|
|
|
51
51
|
"relay": {
|
|
52
52
|
"command": "node",
|
|
53
53
|
"args": ["<absolute-path-to-trantor>/mcp.mjs"],
|
|
54
|
-
"env": { "
|
|
54
|
+
"env": { "RELAY_AGENT": "kimi-orch" },
|
|
55
55
|
"startupTimeoutMs": 15000,
|
|
56
56
|
"toolTimeoutMs": 150000
|
|
57
57
|
}
|
|
@@ -62,6 +62,13 @@ heartbeats, inbox delivery, handoff/baton pass, sub-agent cards):
|
|
|
62
62
|
2. In the Kimi TUI: `/plugins install <absolute-path-to-trantor>` (or the GitHub URL), then
|
|
63
63
|
`/reload`, then start a new session.
|
|
64
64
|
|
|
65
|
+
Since 0.17.76 the Kimi hooks are a **dialect bridge**, not a fork: `kimi/bridge.mjs` runs the
|
|
66
|
+
canonical hooks as children and translates Kimi's input/output conventions at the edges
|
|
67
|
+
(SessionStart context is stashed and delivered on the first prompt). Kimi hooks therefore sign
|
|
68
|
+
their hub calls, follow per-project hub pins, and inherit every future hook fix automatically.
|
|
69
|
+
Do **not** set `RELAY_URL` in MCP configs — a hardcoded URL overrides the per-project pin and
|
|
70
|
+
splits the project across hubs; the pin decides the hub.
|
|
71
|
+
|
|
65
72
|
Notes: Kimi plugin installs are **snapshots** (`~/.kimi-code/plugins/managed/trantor/`) — after
|
|
66
73
|
updating trantor, re-run `/plugins install` to refresh the skills/hooks. The MCP entry above always
|
|
67
74
|
runs your live checkout, so the relay server itself never goes stale. Invoke the skills with
|
|
@@ -260,6 +267,24 @@ Every session registers automatically — **crew or not** — and a solo session
|
|
|
260
267
|
shows up on the board as cards, so the dashboard reflects *all* the work on a project, not just
|
|
261
268
|
crew runs.
|
|
262
269
|
|
|
270
|
+
## The board keeps itself honest
|
|
271
|
+
|
|
272
|
+
Cards carry their **story on the card**: every `note` lands in a permanent per-card log (last 40
|
|
273
|
+
entries) that survives restarts, retention, and id remaps — the drawer shows it as the card's
|
|
274
|
+
narrative, so clicking an old card tells you what actually happened, not a one-line status trail.
|
|
275
|
+
The `todo` lane has a lifecycle: cards untouched for 14 days (`RELAY_TODO_STALE_MS`) move to
|
|
276
|
+
STALE with an "aged out" note instead of rotting silently, and todo tiles wear an age badge from
|
|
277
|
+
day 7. A commit closes the session's focus card and the two link both ways. `trantor doctor`
|
|
278
|
+
cross-checks every hub you know about against the per-project pins and reports any **split-brain**
|
|
279
|
+
(a project live on two hubs) with the exact fix — and `trantor adopt <project>` migrates a project
|
|
280
|
+
between hubs in one verified step, telling stale sessions to restart.
|
|
281
|
+
|
|
282
|
+
Crew output is gated mechanically, too: `bin/slop-gate.mjs` runs the vendored
|
|
283
|
+
[anti-slop](https://github.com/dmmulroy/anti-slop) Oxlint rules over an agent's **changed files
|
|
284
|
+
only** — unexplained type assertions, `unknown` laundering, runtime `typeof`, Reflect tricks and
|
|
285
|
+
friends fail the card before it can reach done, while legacy debt burns down on its own card
|
|
286
|
+
instead of blocking everyone.
|
|
287
|
+
|
|
263
288
|
## The brain — plan-aware economics
|
|
264
289
|
|
|
265
290
|
Trantor's economics engine ([Scrooge](https://github.com/sashabogi/token-scrooge) — installed
|
|
@@ -326,8 +351,8 @@ rate, not work rate.
|
|
|
326
351
|
| `relay_send(to, text)` / `relay_inbox` / `relay_wait(t)` | Live messaging: direct, read-new, long-poll wake |
|
|
327
352
|
| `relay_peers` / `relay_status(text)` / `relay_whoami` | Presence: who's alive (honest, heartbeat-backed), doing what |
|
|
328
353
|
| `relay_project_brief(text)` | The project's what/why on the dashboard |
|
|
329
|
-
| `relay_task_add(title, …, difficulty, model, deps, project?)` | Cards with difficulty/model badges + DAG edges; `project` targets another board when you orchestrate from elsewhere |
|
|
330
|
-
| `relay_task_move(id, status)` | `todo → doing → testing → done` (the gate), `failed`, `blocked` |
|
|
354
|
+
| `relay_task_add(title, …, difficulty, model, deps, note?, project?)` | Cards with difficulty/model badges + DAG edges; `note` seeds the card's **permanent log**; `project` targets another board when you orchestrate from elsewhere |
|
|
355
|
+
| `relay_task_move(id, status, note?)` | `todo → doing → testing → done` (the gate), `failed`, `blocked` — moves to testing/done should carry a `note`: what you did + the evidence, stored on the card forever |
|
|
331
356
|
| `relay_board` | The project's full board, as text |
|
|
332
357
|
| `relay_scrooge(prompt, task?, difficulty?)` | Fractal cheap-model delegation, with the ledger receipt |
|
|
333
358
|
| `relay_lesson(text, scope?)` | Record a failure lesson — auto-injected into all future crews |
|
|
@@ -338,6 +363,7 @@ rate, not work rate.
|
|
|
338
363
|
```
|
|
339
364
|
trantor setup | doctor | connect | profile | provider | models
|
|
340
365
|
| up <agents…> | swap <old> <new> | down | ui | advise | hub | watch
|
|
366
|
+
| adopt <project> | reconcile | duty | orchestrate | patrol | app | backfill | init-hooks
|
|
341
367
|
```
|
|
342
368
|
|
|
343
369
|
- **`trantor provider`** — `list` every crew seat (built-in + brought) with availability + tier ·
|
|
@@ -355,9 +381,12 @@ trantor setup | doctor | connect | profile | provider | models
|
|
|
355
381
|
|
|
356
382
|
## Works with any MCP agent
|
|
357
383
|
|
|
358
|
-
Claude Code, Codex CLI, Kimi Code CLI, and **OpenCode** (the
|
|
359
|
-
OpenRouter, and any provider you bring) are wired by
|
|
360
|
-
backed-up, never overwrites your customizations).
|
|
384
|
+
Claude Code, Codex CLI, Kimi Code CLI, **DeepSeek Harness (`dsh`)**, and **OpenCode** (the
|
|
385
|
+
universal adapter — DeepSeek, GLM, OpenRouter, and any provider you bring) are wired by
|
|
386
|
+
`trantor connect` automatically (idempotent, backed-up, never overwrites your customizations).
|
|
387
|
+
For `dsh`, connect builds a full profile (`~/.dsh/profiles/trantor`): DeepSeek's own Claude Code
|
|
388
|
+
hooks bridge running the trantor hooks, plus their MCP client running the relay server — then
|
|
389
|
+
`trantor up dsh` runs it as a crew seat (fresh session per turn; uses `DEEPSEEK_API_KEY`). Anything else that speaks MCP: point it at
|
|
361
390
|
`mcp.mjs` with `RELAY_AGENT=<brand>` — loading the server auto-registers the session, so presence
|
|
362
391
|
works before the model says a word.
|
|
363
392
|
|
package/bin/crew-runner.mjs
CHANGED
|
@@ -161,7 +161,7 @@ if (!CLI[AGENT]) log(`'${AGENT}' is not a built-in seat — running it as an ope
|
|
|
161
161
|
|
|
162
162
|
// RUNNER_RULES / RUNNER_KICKOFF env overrides: the runner is also the substrate for non-crew
|
|
163
163
|
// always-on seats (the fleet DUTY agent, bin/duty.mjs) whose doctrine is not "work your card".
|
|
164
|
-
const RULES = process.env.RUNNER_RULES || `Rules: you are ${SESSION} on the trantor crew. Before starting a card, query the board for related PAST cards and lessons (relay_board — 1900+ cards of tribal knowledge; prior work may already answer half of it). Work your assigned file(s), report on the bus (relay_send, <280 chars), move your Kanban card as you go (doing -> testing -> done; run the
|
|
164
|
+
const RULES = process.env.RUNNER_RULES || `Rules: you are ${SESSION} on the trantor crew. Before starting a card, query the board for related PAST cards and lessons (relay_board — 1900+ cards of tribal knowledge; prior work may already answer half of it). Work your assigned file(s), report on the bus (relay_send, <280 chars), move your Kanban card as you go with a NOTE saying what you did (doing -> testing -> done; in 'testing' run YOUR OWN test file — never the full npm test, suites collide across seats — plus \`node bin/slop-gate.mjs\` when the repo has one: it lints ONLY your changed files against the anti-slop rules, and a card must not reach done with slop-gate failing; use 'failed' + a report if anything breaks). If you need something from another session, message THAT SESSION (relay_peers to find its id, relay_send to reach it) — never ask the human to pass it along; carrying messages between agents is the job this bus exists to remove. When your work for THIS message is finished, END YOUR TURN — do NOT park, do NOT loop relay_wait; the runner waits for you and will wake you with the next message.`;
|
|
165
165
|
|
|
166
166
|
// ---- the pulse (Scape's Lloyd/Argus loop, Trantor-shaped) --------------------
|
|
167
167
|
// A message-driven seat is DEAF between messages. An orchestrator seat with a mission needs a
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// trantor slop-gate — the anti-slop lint, scoped to YOUR CHANGES.
|
|
3
|
+
//
|
|
4
|
+
// node bin/slop-gate.mjs # lint changed + untracked lintable files (the crew gate)
|
|
5
|
+
// node bin/slop-gate.mjs --all # lint the whole configured surface (advisory audit)
|
|
6
|
+
//
|
|
7
|
+
// The rules are the vendored dmmulroy/anti-slop set (tools/oxlint/anti-slop — ours to tune):
|
|
8
|
+
// they mechanically reject low-evidence AI patterns — unexplained type assertions, unknown
|
|
9
|
+
// laundering, runtime typeof instead of boundary decoding, Reflect tricks, module mocking.
|
|
10
|
+
// Diff-scoped ON PURPOSE: the legacy surface carries known debt (carded), and a gate that fails
|
|
11
|
+
// on code you didn't touch teaches agents to ignore the gate. New work meets the bar; old debt
|
|
12
|
+
// burns down on its own card. Stock eslint warnings stay ADVISORY — only anti-slop errors gate.
|
|
13
|
+
import { execSync, spawnSync } from "node:child_process";
|
|
14
|
+
|
|
15
|
+
const ALL = process.argv.includes("--all");
|
|
16
|
+
const LINTABLE = /\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/;
|
|
17
|
+
|
|
18
|
+
function sh(cmd) {
|
|
19
|
+
try { return execSync(cmd, { encoding: "utf8", maxBuffer: 16 * 1024 * 1024 }).trim(); }
|
|
20
|
+
catch { return ""; }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let args;
|
|
24
|
+
if (ALL) {
|
|
25
|
+
args = ["."];
|
|
26
|
+
} else {
|
|
27
|
+
const changed = sh("git diff --name-only HEAD");
|
|
28
|
+
const untracked = sh("git ls-files --others --exclude-standard");
|
|
29
|
+
const files = [...new Set([...changed.split("\n"), ...untracked.split("\n")])]
|
|
30
|
+
.filter(f => f && LINTABLE.test(f));
|
|
31
|
+
if (!files.length) { console.log("slop-gate: no lintable changes — pass."); process.exit(0); }
|
|
32
|
+
args = files;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// oxlint applies oxlint.config.ts ignorePatterns even to explicitly-passed files (verified), so
|
|
36
|
+
// excluded legacy files (hub.mjs, mcp.mjs) stay excluded here too.
|
|
37
|
+
const r = spawnSync("npx", ["oxlint", ...args], { encoding: "utf8", maxBuffer: 16 * 1024 * 1024 });
|
|
38
|
+
const out = (r.stdout || "") + (r.stderr || "");
|
|
39
|
+
const hits = out.split("\n").filter(l => /error\s+anti-slop\(/.test(l));
|
|
40
|
+
|
|
41
|
+
if (hits.length) {
|
|
42
|
+
console.log(hits.join("\n"));
|
|
43
|
+
console.log(`\nslop-gate: ${hits.length} anti-slop error(s) in your changes — fix them (or state the SAFETY invariant) before moving the card to testing.`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
const warnings = out.split("\n").filter(l => /\bwarning\b/.test(l)).length;
|
|
47
|
+
console.log(`slop-gate: clean${warnings ? ` (${warnings} advisory warning(s) — not gating)` : ""}.`);
|
|
48
|
+
process.exit(0);
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trantor",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.78",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"trantor": "bin/cli.mjs"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"pg": "^8.22.0",
|
|
11
|
+
"zod": "^4.4.3"
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
14
|
"test": "node test.mjs && node test-scenarios.mjs && node test-failure.mjs && node test-redelivery.mjs && node test-handoff.mjs && node test-agents.mjs && node test-update.mjs && node test-handoff-guard.mjs && node test-balances.mjs && node test-subagent-cost.mjs && node test-inbox.mjs && node test-inflight.mjs && node test-notify.mjs && node test-focus.mjs && node test-cardlog.mjs && node test-relay-note.mjs && node test-reaper.mjs && node test-events.mjs && node test-proposals.mjs && node test-scrub.mjs && node test-store-delta.mjs && node test-claims.mjs && node test-adopt.mjs && node test-summarize.mjs && node test-identity-core.mjs && node test-identity.mjs && node test-identity-instances.mjs && node test-duty.mjs && node test-discovery.mjs && node test-doctor.mjs && node test-splitbrain.mjs && node test-overseer.mjs && node test-overseer-lib.mjs && node test-overseer-warn.mjs && node test-provider-keys.mjs && node test-inbox-delivery.mjs && node test-hub-routing.mjs && node test-hook-routing.mjs && node test-relay-wait.mjs && node test-dsh-seat.mjs && node test-kimi-bridge.mjs && node test-kimi-events.mjs && python3 engine/test-routing.py && node test-reconcile.mjs && node test-resources.mjs && node test-patrol.mjs && node test-bridge.mjs && bash test-crew.sh"
|
|
@@ -53,5 +53,9 @@
|
|
|
53
53
|
"license": "MIT",
|
|
54
54
|
"engines": {
|
|
55
55
|
"node": ">=18"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@oxlint/plugins": "^1.79.0",
|
|
59
|
+
"oxlint": "^1.79.0"
|
|
56
60
|
}
|
|
57
61
|
}
|
package/skills/crew/SKILL.md
CHANGED
|
@@ -51,6 +51,7 @@ EXACT launch spec per provider (do not improvise these):
|
|
|
51
51
|
| DeepSeek | `deepseek:deepseek` | runs via opencode; `deepseek` alone = CLI default |
|
|
52
52
|
| **GLM (Z.ai)** | **`glm:zai-coding-plan`** | **runs via opencode, NOT a bare `glm`/`zai` terminal command.** `glm:zai-coding-plan/glm-5.2` pins a model; `glm:zai-coding-plan` live-selects. (Legacy `opencode:zai-coding-plan` still works.) |
|
|
53
53
|
| **OpenRouter (BYOM)** | **`openrouter`** | **the bring-your-own-model on-ramp — one key fronts hundreds of vendors (incl. ones with no CLI).** Bare `openrouter` live-selects the best OpenRouter model for the difficulty; pin one with `openrouter:openrouter/<vendor>/<model>`. Its own bus identity `openrouter:<project>` (never collides with the GLM `opencode` seat). |
|
|
54
|
+
| **DeepSeek Harness** | **`dsh`** | DeepSeek's own open-source harness as a seat (API-billed via `DEEPSEEK_API_KEY`). `trantor connect` builds its profile (their CC-hooks bridge running trantor's hooks + their MCP client running the relay). **Fresh session per turn — no resume** — so the seat relies on the wake prompt + the board, not conversation memory; give it self-contained contracts. |
|
|
54
55
|
|
|
55
56
|
`agent:provider` live-selects the best model now; `agent:provider/model` pins one. Example:
|
|
56
57
|
`trantor up codex kimi deepseek:deepseek glm:zai-coding-plan --task code --difficulty hard`.
|
|
@@ -97,8 +98,12 @@ Loop until the board is done — you are a foreman, not a mailbox:
|
|
|
97
98
|
they auto-inject into every future crew's prompts.
|
|
98
99
|
|
|
99
100
|
## Phase 5 — verification gate + integration
|
|
100
|
-
Card flow is `todo → doing → testing → done`; `testing` runs the
|
|
101
|
-
|
|
101
|
+
Card flow is `todo → doing → testing → done`; `testing` runs the seat's OWN test file (never the
|
|
102
|
+
full suite from a seat — suites spawn hubs on fixed ports and collide across seats; the
|
|
103
|
+
orchestrator runs the full suite at integration) plus `node bin/slop-gate.mjs` where the repo has
|
|
104
|
+
one (the anti-slop lint over the seat's changed files — a card must not reach done failing it);
|
|
105
|
+
`done` only green, and moves to testing/done carry a `note` with the evidence — the note is the
|
|
106
|
+
card's permanent story; `failed` (+ bus report) pulses red on the board until you bounce it.
|
|
102
107
|
Enforce the gate — bounce anything that skipped it (bounces are visible: "↩ bounced" on the
|
|
103
108
|
card, history in its tooltip). When all report done: integrate, fix contract mismatches
|
|
104
109
|
YOURSELF, move your card through testing → done, broadcast "🚀 <thing> is live", and when the
|