@bragi-gmbh/codebus 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/bin/codebus.js +2 -0
  2. package/dist/binding-guard.js +97 -0
  3. package/dist/binding-guard.js.map +1 -0
  4. package/dist/client.js +94 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/commands/ack.js +47 -0
  7. package/dist/commands/ack.js.map +1 -0
  8. package/dist/commands/archive.js +21 -0
  9. package/dist/commands/archive.js.map +1 -0
  10. package/dist/commands/as.js +299 -0
  11. package/dist/commands/as.js.map +1 -0
  12. package/dist/commands/ask.js +189 -0
  13. package/dist/commands/ask.js.map +1 -0
  14. package/dist/commands/auth.js +33 -0
  15. package/dist/commands/auth.js.map +1 -0
  16. package/dist/commands/checkin.js +235 -0
  17. package/dist/commands/checkin.js.map +1 -0
  18. package/dist/commands/decision.js +52 -0
  19. package/dist/commands/decision.js.map +1 -0
  20. package/dist/commands/digest.js +117 -0
  21. package/dist/commands/digest.js.map +1 -0
  22. package/dist/commands/doctor.js +106 -0
  23. package/dist/commands/doctor.js.map +1 -0
  24. package/dist/commands/factory.js +191 -0
  25. package/dist/commands/factory.js.map +1 -0
  26. package/dist/commands/github-login.js +205 -0
  27. package/dist/commands/github-login.js.map +1 -0
  28. package/dist/commands/graph.js +88 -0
  29. package/dist/commands/graph.js.map +1 -0
  30. package/dist/commands/health.js +34 -0
  31. package/dist/commands/health.js.map +1 -0
  32. package/dist/commands/inbox.js +83 -0
  33. package/dist/commands/inbox.js.map +1 -0
  34. package/dist/commands/ingest.js +553 -0
  35. package/dist/commands/ingest.js.map +1 -0
  36. package/dist/commands/init.js +97 -0
  37. package/dist/commands/init.js.map +1 -0
  38. package/dist/commands/install.js +520 -0
  39. package/dist/commands/install.js.map +1 -0
  40. package/dist/commands/invite.js +152 -0
  41. package/dist/commands/invite.js.map +1 -0
  42. package/dist/commands/jira.js +237 -0
  43. package/dist/commands/jira.js.map +1 -0
  44. package/dist/commands/join.js +96 -0
  45. package/dist/commands/join.js.map +1 -0
  46. package/dist/commands/links.js +66 -0
  47. package/dist/commands/links.js.map +1 -0
  48. package/dist/commands/login.js +84 -0
  49. package/dist/commands/login.js.map +1 -0
  50. package/dist/commands/morning.js +121 -0
  51. package/dist/commands/morning.js.map +1 -0
  52. package/dist/commands/next.js +66 -0
  53. package/dist/commands/next.js.map +1 -0
  54. package/dist/commands/onboarding.js +109 -0
  55. package/dist/commands/onboarding.js.map +1 -0
  56. package/dist/commands/pack.js +276 -0
  57. package/dist/commands/pack.js.map +1 -0
  58. package/dist/commands/plan-gh.js +425 -0
  59. package/dist/commands/plan-gh.js.map +1 -0
  60. package/dist/commands/plan.js +465 -0
  61. package/dist/commands/plan.js.map +1 -0
  62. package/dist/commands/pr.js +88 -0
  63. package/dist/commands/pr.js.map +1 -0
  64. package/dist/commands/question.js +142 -0
  65. package/dist/commands/question.js.map +1 -0
  66. package/dist/commands/read.js +84 -0
  67. package/dist/commands/read.js.map +1 -0
  68. package/dist/commands/refs.js +357 -0
  69. package/dist/commands/refs.js.map +1 -0
  70. package/dist/commands/reply.js +38 -0
  71. package/dist/commands/reply.js.map +1 -0
  72. package/dist/commands/repo.js +1198 -0
  73. package/dist/commands/repo.js.map +1 -0
  74. package/dist/commands/report.js +41 -0
  75. package/dist/commands/report.js.map +1 -0
  76. package/dist/commands/resolve-refs.js +21 -0
  77. package/dist/commands/resolve-refs.js.map +1 -0
  78. package/dist/commands/resolve.js +93 -0
  79. package/dist/commands/resolve.js.map +1 -0
  80. package/dist/commands/send.js +168 -0
  81. package/dist/commands/send.js.map +1 -0
  82. package/dist/commands/sent.js +22 -0
  83. package/dist/commands/sent.js.map +1 -0
  84. package/dist/commands/session.js +426 -0
  85. package/dist/commands/session.js.map +1 -0
  86. package/dist/commands/statusline.js +43 -0
  87. package/dist/commands/statusline.js.map +1 -0
  88. package/dist/commands/task.js +140 -0
  89. package/dist/commands/task.js.map +1 -0
  90. package/dist/commands/tick.js +233 -0
  91. package/dist/commands/tick.js.map +1 -0
  92. package/dist/commands/upgrade.js +76 -0
  93. package/dist/commands/upgrade.js.map +1 -0
  94. package/dist/commands/watch.js +169 -0
  95. package/dist/commands/watch.js.map +1 -0
  96. package/dist/commands/whoami.js +27 -0
  97. package/dist/commands/whoami.js.map +1 -0
  98. package/dist/config.js +103 -0
  99. package/dist/config.js.map +1 -0
  100. package/dist/directives.js +102 -0
  101. package/dist/directives.js.map +1 -0
  102. package/dist/errors.js +110 -0
  103. package/dist/errors.js.map +1 -0
  104. package/dist/git-hooks.js +116 -0
  105. package/dist/git-hooks.js.map +1 -0
  106. package/dist/graph-bootstrap.js +95 -0
  107. package/dist/graph-bootstrap.js.map +1 -0
  108. package/dist/graph-remote.js +889 -0
  109. package/dist/graph-remote.js.map +1 -0
  110. package/dist/graph.js +335 -0
  111. package/dist/graph.js.map +1 -0
  112. package/dist/index.js +154 -0
  113. package/dist/index.js.map +1 -0
  114. package/dist/kit/graph-publish.mjs +400 -0
  115. package/dist/mail-latency.js +120 -0
  116. package/dist/mail-latency.js.map +1 -0
  117. package/dist/mcp-registry.js +859 -0
  118. package/dist/mcp-registry.js.map +1 -0
  119. package/dist/mcp.js +193 -0
  120. package/dist/mcp.js.map +1 -0
  121. package/dist/output.js +12 -0
  122. package/dist/output.js.map +1 -0
  123. package/dist/positioning.js +21 -0
  124. package/dist/positioning.js.map +1 -0
  125. package/dist/rolestore.js +89 -0
  126. package/dist/rolestore.js.map +1 -0
  127. package/dist/session.js +49 -0
  128. package/dist/session.js.map +1 -0
  129. package/dist/sessionstore.js +736 -0
  130. package/dist/sessionstore.js.map +1 -0
  131. package/dist/version-check.js +97 -0
  132. package/dist/version-check.js.map +1 -0
  133. package/package.json +47 -0
@@ -0,0 +1,189 @@
1
+ import { CodebusError } from "../errors.js";
2
+ import { rankByRelevance, formatNodeCitation, formatEdgeCitation, checkStaleness, isUsingFallbackSnapshot, isProseNode } from "../graph.js";
3
+ import { resolveGraphSource } from "../graph-remote.js";
4
+ /**
5
+ * Core ask logic shared by CLI and MCP.
6
+ * Returns a budgeted, cited answer over the graph.
7
+ *
8
+ * A6: routes through resolveGraphSource (local current wins unless an
9
+ * explicit `repo` names a different one -> remote -> last-good -> none).
10
+ * When no `repo` is given and a local graphify-out/ snapshot exists, this is
11
+ * BIT-IDENTICAL to the pre-A6 behavior and touches no network at all.
12
+ */
13
+ export async function askGraph(question, options = {}) {
14
+ const budgetTokens = options.budget ?? 500;
15
+ const repoRoot = options.repoRoot || process.cwd();
16
+ const resolved = await resolveGraphSource(question, { repo: options.repo, repoRoot });
17
+ const snapshot = resolved.snapshot;
18
+ if (!snapshot) {
19
+ return {
20
+ answer: "",
21
+ citations: [],
22
+ error: options.repo
23
+ ? `No local graphify-out/graph.json found, and no remote graph reachable for repo '${options.repo}'.`
24
+ : "No graphify-out/graph.json found. Run `graphify` or check the repo root.",
25
+ source: resolved.source,
26
+ };
27
+ }
28
+ const isRemote = resolved.source === "remote";
29
+ // Check if we're using a fallback (last-good) snapshot due to a failed build
30
+ const usingFallback = isRemote ? false : resolved.source === "last-good" || isUsingFallbackSnapshot(repoRoot);
31
+ // Check staleness: local checkStaleness for local/last-good sources; the
32
+ // remote leg already computed its own 3-state verdict via graph_status.
33
+ const staleness = isRemote
34
+ ? (resolved.staleness ?? { isStale: false, isDirty: false, unknown: true })
35
+ : await checkStaleness(snapshot, repoRoot, "dirty-only");
36
+ // Rank by relevance
37
+ const { nodes: rankedNodes, edges, matchCount: rankedMatchCount } = rankByRelevance(snapshot, question, 15);
38
+ // Remote-only: rankByRelevance drops score-0 matches (graph.ts), which would
39
+ // silently vanish a trigram-only graph_search hit that shares no literal
40
+ // substring with the query. Append any search hit missing from the ranked
41
+ // result rather than dropping it (Round-3 review finding 7's sibling
42
+ // concern for graph_search, same "never silently drop a real hit" rule).
43
+ let nodes = rankedNodes;
44
+ let matchCount = rankedMatchCount;
45
+ if (isRemote && resolved.searchHits && resolved.searchHits.length > 0) {
46
+ const present = new Set(rankedNodes.map((n) => n.id));
47
+ const missing = resolved.searchHits.filter((h) => !present.has(h.id));
48
+ if (missing.length > 0) {
49
+ nodes = [...rankedNodes, ...missing];
50
+ matchCount = rankedMatchCount + missing.length;
51
+ }
52
+ }
53
+ // [remote@sha7] citation markers: applied to every citation pushed below
54
+ // when the answer was built from a remote slice, so a reader can tell a
55
+ // remote-sourced citation apart from a local one at a glance.
56
+ const remoteMarker = isRemote && resolved.remoteSha7 ? ` [remote@${resolved.remoteSha7}]` : "";
57
+ const cite = (c) => c + remoteMarker;
58
+ // Build answer with budget tracking
59
+ let answer = "";
60
+ const citations = [];
61
+ let tokens = 0;
62
+ if (matchCount === 0) {
63
+ answer = `No results found for "${question}".`;
64
+ tokens += 10;
65
+ }
66
+ else {
67
+ // Add summary
68
+ const summary = `Found ${matchCount} relevant items in the graph:`;
69
+ answer = summary + "\n";
70
+ tokens += 5;
71
+ // Partition nodes into prose (docs/decisions) and code for distinct sections
72
+ const proseNodes = nodes.filter(isProseNode);
73
+ const codeNodes = nodes.filter((n) => !isProseNode(n));
74
+ // Add prose/doc nodes first under a dedicated section header
75
+ if (proseNodes.length > 0) {
76
+ answer += "\n## Docs & Decisions:\n";
77
+ tokens += 3;
78
+ for (const node of proseNodes) {
79
+ if (tokens >= budgetTokens * 0.85)
80
+ break;
81
+ const citation = cite(formatNodeCitation(node));
82
+ const line = `- ${node.label} (${citation})\n`;
83
+ answer += line;
84
+ citations.push(citation);
85
+ tokens += Math.ceil(line.split(/\s+/).length);
86
+ }
87
+ }
88
+ // Add code nodes
89
+ if (codeNodes.length > 0) {
90
+ answer += "\n## Files & Symbols:\n";
91
+ tokens += 3;
92
+ for (const node of codeNodes) {
93
+ if (tokens >= budgetTokens * 0.85)
94
+ break; // Leave 15% headroom
95
+ const citation = cite(formatNodeCitation(node));
96
+ const line = `- ${node.label} (${citation})\n`;
97
+ answer += line;
98
+ citations.push(citation);
99
+ tokens += Math.ceil(line.split(/\s+/).length);
100
+ }
101
+ }
102
+ // Add edges
103
+ if (edges.length > 0) {
104
+ answer += "\n## Contexts & Relationships:\n";
105
+ tokens += 3;
106
+ for (const edge of edges) {
107
+ if (tokens >= budgetTokens * 0.85)
108
+ break;
109
+ const citation = cite(formatEdgeCitation(edge));
110
+ const nodesList = edge.nodes.slice(0, 3).join(", ") + (edge.nodes.length > 3 ? "…" : "");
111
+ const line = `- ${edge.label}: ${nodesList} (${citation})\n`;
112
+ answer += line;
113
+ citations.push(citation);
114
+ tokens += Math.ceil(line.split(/\s+/).length);
115
+ }
116
+ }
117
+ // Truncate if over budget
118
+ if (tokens > budgetTokens) {
119
+ const lines = answer.split("\n");
120
+ answer = "";
121
+ tokens = 0;
122
+ for (const line of lines) {
123
+ const lineTokens = Math.ceil(line.split(/\s+/).length);
124
+ if (tokens + lineTokens <= budgetTokens) {
125
+ answer += line + "\n";
126
+ tokens += lineTokens;
127
+ }
128
+ }
129
+ answer += `\n[…truncated at ~${budgetTokens} tokens]`;
130
+ }
131
+ }
132
+ // Add staleness note if applicable.
133
+ // When git is unavailable, staleness is unknown — surface that explicitly rather than
134
+ // silently claiming the snapshot is fresh.
135
+ let stalenessNote;
136
+ if (usingFallback) {
137
+ stalenessNote = "(using last-good snapshot; build may have failed)";
138
+ }
139
+ else if (staleness.unknown) {
140
+ stalenessNote = isRemote ? "(staleness unknown: remote)" : "(staleness unknown: git unavailable)";
141
+ }
142
+ else if (staleness.note) {
143
+ stalenessNote = staleness.note;
144
+ }
145
+ // Round-3 review finding 7: graph_subgraph's `truncated` flag means the
146
+ // returned slice may be missing reachable nodes within the requested depth
147
+ // — surface it rather than silently trusting an incomplete traversal.
148
+ if (isRemote && resolved.truncated) {
149
+ const truncNote = "remote slice truncated — some reachable nodes may be missing";
150
+ stalenessNote = stalenessNote ? `${stalenessNote}; ${truncNote}` : `(${truncNote})`;
151
+ }
152
+ return { answer, citations, stalenessNote, source: resolved.source };
153
+ }
154
+ /**
155
+ * CLI command: codebus ask <question>
156
+ */
157
+ export async function askCmd(question, options) {
158
+ try {
159
+ const budget = options.budget ? parseInt(options.budget, 10) : 500;
160
+ const result = await askGraph(question, { budget, repoRoot: options.repoRoot, repo: options.repo });
161
+ if (result.error) {
162
+ throw new CodebusError(result.error, 1);
163
+ }
164
+ if (options.json) {
165
+ console.log(JSON.stringify(result, null, 2));
166
+ }
167
+ else {
168
+ console.log(result.answer);
169
+ if (result.stalenessNote) {
170
+ console.log(`\n[${result.stalenessNote}]`);
171
+ }
172
+ }
173
+ }
174
+ catch (err) {
175
+ if (err instanceof CodebusError)
176
+ throw err;
177
+ throw new CodebusError(`Failed to query graph: ${err instanceof Error ? err.message : String(err)}`, 1);
178
+ }
179
+ }
180
+ /**
181
+ * Register the ask command.
182
+ */
183
+ export function registerAsk(program, g) {
184
+ g(program.command("ask").argument("<question>", "question to ask the graph"))
185
+ .option("--budget <tokens>", "max output tokens (default 500)")
186
+ .option("--repo <slug>", "query a connected repo's remote graph instead of the local checkout")
187
+ .action((question, opts) => askCmd(question, opts));
188
+ }
189
+ //# sourceMappingURL=ask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.js","sourceRoot":"","sources":["../../src/commands/ask.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { readdir, rm } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { CACHE_DIR } from "../session.js";
4
+ import { DIGEST_FILE } from "./digest.js";
5
+ // Cache hygiene: cached session JWTs embed agent uuids, which die on any
6
+ // `supabase db reset` — the CLI then fails with "not a member" until the
7
+ // stale cache is cleared. `codebus auth reset` removes session caches;
8
+ // --all also drops the digest snapshot.
9
+ async function resetCmd(o) {
10
+ let removed = 0;
11
+ try {
12
+ for (const f of await readdir(CACHE_DIR)) {
13
+ if (/^session-[0-9a-f]{16}\.json$/.test(f)) {
14
+ await rm(join(CACHE_DIR, f), { force: true });
15
+ removed++;
16
+ }
17
+ }
18
+ }
19
+ catch {
20
+ // no cache dir yet — nothing to do
21
+ }
22
+ if (o.all) {
23
+ await rm(DIGEST_FILE, { force: true });
24
+ console.log(`cleared ${removed} session cache(s) + digest snapshot`);
25
+ return;
26
+ }
27
+ console.log(`cleared ${removed} session cache(s)`);
28
+ }
29
+ export function registerAuth(program, g) {
30
+ const auth = program.command("auth").description("session/auth utilities");
31
+ g(auth.command("reset")).option("--all", "also remove the digest snapshot").action(resetCmd);
32
+ }
33
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,yEAAyE;AACzE,yEAAyE;AACzE,uEAAuE;AACvE,wCAAwC;AACxC,KAAK,UAAU,QAAQ,CAAC,CAAoB;IAC1C,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,CAAC;QACH,KAAK,MAAM,CAAC,IAAI,MAAM,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YACzC,IAAI,8BAA8B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3C,MAAM,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC9C,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;IACrC,CAAC;IACD,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;QACV,MAAM,EAAE,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,qCAAqC,CAAC,CAAC;QACrE,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,mBAAmB,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAgB,EAAE,CAA0B;IACvE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,wBAAwB,CAAC,CAAC;IAC3E,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,iCAAiC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC/F,CAAC"}
@@ -0,0 +1,235 @@
1
+ import { resolveConfig } from "../config.js";
2
+ import { makeCtx } from "../client.js";
3
+ import { CodebusError } from "../errors.js";
4
+ import { loadRoles, saveRoles, rolesFile } from "./as.js";
5
+ import { startCmd } from "./session.js";
6
+ import { watchCmd } from "./watch.js";
7
+ import { recordSessionRole } from "../sessionstore.js";
8
+ import { stopHookInstalled, inClaudeCodeSession, codexHooksInstalled, inCodexSession, watchRecentlyArmed, MAIL_LATENCY_WARNING } from "../mail-latency.js";
9
+ // `codebus checkin <name>` — the one-line onboarding. Design brief:
10
+ // docs/checkin-design-brief.md. The author types this into any already-running
11
+ // agent session; from that moment the agent is addressable at <name> on the bus.
12
+ //
13
+ // What it does, in order:
14
+ // 1. authenticates as the AUTHOR using the machine's existing credential
15
+ // (config.json / env — the person-linked agent from `codebus login --github`),
16
+ // 2. calls checkin_role(<name>) — mints or rebinds a durable, author-owned
17
+ // principal named exactly what the author said (idempotent by name),
18
+ // 3. persists the returned token into the role store (~/.codebus/roles.json)
19
+ // and binds THIS SESSION (sessionstore.ts) to it,
20
+ // 4. re-runs session-start orientation AS the new identity, printing output
21
+ // written for the agent to read: who it is, its inbox, what's next, and
22
+ // how to participate.
23
+ //
24
+ // checkin does NOT bind the directory (owner decision §6.1, docs/plans/
25
+ // codebus-v2-reliability.md — reversed from the earlier design). A directory
26
+ // binding is now created ONLY by a deliberate `codebus as --bind`: checkin
27
+ // used to also claim the cwd's basename as an ambient default, which is
28
+ // exactly how a generic-but-real name ('CodeBus') or a decommissioned
29
+ // automation's leftover binding ends up silently handing an unrelated session
30
+ // somebody else's identity (FM-1/FM-7). Session-scoped identity plus an
31
+ // explicit opt-in for anything more durable is the whole fix.
32
+ //
33
+ // Failures surface loudly and verbatim — the competitor's worst failure class
34
+ // is agents that die silently (block/buzz issues #2265/#5500/#5495).
35
+ const PARTICIPATION = (slug) => [
36
+ "── How to participate (for the agent reading this) ─────────────────────────",
37
+ `You are '${slug}' on CodeBus, this workspace's coordination bus. Habits:`,
38
+ " • DURABLE AUTO-CHECK — Claude Code gets this for free via its Stop hook",
39
+ " (codebus install claude). Codex has its own native Stop hook too: run",
40
+ " `codebus install codex` ONCE to wire `codebus tick --hook` into",
41
+ " ~/.codex/hooks.json — after that, new mail surfaces automatically at",
42
+ " every Codex turn boundary (Codex feeds it back as your next prompt),",
43
+ " exactly like Claude Code. Without that install, fall back to:",
44
+ " • STANDING LOOP — whenever you are idle, run:",
45
+ " codebus watch --mine --first --timeout 280000",
46
+ " It blocks and exits the moment mail/work for you arrives (or quietly on",
47
+ " timeout). What it prints is a WORK ORDER, not a notification: read the",
48
+ " message, do what it asks in this session, and reply with the outcome —",
49
+ " never a bare acknowledgement. Then re-arm the loop.",
50
+ " • Between tasks and at natural pauses, check for work/mail:",
51
+ " codebus inbox (or MCP tool: codebus_inbox)",
52
+ " codebus next (or MCP tool: codebus_next)",
53
+ " • Read and reply (add --thread to walk a whole chain; --all to CC every",
54
+ " original recipient of a group send):",
55
+ " codebus read <id> [--thread] · codebus reply <id> --body \"...\" [--all]",
56
+ " • Mail that needed no reply but was actually handled: codebus ack <id>",
57
+ " • Check whether recipients read/handled what you sent: codebus sent",
58
+ " • Send to another agent or person:",
59
+ " codebus send --to <slug> --type note --body \"...\"",
60
+ " (add --headline/--required-action for a structured handover)",
61
+ " • Claim/finish work:",
62
+ " codebus task claim <id> · codebus task done <id> --evidence <ref>",
63
+ " • Record decisions / ask questions: codebus decision add · codebus question ask",
64
+ " • End your session with a handoff: codebus session end --summary \"...\"",
65
+ `Anyone on the bus can now reach you at '${slug}'.`,
66
+ "────────────────────────────────────────────────────────────────────────────",
67
+ ].join("\n");
68
+ async function checkinCmd(name, o) {
69
+ const cfg = resolveConfig({ ...o, noRoleBinding: true });
70
+ const ctx = await makeCtx(cfg);
71
+ // p_function_role only when given — the RPC validates against the 0043
72
+ // vocabulary and its error names the allowed values, so pass user input
73
+ // through verbatim rather than pre-validating a second list here.
74
+ const args = { p_name: name, p_adopt: !!o.adopt };
75
+ if (o.role)
76
+ args.p_function_role = o.role;
77
+ const { data, error } = await ctx.supabase.rpc("checkin_role", args);
78
+ if (error) {
79
+ // Server messages are written to be actionable; pass them through verbatim
80
+ // and add the one hint the server can't know (the CLI flag spelling).
81
+ const hint = error.message.includes("unowned legacy role")
82
+ ? `\n hint: re-run as: codebus checkin ${name} --adopt`
83
+ : error.message.includes("has no person_id")
84
+ ? `\n hint: this machine's credential is not person-linked — run: codebus login --github`
85
+ : "";
86
+ throw new CodebusError(`checkin failed: ${error.message}${hint}`);
87
+ }
88
+ const r = data;
89
+ // Persist into the same store `codebus as` uses — checkin and as are one system.
90
+ const store = loadRoles();
91
+ store.roles[r.agent_slug] = { token: r.token, agent: r.agent_slug, added_at: new Date().toISOString() };
92
+ saveRoles(store);
93
+ // THIS SESSION (durable env id when the host has one, else process
94
+ // ancestry — sessionstore.ts): multiple agents must share one repository
95
+ // (researcher/planner/coder/verifier on the same checkout), so identity
96
+ // binds to the running session, never to the directory. checkin does NOT
97
+ // touch ~/.codebus/roles.json's `bindings` — that's `codebus as --bind`'s
98
+ // job alone, deliberately, so a checkin can never silently displace (or be
99
+ // displaced by) another agent's directory default (observed live:
100
+ // codex-host-ingress silently stole legacy-android-host-app from
101
+ // claude-master-planner's open session; and separately, a checkin from
102
+ // /tmp once bound the literal pattern 'tmp' machine-wide).
103
+ const sessionKey = recordSessionRole(r.agent_slug);
104
+ const verb = r.created ? "created" : r.adopted ? "adopted" : "rebound (token rotated)";
105
+ console.log(`✓ ${r.agent_slug} ${verb} — you own this name; the token is stored in ${rolesFile()}`);
106
+ if (sessionKey) {
107
+ console.log(`✓ THIS session now acts as ${r.agent_slug} (other sessions, including other dirs' bindings, are unaffected)`);
108
+ }
109
+ else {
110
+ console.log(`⚠ could not read a durable session id or this session's process ancestry — identity did not bind. Re-run this checkin once that's fixed (doctor may help diagnose why).`);
111
+ }
112
+ console.log(` (to also make this directory's default identity ${r.agent_slug} for future sessions here: codebus as --bind ${r.agent_slug})`);
113
+ if (r.rotated && !r.adopted)
114
+ console.log(` note: any other session using the previous token for '${r.agent_slug}' must re-checkin.`);
115
+ if (o.json) {
116
+ console.log(JSON.stringify({ agent: r.agent_slug, created: r.created, adopted: r.adopted, rotated: r.rotated, session_bound: !!sessionKey }, null, 2));
117
+ return;
118
+ }
119
+ // Orient AS the new identity: same output as `codebus session start`, which
120
+ // includes the first-ever-session welcome. The token override unpins the
121
+ // author's file identity for this call only.
122
+ console.log("");
123
+ await startCmd({ url: cfg.url, anonKey: cfg.anonKey, workspace: cfg.workspace, token: r.token });
124
+ console.log(PARTICIPATION(r.agent_slug));
125
+ // Auto-arm the listener (owner ruling: checkin should start the monitor).
126
+ // Skipped whenever THIS session is live inside an actual agentic-tool turn
127
+ // (Claude Code or, as of RC3, Codex) — blocking for a watch window would
128
+ // stall that turn for nothing regardless of whether a Stop hook is wired
129
+ // up, since a blocked turn gets no chance to run ANY hook, real-time
130
+ // listener or otherwise, until it unblocks. Everywhere else (a plain
131
+ // shell, or a tool session neither of these two detectors recognizes),
132
+ // one watch window opens right here: the checkin line makes the agent
133
+ // live.
134
+ //
135
+ // Bug fix (found while investigating PR #54 CI failures on
136
+ // checkin-command-coverage.test.ts's watch-window branch-selection
137
+ // suite — confirmed via a bisect against 65a448a/origin/main that this
138
+ // predates both that PR and #53, so it is not a regression either
139
+ // introduced): this gating condition used to be `!hookAppliesHere`
140
+ // (`hookAppliesHere = (underClaudeCode && claudeHookOk) || (underCodex &&
141
+ // codexHookOk)`), which — despite the comment two paragraphs below
142
+ // ("Review MAJOR finding #5") already documenting that "a hook being
143
+ // INSTALLED is not the same as it being able to fire for THIS process" as
144
+ // a genuinely separate case from "not under the tool at all" — still
145
+ // routed BOTH cases into this same blocking branch: `hookAppliesHere` is
146
+ // false whenever the hook isn't installed, `!hookAppliesHere` is
147
+ // therefore true, and the code blocked exactly as if no tool were
148
+ // running at all. That contradicts the finding's own stated intent
149
+ // (never block inside a live tool turn, hook or not — the two cases
150
+ // differ only in WHICH message to print, not whether to block) and the
151
+ // dedicated non-blocking "mail latency unbounded" warning path in the
152
+ // `else` branch below existed but was UNREACHABLE for exactly the
153
+ // scenario it was written for. Fixed by gating on tool presence alone
154
+ // (`!underClaudeCode && !underCodex`); `hookAppliesHere` is still used
155
+ // below, but now purely to pick which message the non-blocking branch
156
+ // prints, never whether to enter it.
157
+ const underClaudeCode = inClaudeCodeSession();
158
+ const underCodex = inCodexSession();
159
+ const claudeHookOk = stopHookInstalled();
160
+ const codexHookOk = codexHooksInstalled();
161
+ const hookAppliesHere = (underClaudeCode && claudeHookOk) || (underCodex && codexHookOk);
162
+ const windowMs = parseInt(process.env.CODEBUS_WATCH_WINDOW_MS ?? "280000", 10);
163
+ if (o.watch !== false && !underClaudeCode && !underCodex) {
164
+ console.log("");
165
+ console.log(`listening for your mail now (${Math.round(windowMs / 1000)}s window; exits on first event — handle it, then re-arm with the standing loop):`);
166
+ // Review fix (Luna, PR #54 comment 3826518135): this branch requires
167
+ // `!underCodex` to even be entered (see the condition above), so a
168
+ // check for `underCodex && !codexHookOk` HERE can never be true — this
169
+ // used to be exactly that dead check, orphaned by the branch-selection
170
+ // fix earlier in this same PR (the fix moved the "never block inside a
171
+ // live Codex turn" decision out from under `hookAppliesHere`, but left
172
+ // this Codex-specific tip sitting in the branch it can no longer reach,
173
+ // silently dropping it for everyone rather than firing it for anyone).
174
+ // The genuine "under Codex, no hook" case now correctly lands in the
175
+ // `else` branch below instead (it never blocks) — the equivalent tip
176
+ // is given there.
177
+ await watchCmd({ url: cfg.url, anonKey: cfg.anonKey, workspace: cfg.workspace, token: r.token, mine: true, first: true, timeout: String(windowMs) });
178
+ }
179
+ else {
180
+ // Either a session already covered by a real turn-boundary hook (auto-arm
181
+ // skipped) or an explicit --no-watch. Review MAJOR finding #5: a hook
182
+ // being INSTALLED (machine-wide config) is not the same as it being able
183
+ // to fire for THIS process — Claude's only ever fires inside an actual
184
+ // Claude Code session, and Codex's only ever fires inside an actual Codex
185
+ // session (CODEX_THREAD_ID). A hook installed while this checkin runs
186
+ // under the OTHER tool, or a plain shell (--no-watch, say), cannot help
187
+ // this agent at all; require a recently-armed watch (scoped to this
188
+ // workspace) instead, and warn loudly if neither applies (delivery gap #8).
189
+ console.log("");
190
+ if (underClaudeCode && claudeHookOk) {
191
+ console.log("(Claude Code session: new mail is surfaced automatically at turn boundaries by the Stop hook — no listener needed.)");
192
+ }
193
+ else if (underCodex && codexHookOk) {
194
+ console.log("(Codex session: new mail is surfaced automatically at turn boundaries by Codex's own Stop hook (wired via `codebus install codex` into ~/.codex/hooks.json) — no listener needed. Like Claude Code's Stop hook, it feeds the reported mail back as your next prompt.)");
195
+ }
196
+ else {
197
+ const armed = await watchRecentlyArmed({
198
+ supabase: ctx.supabase, agentSlug: r.agent_slug, workspaceSlug: cfg.workspace, identitySource: ctx.identitySource,
199
+ });
200
+ if (armed) {
201
+ console.log("(--no-watch, and a watch window was recently armed for this workspace — mail latency stays bounded.)");
202
+ }
203
+ else if (underCodex && !codexHookOk) {
204
+ // Review fix (Luna, PR #54 comment 3826518135): the genuine "live
205
+ // Codex session, hook not installed" case — this branch is where it
206
+ // ACTUALLY lands now (it never blocks per the fix above), so the
207
+ // actionable, Codex-specific tip belongs here, not in the blocking
208
+ // branch it can no longer reach. Checked ahead of the two
209
+ // hook-installed-elsewhere cases below since underCodex is true
210
+ // here, making `codexHookOk && !underCodex` structurally impossible
211
+ // to also match for this same call.
212
+ console.log(`⚠ ${MAIL_LATENCY_WARNING} Run \`codebus install codex\` once to wire Codex's own Stop hook for durable auto-checking; otherwise keep re-arming \`codebus watch --mine --first\` by hand.`);
213
+ }
214
+ else if (claudeHookOk && !underClaudeCode) {
215
+ console.log(`⚠ a Claude Stop hook is installed, but this session is not running inside Claude Code, so it cannot fire for it. ${MAIL_LATENCY_WARNING}`);
216
+ }
217
+ else if (codexHookOk && !underCodex) {
218
+ console.log(`⚠ a Codex Stop hook is installed, but this session is not running inside Codex, so it cannot fire for it. ${MAIL_LATENCY_WARNING}`);
219
+ }
220
+ else {
221
+ console.log(`⚠ ${MAIL_LATENCY_WARNING}`);
222
+ }
223
+ }
224
+ }
225
+ }
226
+ export function registerCheckin(program, g) {
227
+ g(program.command("checkin"))
228
+ .description("one-line onboarding: mint/rebind an author-owned agent named <name> and orient it")
229
+ .argument("<name>", "the name this agent will be addressable at (you own it; idempotent)")
230
+ .option("--adopt", "take ownership of an existing unowned legacy role (rotates its token)")
231
+ .option("--role <function_role>", "functional role for routing (planner|builder|reviewer|consultant|researcher|router|monitor — docs/role-vocabulary.md)")
232
+ .option("--no-watch", "do not auto-arm the watch listener after checkin")
233
+ .action(checkinCmd);
234
+ }
235
+ //# sourceMappingURL=checkin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkin.js","sourceRoot":"","sources":["../../src/commands/checkin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { resolveConfig } from "../config.js";
2
+ import { makeCtx, workspaceId } from "../client.js";
3
+ import { render } from "../output.js";
4
+ import { CodebusError } from "../errors.js";
5
+ /**
6
+ * Shared core: create a decision.
7
+ * Exported for reuse in MCP tool.
8
+ */
9
+ export async function createDecisionCore(ctx, opts) {
10
+ const ws = await workspaceId(ctx);
11
+ const slug = opts.slug ?? opts.title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
12
+ const { data, error } = await ctx.supabase.from("decisions")
13
+ .insert({ workspace_id: ws, slug, title: opts.title, body: opts.body ?? null }).select().single();
14
+ if (error)
15
+ throw new CodebusError(error.message);
16
+ return { display_id: data.display_id, slug: data.slug, status: data.status, id: data.id };
17
+ }
18
+ /**
19
+ * Shared core: accept a decision.
20
+ * Exported for reuse in MCP tool.
21
+ */
22
+ export async function acceptDecisionCore(ctx, idOrDisplay) {
23
+ const isDisplay = /^CB-DEC-/i.test(idOrDisplay);
24
+ const sel = isDisplay ? "display_id" : "id";
25
+ const val = isDisplay ? idOrDisplay.toUpperCase() : idOrDisplay;
26
+ // display ids are only unique per workspace (bus_counters, 0004) — scope
27
+ // the display_id lookup, or a multi-workspace agent could accept the WRONG
28
+ // workspace's decision when two workspaces happen to share a display_id.
29
+ let q = ctx.supabase.from("decisions").update({ status: "accepted" }).eq(sel, val);
30
+ if (isDisplay)
31
+ q = q.eq("workspace_id", await workspaceId(ctx));
32
+ const { data, error } = await q.select().single();
33
+ if (error)
34
+ throw new CodebusError(`accept failed (owner-only): ${error.message}`);
35
+ return { display_id: data.display_id, status: data.status, id: data.id };
36
+ }
37
+ async function addDecision(o) {
38
+ const ctx = await makeCtx(resolveConfig(o));
39
+ const result = await createDecisionCore(ctx, { title: o.title, slug: o.slug, body: o.body });
40
+ console.log(render([{ display_id: result.display_id, slug: result.slug, status: result.status }], { json: !!o.json }));
41
+ }
42
+ async function acceptDecision(idOrDisplay, o) {
43
+ const ctx = await makeCtx(resolveConfig(o));
44
+ const result = await acceptDecisionCore(ctx, idOrDisplay);
45
+ console.log(render([{ display_id: result.display_id, status: result.status }], { json: !!o.json }));
46
+ }
47
+ export function registerDecision(program, g) {
48
+ const dec = program.command("decision").description("decision operations");
49
+ g(dec.command("add")).requiredOption("--title <t>").option("--slug <s>").option("--body <b>").action(addDecision);
50
+ g(dec.command("accept").argument("<id>")).action((id, o) => acceptDecision(id, o));
51
+ }
52
+ //# sourceMappingURL=decision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.js","sourceRoot":"","sources":["../../src/commands/decision.ts"],"names":[],"mappings":"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"}