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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trantor",
3
- "version": "0.17.76",
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": { "RELAY_URL": "http://127.0.0.1:4477", "RELAY_AGENT": "kimi-orch" },
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 universal adapter — DeepSeek, GLM,
359
- OpenRouter, and any provider you bring) are wired by `trantor connect` automatically (idempotent,
360
- backed-up, never overwrites your customizations). Anything else that speaks MCP: point it at
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
 
@@ -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 tests in 'testing', use 'failed' + a report if they break). 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.`;
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.76",
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
- "zod": "^4.4.3",
11
- "pg": "^8.22.0"
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
  }
@@ -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 project's tests/typecheck;
101
- `done` only green; `failed` (+ bus report) pulses red on the board until you bounce it.
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