@pitboss/cli 0.4.6 → 0.4.7

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/dist/cli.js CHANGED
@@ -20889,9 +20889,11 @@ Find the default branch with \`git remote show origin\`.
20889
20889
  issue as the spec; the order's \`feature\` text, when it says more than "Resolve the GitHub issue",
20890
20890
  narrows or adds to it. Put \`Closes #<n>\` (the issue number) in the PR body so the merge closes it.
20891
20891
  2. Create the branch and PR:
20892
- \`git fetch origin && git checkout -B order/<orderId> origin/<default>\`,
20893
- \`git commit --allow-empty -m "Start order <orderId>"\`, \`git push -u origin order/<orderId>\`,
20892
+ \`git fetch origin && git checkout --detach origin/<default>\`,
20893
+ \`git commit --allow-empty -m "Start order <orderId>"\`, \`git push origin HEAD:refs/heads/order/<orderId>\`,
20894
20894
  then \`gh pr create --draft --base <default> --head order/<orderId> --title "<feature>" --body "Order <orderId>"\`.
20895
+ Work detached and never check out \`order/<orderId>\` as a local branch: every agent's worktree
20896
+ shares one repository, and git lets only one worktree hold a branch.
20895
20897
  Record both with \`mcp__relai__update_order\` (\`branch\`, \`prUrl\`).
20896
20898
  3. Build tasks: \`mcp__relai__create_task\` for each piece of work, with \`epicId\` = the order's
20897
20899
  \`epicId\`, \`assignedTo: "@auto"\`, and
@@ -20929,9 +20931,9 @@ Find the default branch with \`git remote show origin\`.
20929
20931
  reject with exactly what to change.
20930
20932
 
20931
20933
  **orderRole "build"**:
20932
- - \`git fetch origin && git checkout -B order/<orderId> origin/order/<orderId>\`, then implement,
20933
- test and commit. Do not create another branch or PR.
20934
- - Push with \`git pull --rebase origin order/<orderId> && git push origin HEAD:order/<orderId>\`,
20934
+ - \`git fetch origin && git checkout --detach origin/order/<orderId>\`, then implement, test and commit
20935
+ on the detached head. Do not create a local branch, another branch on the remote, or a PR.
20936
+ - Push with \`git fetch origin && git rebase origin/order/<orderId> && git push origin HEAD:order/<orderId>\`,
20935
20937
  repeating up to 5 times if the push is rejected. Never force-push.
20936
20938
  - If you drop or change any part of what the goal asked for, even for a good reason, record each one
20937
20939
  with \`mcp__relai__update_task_status\` metadata \`deviations: [{ "item": "<what the goal asked>",
@@ -20948,7 +20950,9 @@ Find the default branch with \`git remote show origin\`.
20948
20950
  on deviations in the approval gate.
20949
20951
 
20950
20952
  **orderRole "merge"**:
20951
- 1. \`gh pr ready <prUrl>\`, then \`gh pr checks <prUrl> --watch --fail-fast\`.
20953
+ 1. \`gh pr ready <prUrl>\`, then \`gh pr checks <prUrl> --watch --fail-fast\`. If the PR has no checks
20954
+ (the repo has no CI), check out the PR head and run the repo's own lint, typecheck and test scripts
20955
+ from its package manifest instead, and treat a failure there as a failed check.
20952
20956
  Before merging, replace the PR body with a run report built from
20953
20957
  \`mcp__relai__list_all_tasks\` filtered to the order's Epic: the feature, the workflow
20954
20958
  (planning, build, gates, merge), each task with its assignee, status, and created and
@@ -281,9 +281,11 @@ Find the default branch with \`git remote show origin\`.
281
281
  issue as the spec; the order's \`feature\` text, when it says more than "Resolve the GitHub issue",
282
282
  narrows or adds to it. Put \`Closes #<n>\` (the issue number) in the PR body so the merge closes it.
283
283
  2. Create the branch and PR:
284
- \`git fetch origin && git checkout -B order/<orderId> origin/<default>\`,
285
- \`git commit --allow-empty -m "Start order <orderId>"\`, \`git push -u origin order/<orderId>\`,
284
+ \`git fetch origin && git checkout --detach origin/<default>\`,
285
+ \`git commit --allow-empty -m "Start order <orderId>"\`, \`git push origin HEAD:refs/heads/order/<orderId>\`,
286
286
  then \`gh pr create --draft --base <default> --head order/<orderId> --title "<feature>" --body "Order <orderId>"\`.
287
+ Work detached and never check out \`order/<orderId>\` as a local branch: every agent's worktree
288
+ shares one repository, and git lets only one worktree hold a branch.
287
289
  Record both with \`mcp__relai__update_order\` (\`branch\`, \`prUrl\`).
288
290
  3. Build tasks: \`mcp__relai__create_task\` for each piece of work, with \`epicId\` = the order's
289
291
  \`epicId\`, \`assignedTo: "@auto"\`, and
@@ -321,9 +323,9 @@ Find the default branch with \`git remote show origin\`.
321
323
  reject with exactly what to change.
322
324
 
323
325
  **orderRole "build"**:
324
- - \`git fetch origin && git checkout -B order/<orderId> origin/order/<orderId>\`, then implement,
325
- test and commit. Do not create another branch or PR.
326
- - Push with \`git pull --rebase origin order/<orderId> && git push origin HEAD:order/<orderId>\`,
326
+ - \`git fetch origin && git checkout --detach origin/order/<orderId>\`, then implement, test and commit
327
+ on the detached head. Do not create a local branch, another branch on the remote, or a PR.
328
+ - Push with \`git fetch origin && git rebase origin/order/<orderId> && git push origin HEAD:order/<orderId>\`,
327
329
  repeating up to 5 times if the push is rejected. Never force-push.
328
330
  - If you drop or change any part of what the goal asked for, even for a good reason, record each one
329
331
  with \`mcp__relai__update_task_status\` metadata \`deviations: [{ "item": "<what the goal asked>",
@@ -340,7 +342,9 @@ Find the default branch with \`git remote show origin\`.
340
342
  on deviations in the approval gate.
341
343
 
342
344
  **orderRole "merge"**:
343
- 1. \`gh pr ready <prUrl>\`, then \`gh pr checks <prUrl> --watch --fail-fast\`.
345
+ 1. \`gh pr ready <prUrl>\`, then \`gh pr checks <prUrl> --watch --fail-fast\`. If the PR has no checks
346
+ (the repo has no CI), check out the PR head and run the repo's own lint, typecheck and test scripts
347
+ from its package manifest instead, and treat a failure there as a failed check.
344
348
  Before merging, replace the PR body with a run report built from
345
349
  \`mcp__relai__list_all_tasks\` filtered to the order's Epic: the feature, the workflow
346
350
  (planning, build, gates, merge), each task with its assignee, status, and created and
package/dist/mcp.js CHANGED
@@ -13238,21 +13238,42 @@ ${version.body}`
13238
13238
  ] : []
13239
13239
  ];
13240
13240
  }
13241
+ var ATTENTION_STATUSES = "blocked,pending_verification,proposed";
13242
+ function attentionMaxAgeDays() {
13243
+ const n = Number(process.env.ATTENTION_MAX_AGE_DAYS);
13244
+ return Number.isFinite(n) && n > 0 ? n : 7;
13245
+ }
13246
+ var attentionWindowSchema = {
13247
+ includeStale: external_exports.boolean().optional().describe("Include items untouched for longer than maxAgeDays. Off by default so new asks lead."),
13248
+ maxAgeDays: external_exports.number().positive().optional().describe("Hide items untouched for longer than this many days (default 7).")
13249
+ };
13250
+ function attentionCutoff(input) {
13251
+ if (input.includeStale) return void 0;
13252
+ return new Date(Date.now() - (input.maxAgeDays ?? attentionMaxAgeDays()) * 864e5).toISOString();
13253
+ }
13254
+ async function staleAttentionCount(client, cutoff) {
13255
+ if (!cutoff) return 0;
13256
+ const { meta } = await client.getTasksPage({ status: ATTENTION_STATUSES, updatedBefore: cutoff, limit: 1, clip: true });
13257
+ return meta?.total ?? 0;
13258
+ }
13241
13259
  function buildGodCoordinationTools(client) {
13242
13260
  return [
13243
13261
  {
13244
13262
  name: "list_attention",
13245
- description: "List what needs attention across ALL your owner's repos: tasks that are 'blocked' (a worker is waiting), 'pending_verification' (awaiting a review decision), or 'proposed' (a worker's task awaiting commit), plus idle workers that cannot take the ready work that is sitting there (idle_unroutable \u2014 derived now, not from the event log). Each task carries its repoId. A blocked task with metadata.blockedThreadId resumes when you answer with send_message on that thread, as if the owner had. One without it (stalled or overflowed work, or your own task) needs reassigning with assign_task or splitting instead. An idle_unroutable item names the agent and why each task is ineligible (domain, specialization, review_gate, for-human, product-decision, pinned, blockedBy). Capped and clipped, newest first; read one in full with get_task.",
13246
- inputSchema: external_exports.object({}),
13247
- handler: async () => {
13263
+ description: "List what needs attention across ALL your owner's repos: tasks that are 'blocked' (a worker is waiting), 'pending_verification' (awaiting a review decision), or 'proposed' (a worker's task awaiting commit), plus idle workers that cannot take the ready work that is sitting there (idle_unroutable \u2014 derived now, not from the event log). Each task carries its repoId. A blocked task with metadata.blockedThreadId resumes when you answer with send_message (type decision) on that thread, as if the owner had, when the owner has given you a decide delegation for that repo; the task records clearedBy. Answer only reversible, branch-level confirmations yourself (editing, pushing or deleting files on an order branch, choosing between plan options). Merges into a default branch, deploys, deletes outside an order branch, and anything touching credentials or money go to the owner. One without it (stalled or overflowed work, or your own task) needs reassigning with assign_task or splitting instead. An idle_unroutable item names the agent and why each task is ineligible (domain, specialization, review_gate, for-human, product-decision, pinned, blockedBy). Capped and clipped, newest first; read one in full with get_task.",
13264
+ inputSchema: external_exports.object(attentionWindowSchema),
13265
+ handler: async (input) => {
13266
+ const cutoff = attentionCutoff(input);
13248
13267
  const [{ data, meta }, idleUnroutable] = await Promise.all([
13249
13268
  client.getTasksPage({
13250
- status: "blocked,pending_verification,proposed",
13269
+ status: ATTENTION_STATUSES,
13251
13270
  limit: listTasksLimit(),
13252
- clip: true
13271
+ clip: true,
13272
+ ...cutoff ? { updatedAfter: cutoff } : {}
13253
13273
  }),
13254
13274
  client.getIdleUnroutable()
13255
13275
  ]);
13276
+ const staleCount = await staleAttentionCount(client, cutoff);
13256
13277
  const tasks = data ?? [];
13257
13278
  const idle = idleUnroutable ?? [];
13258
13279
  const total = meta?.total ?? tasks.length;
@@ -13260,11 +13281,12 @@ function buildGodCoordinationTools(client) {
13260
13281
  return {
13261
13282
  content: [{
13262
13283
  type: "text",
13263
- text: tasks.length === 0 && idle.length === 0 ? "Nothing needs attention across your repos right now." : JSON.stringify({
13284
+ text: tasks.length === 0 && idle.length === 0 && staleCount === 0 ? "Nothing needs attention across your repos right now." : JSON.stringify({
13264
13285
  tasks,
13265
13286
  taskCount: total,
13266
13287
  ...idle.length > 0 ? { idleUnroutable: idle } : {},
13267
13288
  ...notShown ? { notShown } : {},
13289
+ ...staleCount > 0 ? { staleCount, stale: `${staleCount} older items hidden; pass includeStale: true to see them, and cancel or archive what is dead.` } : {},
13268
13290
  peerBoundary: PEER_BOUNDARY
13269
13291
  }, null, 2)
13270
13292
  }]
@@ -13536,19 +13558,22 @@ function buildOperatorTools(client, ownerId) {
13536
13558
  {
13537
13559
  name: "list_attention",
13538
13560
  description: "List everything across ALL your projects that needs you right now: tasks that are 'blocked' (a worker is waiting on your input), 'pending_verification' (awaiting a review decision), or 'proposed' (a worker's task awaiting your commit), plus idle workers that cannot take the ready work sitting there (idle_unroutable). Call this first to see what to act on. Each task carries its repoId and, for blocked tasks, metadata.blockedThreadId \u2014 the thread to post a reply on (via reply_human) to resume the worker. An idle_unroutable item names the agent and why each task is ineligible.",
13539
- inputSchema: external_exports.object({}),
13540
- handler: async () => {
13541
- const [tasks, idleUnroutable] = await Promise.all([
13542
- client.getTasks({ status: "blocked,pending_verification,proposed" }),
13543
- client.getIdleUnroutable()
13561
+ inputSchema: external_exports.object(attentionWindowSchema),
13562
+ handler: async (input) => {
13563
+ const cutoff = attentionCutoff(input);
13564
+ const [tasks, idleUnroutable, staleCount] = await Promise.all([
13565
+ client.getTasks({ status: ATTENTION_STATUSES, ...cutoff ? { updatedAfter: cutoff } : {} }),
13566
+ client.getIdleUnroutable(),
13567
+ staleAttentionCount(client, cutoff)
13544
13568
  ]);
13545
13569
  const idle = idleUnroutable ?? [];
13546
13570
  return {
13547
13571
  content: [{
13548
13572
  type: "text",
13549
- text: tasks.length === 0 && idle.length === 0 ? "Nothing needs your attention across your projects right now." : JSON.stringify({
13573
+ text: tasks.length === 0 && idle.length === 0 && staleCount === 0 ? "Nothing needs your attention across your projects right now." : JSON.stringify({
13550
13574
  tasks,
13551
- ...idle.length > 0 ? { idleUnroutable: idle } : {}
13575
+ ...idle.length > 0 ? { idleUnroutable: idle } : {},
13576
+ ...staleCount > 0 ? { staleCount, stale: `${staleCount} older items hidden; pass includeStale: true to see them, and cancel or archive what is dead.` } : {}
13552
13577
  }, null, 2)
13553
13578
  }]
13554
13579
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pitboss/cli",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
4
  "private": false,
5
5
  "description": "Connect your coding agents to a pitboss instance",
6
6
  "keywords": [